diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index 12e4dd6159cb..864fd36756ec 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -1125,6 +1125,8 @@ class CConfig { string caseName; /*!< \brief Name of the current case */ + unsigned long edgeColorGroupSize; /*!< \brief Size of the edge groups colored for OpenMP parallelization of edge loops. */ + unsigned short Kind_InletInterpolationFunction; /*!brief type of spanwise interpolation function to use for the inlet face. */ unsigned short Kind_Inlet_InterpolationType; /*!brief type of spanwise interpolation data to use for the inlet face. */ bool PrintInlet_InterpolatedData; /*!brief option for printing the interpolated data file. */ @@ -4251,7 +4253,7 @@ class CConfig { * \brief Get whether to "Use Accurate Jacobians" for AUSM+up(2) and SLAU(2). * \return yes/no. */ - bool GetUse_Accurate_Jacobians(void) { return Use_Accurate_Jacobians; } + bool GetUse_Accurate_Jacobians(void) const { return Use_Accurate_Jacobians; } /*! * \brief Get the kind of integration scheme (explicit or implicit) @@ -4454,7 +4456,7 @@ class CConfig { * \brief Factor by which to multiply the dissipation contribution to Jacobians of central schemes. * \return The factor. */ - su2double GetCent_Jac_Fix_Factor(void) { return Cent_Jac_Fix_Factor; } + su2double GetCent_Jac_Fix_Factor(void) const { return Cent_Jac_Fix_Factor; } /*! * \brief Get the kind of integration scheme (explicit or implicit) @@ -5833,7 +5835,7 @@ class CConfig { * \brief Get a pointer to the body force vector. * \return A pointer to the body force vector. */ - su2double* GetBody_Force_Vector(void) { return Body_Force_Vector; } + const su2double* GetBody_Force_Vector(void) const { return Body_Force_Vector; } /*! * \brief Get information about the rotational frame. @@ -8491,7 +8493,7 @@ class CConfig { * \param[in] val_coeff - Index of the coefficient. * \return Alpha coefficient for the Runge-Kutta integration scheme. */ - su2double* Get_Electric_Field_Dir(void) { return Electric_Field_Dir; } + const su2double* Get_Electric_Field_Dir(void) const { return Electric_Field_Dir; } /*! * \brief Check if the user wants to apply the load as a ramp. @@ -8712,28 +8714,27 @@ class CConfig { */ su2double GetRadialBasisFunctionParameter(void) const { return RadialBasisFunction_Parameter; } - /*! - * \brief Get information about using UQ methodology - * \return TRUE means that UQ methodology of eigenspace perturbation will be used - */ - bool GetUsing_UQ(void) const { return using_uq; } - /*! * \brief Get the kind of inlet face interpolation function to use. */ inline unsigned short GetKindInletInterpolationFunction(void) const {return Kind_InletInterpolationFunction;} - - /*! + /*! * \brief Get the kind of inlet face interpolation data type. */ inline unsigned short GetKindInletInterpolationType (void) const {return Kind_Inlet_InterpolationType;} - /*! + /*! * \brief Get whether to print inlet interpolated data or not. */ bool GetPrintInlet_InterpolatedData(void) const { return PrintInlet_InterpolatedData;} + /*! + * \brief Get information about using UQ methodology + * \return TRUE means that UQ methodology of eigenspace perturbation will be used + */ + bool GetUsing_UQ(void) const { return using_uq; } + /*! * \brief Get the amount of eigenvalue perturbation to be done * \return Value of the uq_delta_b parameter @@ -9221,4 +9222,9 @@ class CConfig { */ unsigned long GetLinear_Solver_Prec_Threads(void) const { return Linear_Solver_Prec_Threads; } + /*! + * \brief Get the size of the edge groups colored for OpenMP parallelization of edge loops. + */ + unsigned long GetEdgeColoringGroupSize(void) const { return edgeColorGroupSize; } + }; diff --git a/Common/include/interpolation_structure.hpp b/Common/include/interpolation_structure.hpp index ba03bed85b65..1d29a85dd5e2 100644 --- a/Common/include/interpolation_structure.hpp +++ b/Common/include/interpolation_structure.hpp @@ -1,7 +1,7 @@ /*! * \file interpolation_structure.hpp - * \brief Headers of the main subroutines used by SU2_FSI. - * The subroutines and functions are in the interpolation_structure.cpp file. + * \brief Headers of classes used for multiphysics interpolation. + * The implementation is in the interpolation_structure.cpp file. * \author H. Kline * \version 7.0.1 "Blackbird" * @@ -244,7 +244,7 @@ class CIsoparametric : public CInterpolator { * \param[in] nDim - the dimension of the coordinates. * \param[in] iZone_1 - zone index of the element to use for interpolation (the DONOR zone) * \param[in] donor_elem - element index of the element to use for interpolation (or global index of a point in 2D) - * \param[in[ nDonorPoints - number of donor points in the element. + * \param[in] nDonorPoints - number of donor points in the element. * \param[in] xj - point projected onto the plane of the donor element. * \param[out] isoparams - isoparametric coefficients. Must be allocated to size nNodes ahead of time. (size> nDonors) * diff --git a/Common/include/linear_algebra/CSysMatrix.hpp b/Common/include/linear_algebra/CSysMatrix.hpp index 01bb9041d0ea..be91dcab6865 100644 --- a/Common/include/linear_algebra/CSysMatrix.hpp +++ b/Common/include/linear_algebra/CSysMatrix.hpp @@ -95,6 +95,7 @@ class CSysMatrix { const unsigned long *row_ptr; /*!< \brief Pointers to the first element in each row. */ const unsigned long *dia_ptr; /*!< \brief Pointers to the diagonal element in each row. */ const unsigned long *col_ind; /*!< \brief Column index for each of the elements in val(). */ + vector col_ptr;/*!< \brief The transpose of col_ind, pointer to blocks with the same column index. */ ScalarType *ILU_matrix; /*!< \brief Entries of the ILU sparse matrix. */ unsigned long nnz_ilu; /*!< \brief Number of possible nonzero entries in the matrix (ILU). */ @@ -440,7 +441,7 @@ class CSysMatrix { * \param[in] val_block - Block to set to A(i, j). */ template - inline void SetBlock(unsigned long block_i, unsigned long block_j, OtherType **val_block) { + inline void SetBlock(unsigned long block_i, unsigned long block_j, const OtherType* const* val_block) { unsigned long iVar, jVar, index; @@ -503,7 +504,7 @@ class CSysMatrix { * \param[in] val_block - Block to add to A(i, j). */ template - inline void AddBlock(unsigned long block_i, unsigned long block_j, OtherType **val_block) { + inline void AddBlock(unsigned long block_i, unsigned long block_j, const OtherType* const* val_block) { unsigned long iVar, jVar, index; @@ -524,7 +525,7 @@ class CSysMatrix { * \param[in] val_block - Block to subtract to A(i, j). */ template - inline void SubtractBlock(unsigned long block_i, unsigned long block_j, OtherType **val_block) { + inline void SubtractBlock(unsigned long block_i, unsigned long block_j, const OtherType* const* val_block) { unsigned long iVar, jVar, index; @@ -550,7 +551,7 @@ class CSysMatrix { */ template inline void UpdateBlocks(unsigned long iEdge, unsigned long iPoint, unsigned long jPoint, - OtherType **block_i, OtherType **block_j) { + const OtherType* const* block_i, const OtherType* const* block_j) { ScalarType *bii = &matrix[dia_ptr[iPoint]*nVar*nEqn]; ScalarType *bjj = &matrix[dia_ptr[jPoint]*nVar*nEqn]; @@ -570,6 +571,84 @@ class CSysMatrix { } } + /*! + * \brief Short-hand for the "subtractive" version (sub from i* add to j*) of UpdateBlocks. + */ + template + inline void UpdateBlocksSub(unsigned long iEdge, unsigned long iPoint, unsigned long jPoint, + const OtherType* const* block_i, const OtherType* const* block_j) { + UpdateBlocks(iEdge, iPoint, jPoint, block_i, block_j); + } + + /*! + * \brief Update 2 blocks ij and ji (add to i* sub from j*). + * \note The template parameter Sign, can be used create a "subtractive" + * update i.e. subtract from row i and add to row j instead. + * \param[in] edge - Index of edge that connects iPoint and jPoint. + * \param[in] block_i - Subs from ji. + * \param[in] block_j - Adds to ij. + */ + template + inline void UpdateBlocks(unsigned long iEdge, const OtherType* const* block_i, const OtherType* const* block_j) { + + ScalarType *bij = &matrix[edge_ptr(iEdge,0)*nVar*nEqn]; + ScalarType *bji = &matrix[edge_ptr(iEdge,1)*nVar*nEqn]; + + unsigned long iVar, jVar, offset = 0; + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nEqn; jVar++) { + bij[offset] += PassiveAssign(block_j[iVar][jVar]) * Sign; + bji[offset] -= PassiveAssign(block_i[iVar][jVar]) * Sign; + ++offset; + } + } + } + + /*! + * \brief Short-hand for the "subtractive" version (sub from i* add to j*) of UpdateBlocks. + */ + template + inline void UpdateBlocksSub(unsigned long iEdge, const OtherType* const* block_i, const OtherType* const* block_j) { + UpdateBlocks(iEdge, block_i, block_j); + } + + /*! + * \brief Adds the specified block to the (i, i) subblock of the matrix-by-blocks structure. + * \param[in] block_i - Diagonal index. + * \param[in] val_block - Block to add to the diagonal of the matrix. + */ + template + inline void AddBlock2Diag(unsigned long block_i, const OtherType* const* val_block) { + + ScalarType *bii = &matrix[dia_ptr[block_i]*nVar*nEqn]; + + unsigned long iVar, jVar, offset = 0; + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nEqn; jVar++) + bii[offset++] += PassiveAssign(val_block[iVar][jVar]); + + } + + /*! + * \brief Subtracts the specified block from the (i, i) subblock of the matrix-by-blocks structure. + * \param[in] block_i - Diagonal index. + * \param[in] val_block - Block to subtract from the diagonal of the matrix. + */ + template + inline void SubtractBlock2Diag(unsigned long block_i, const OtherType* const* val_block) { + + ScalarType *bii = &matrix[dia_ptr[block_i]*nVar*nEqn]; + + unsigned long iVar, jVar, offset = 0; + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nEqn; jVar++) + bii[offset++] -= PassiveAssign(val_block[iVar][jVar]); + + } + /*! * \brief Adds the specified value to the diagonal of the (i, i) subblock * of the matrix-by-blocks structure. @@ -616,6 +695,11 @@ class CSysMatrix { template void EnforceSolutionAtNode(const unsigned long node_i, const OtherType *x_i, CSysVector & b); + /*! + * \brief Sets the diagonal entries of the matrix as the sum of the blocks in the corresponding column. + */ + void SetDiagonalAsColumnSum(); + /*! * \brief Add a scaled sparse matrix to "this" (axpy-type operation, A = A+alpha*B). * \note Matrices must have the same sparse pattern. diff --git a/Common/include/linear_algebra/CSysSolve.hpp b/Common/include/linear_algebra/CSysSolve.hpp index 20f480bf4f0d..4922064507f7 100644 --- a/Common/include/linear_algebra/CSysSolve.hpp +++ b/Common/include/linear_algebra/CSysSolve.hpp @@ -57,6 +57,10 @@ using namespace std; * creating CSysSolve objects we can more easily assign different * matrix-vector products and preconditioners to different problems * that may arise in a hierarchical solver (i.e. multigrid). + * + * The methods of this class are designed to be called by multiple OpenMP threads. + * Beware of writes to class member variables, for example "Residual" should only + * be modified by one thread. */ template class CSysSolve { diff --git a/Common/include/linear_algebra/CSysVector.hpp b/Common/include/linear_algebra/CSysVector.hpp index 7f59b23055f4..d55759d67244 100644 --- a/Common/include/linear_algebra/CSysVector.hpp +++ b/Common/include/linear_algebra/CSysVector.hpp @@ -59,7 +59,7 @@ class CSysVector { * \brief Generic initialization from a scalar or array. * \note If val==nullptr vec_val is not initialized, only allocated. * \param[in] numBlk - number of blocks locally - * \param[in] numBlkDomain - number of blocks locally (without g cells) + * \param[in] numBlkDomain - number of blocks locally (without ghost cells) * \param[in] numVar - number of variables in each block * \param[in] val - default value for elements * \param[in] valIsArray - if true val is treated as array @@ -360,7 +360,11 @@ class CSysVector { * \param[in] val_var - inde of the residual to be set. * \return Value of the residual. */ - inline ScalarType GetBlock(unsigned long val_ipoint, unsigned long val_var) const { + inline const ScalarType& operator() (unsigned long val_ipoint, unsigned long val_var) const { + return vec_val[val_ipoint*nVar+val_var]; + } + inline ScalarType& operator() (unsigned long val_ipoint, unsigned long val_var) { return vec_val[val_ipoint*nVar+val_var]; } + }; diff --git a/Common/include/omp_structure.hpp b/Common/include/omp_structure.hpp index 671297487138..a619d5711333 100644 --- a/Common/include/omp_structure.hpp +++ b/Common/include/omp_structure.hpp @@ -38,6 +38,8 @@ #pragma once +#include + #if defined(_MSC_VER) #define PRAGMIZE(X) __pragma(X) #else @@ -45,8 +47,8 @@ #endif /*--- Detect compilation with OpenMP support, protect agaisnt - * using OpenMP with AD (not supported yet). ---*/ -#if defined(_OPENMP) && !defined(CODI_REVERSE_TYPE) && !defined(CODI_FORWARD_TYPE) + * using OpenMP with Reverse AD (not supported yet). ---*/ +#if defined(_OPENMP) && !defined(CODI_REVERSE_TYPE) #define HAVE_OMP #include @@ -84,7 +86,9 @@ inline constexpr int omp_get_thread_num(void) {return 0;} #define SU2_OMP_SIMD SU2_OMP(simd) #define SU2_OMP_MASTER SU2_OMP(master) +#define SU2_OMP_ATOMIC SU2_OMP(atomic) #define SU2_OMP_BARRIER SU2_OMP(barrier) +#define SU2_OMP_CRITICAL SU2_OMP(critical) #define SU2_OMP_PARALLEL SU2_OMP(parallel) #define SU2_OMP_PARALLEL_(ARGS) SU2_OMP(parallel ARGS) @@ -122,3 +126,49 @@ inline size_t computeStaticChunkSize(size_t totalWork, return roundUpDiv(workPerThread, chunksPerThread); } +/*! + * \brief Copy data from one array-like object to another in parallel. + * \param[in] size - Number of elements. + * \param[in] src - Source array. + * \param[in] dst - Destination array. + */ +template +void parallelCopy(size_t size, const T* src, U* dst) +{ + SU2_OMP_FOR_STAT(4196) + for(size_t i=0; i +void parallelSet(size_t size, T val, U* dst) +{ + SU2_OMP_FOR_STAT(4196) + for(size_t i=0; i::value,bool>::type = 0> +inline void atomicAdd(T rhs, T& lhs) +{ + SU2_OMP_CRITICAL + lhs += rhs; +} +template::value,bool>::type = 0> +inline void atomicAdd(T rhs, T& lhs) +{ + SU2_OMP_ATOMIC + lhs += rhs; +} diff --git a/Common/include/toolboxes/C1DInterpolation.hpp b/Common/include/toolboxes/C1DInterpolation.hpp index 348a9dddefa4..703f208ea86e 100644 --- a/Common/include/toolboxes/C1DInterpolation.hpp +++ b/Common/include/toolboxes/C1DInterpolation.hpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -38,130 +38,131 @@ using namespace std; class C1DInterpolation{ protected: - bool Point_Match = false; /*!< \brief to make sure all points from the inlet data match the vertex coordinates */ - vector X; /*!< \brief x for inlet data */ - vector Data; /*!< \brief f(x) for inlet data */ + bool Point_Match = false; /*!< \brief to make sure all points from the inlet data match the vertex coordinates */ + vector X; /*!< \brief x for inlet data */ + vector Data; /*!< \brief f(x) for inlet data */ public: - /*! - * \brief Virtual destructor of the C1DInterpolation class. - */ - virtual ~C1DInterpolation() = default; - - /*! - * \brief virtual method for setting the cofficients for the respective spline spline. - * \param[in] X - the x values. - * \param[in] Data - the f(x) values. - */ - virtual void SetSpline(const vector &X, const vector &Data){} - - /*! - * \brief virtual method for evaluating the value of the respective Spline. - * \param[in] Point_Interp - the point where interpolation value is required. - * \returns the interpolated value. - */ - virtual su2double EvaluateSpline(su2double Point_Interp){return 0;} - - /*! - * \brief bool variable to make sure all vertex points fell in range of the inlet data. - * \returns the bool variable. - */ - bool GetPointMatch() const {return Point_Match;} + /*! + * \brief Virtual destructor of the C1DInterpolation class. + */ + virtual ~C1DInterpolation() = default; + + /*! + * \brief virtual method for setting the cofficients for the respective spline spline. + * \param[in] X - the x values. + * \param[in] Data - the f(x) values. + */ + virtual void SetSpline(const vector &X, const vector &Data){} + + /*! + * \brief virtual method for evaluating the value of the respective Spline. + * \param[in] Point_Interp - the point where interpolation value is required. + * \returns the interpolated value. + */ + virtual su2double EvaluateSpline(su2double Point_Interp){return 0;} + + /*! + * \brief bool variable to make sure all vertex points fell in range of the inlet data. + * \returns the bool variable. + */ + bool GetPointMatch() const {return Point_Match;} }; -class CAkimaInterpolation final: public C1DInterpolation{ +class CAkimaInterpolation final: public C1DInterpolation{ private: - vector x,y,b,c,d; /*!< \brief local variables for Akima spline cooefficients */ - int n; /*!< \brief local variable for holding the size of the vector */ + vector x,y,b,c,d; /*!< \brief local variables for Akima spline cooefficients */ + int n; /*!< \brief local variable for holding the size of the vector */ + public: - - /*! - * \brief Constructor of the CAkimaInterpolation class. - * \param[in] X - the x values. - * \param[in] Data - the f(x) values. - */ - CAkimaInterpolation(vector &X, vector &Data){ - SetSpline(X,Data); - } - - /*! - * \brief Destructor of the CAkimaInterpolation class. - */ - ~CAkimaInterpolation(){} - - /*! - * \brief for setting the cofficients for the Akima spline. - * \param[in] X - the x values. - * \param[in] Data - the f(x) values. - */ - void SetSpline(const vector &X, const vector &Data) override; - - /*! - * \brief For evaluating the value of Akima Spline. - * \param[in] Point_Interp - the point where interpolation value is required. - * \returns the interpolated value. - */ - su2double EvaluateSpline(su2double Point_Interp) override; + /*! + * \brief Constructor of the CAkimaInterpolation class. + * \param[in] X - the x values. + * \param[in] Data - the f(x) values. + */ + CAkimaInterpolation(vector &X, vector &Data){ + SetSpline(X,Data); + } + + /*! + * \brief Destructor of the CAkimaInterpolation class. + */ + ~CAkimaInterpolation(){} + + /*! + * \brief for setting the cofficients for the Akima spline. + * \param[in] X - the x values. + * \param[in] Data - the f(x) values. + */ + void SetSpline(const vector &X, const vector &Data) override; + + /*! + * \brief For evaluating the value of Akima Spline. + * \param[in] Point_Interp - the point where interpolation value is required. + * \returns the interpolated value. + */ + su2double EvaluateSpline(su2double Point_Interp) override; }; class CLinearInterpolation final: public C1DInterpolation{ - private: - vector x,y,dydx; /*!< \brief local variables for linear 'spline' cooefficients */ - int n; /*!< \brief local variable for holding the size of the vector */ - public: - - /*! - * \brief Constructor of the CLinearInterpolation class. - * \param[in] X - the x values. - * \param[in] Data - the f(x) values. - */ - CLinearInterpolation(vector &X, vector &Data){ - SetSpline(X,Data); - } - - /*! - * \brief Destructor of the CInletInterpolation class. - */ - ~CLinearInterpolation(){} - - /*! - * \brief for setting the cofficients for Linear 'spline'. - * \param[in] X - the x values. - * \param[in] Data - the f(x) values. - */ - void SetSpline(const vector &X, const vector &Data) override; - - /*! - * \brief For evaluating the value for Linear 'spline'. - * \param[in] Point_Interp - the point where interpolation value is required. - * \returns the interpolated value. - */ - su2double EvaluateSpline(su2double Point_Interp) override; +private: + vector x,y,dydx; /*!< \brief local variables for linear 'spline' cooefficients */ + int n; /*!< \brief local variable for holding the size of the vector */ + +public: + /*! + * \brief Constructor of the CLinearInterpolation class. + * \param[in] X - the x values. + * \param[in] Data - the f(x) values. + */ + CLinearInterpolation(vector &X, vector &Data){ + SetSpline(X,Data); + } + + /*! + * \brief Destructor of the CInletInterpolation class. + */ + ~CLinearInterpolation(){} + + /*! + * \brief for setting the cofficients for Linear 'spline'. + * \param[in] X - the x values. + * \param[in] Data - the f(x) values. + */ + void SetSpline(const vector &X, const vector &Data) override; + + /*! + * \brief For evaluating the value for Linear 'spline'. + * \param[in] Point_Interp - the point where interpolation value is required. + * \returns the interpolated value. + */ + su2double EvaluateSpline(su2double Point_Interp) override; }; /*! -* \brief to correct for interpolation type. -* \param[in] Inlet_Interpolated - the interpolated data after spline evaluation. -* \param[in] Theta - the angle of the vertex (in xy plane). -* \param[in] nDim - the dimensions of the case. -* \param[in] Coord - the coordinates of the vertex. -* \param[in] nVar_Turb - the number of turbulence variables as defined by turbulence model -* \param[in] ENUM_INLET_INTERPOLATIONTYPE - enum of the interpolation type to be done -* \returns the corrected Inlet Interpolated Data. -*/ -vector CorrectedInletValues(const vector &Inlet_Interpolated, - su2double Theta , - unsigned short nDim, - su2double *Coord, - unsigned short nVar_Turb, - ENUM_INLET_INTERPOLATIONTYPE Interpolation_Type); + * \brief to correct for interpolation type. + * \param[in] Inlet_Interpolated - the interpolated data after spline evaluation. + * \param[in] Theta - the angle of the vertex (in xy plane). + * \param[in] nDim - the dimensions of the case. + * \param[in] Coord - the coordinates of the vertex. + * \param[in] nVar_Turb - the number of turbulence variables as defined by turbulence model + * \param[in] ENUM_INLET_INTERPOLATIONTYPE - enum of the interpolation type to be done + * \returns the corrected Inlet Interpolated Data. + */ +vector CorrectedInletValues(const vector &Inlet_Interpolated, + su2double Theta , + unsigned short nDim, + const su2double *Coord, + unsigned short nVar_Turb, + ENUM_INLET_INTERPOLATIONTYPE Interpolation_Type); /*! -* \brief to print the Inlet Interpolated Data -* \param[in] Inlet_Interpolated_Interpolated - the final vector for the interpolated data -* \param[in] Marker - name of the inlet marker -* \param[in] nVertex - total number of vertexes. -* \param[in] nDim - the dimensions of the problem. -* \param[in] nColumns - the number of columns in the final interpolated data -*/ -void PrintInletInterpolatedData(const vector& Inlet_Data_Interpolated, string Marker, unsigned long nVertex, unsigned short nDim, unsigned short nColumns); + * \brief to print the Inlet Interpolated Data + * \param[in] Inlet_Interpolated_Interpolated - the final vector for the interpolated data + * \param[in] Marker - name of the inlet marker + * \param[in] nVertex - total number of vertexes. + * \param[in] nDim - the dimensions of the problem. + * \param[in] nColumns - the number of columns in the final interpolated data + */ +void PrintInletInterpolatedData(const vector& Inlet_Data_Interpolated, string Marker, + unsigned long nVertex, unsigned short nDim, unsigned short nColumns); diff --git a/Common/include/toolboxes/MMS/CIncTGVSolution.hpp b/Common/include/toolboxes/MMS/CIncTGVSolution.hpp index b4655b7844e1..d38e3b937050 100644 --- a/Common/include/toolboxes/MMS/CIncTGVSolution.hpp +++ b/Common/include/toolboxes/MMS/CIncTGVSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -31,32 +31,32 @@ #include #include "CVerificationSolution.hpp" - + /*! * \class CIncTGVSolution * \brief Class to define the required data for the incompressible Taylor Green Vortex. * \author T. Economon, E. van der Weide */ -class CIncTGVSolution: public CVerificationSolution { - +class CIncTGVSolution final: public CVerificationSolution { + protected: - + /*--- TGV specific conditions. ---*/ - + su2double tgvLength; /*!< \brief Taylor-Green length scale. */ su2double tgvVelocity; /*!< \brief Taylor-Green velocity. */ su2double tgvDensity; /*!< \brief Taylor-Green density. */ su2double tgvViscosity; /*!< \brief Taylor-Green viscosity. */ - + su2double Temperature; /*!< \brief Temperature, just to be safe. */ - + public: - + /*! * \brief Constructor of the class. */ CIncTGVSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -68,12 +68,12 @@ class CIncTGVSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ ~CIncTGVSolution(void); - + /*! * \brief Get the exact solution at the current position and time. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -82,8 +82,8 @@ class CIncTGVSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); - + su2double *val_solution) const override; + /*! * \brief Get the boundary conditions state for an exact solution. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -92,5 +92,5 @@ class CIncTGVSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; }; diff --git a/Common/include/toolboxes/MMS/CInviscidVortexSolution.hpp b/Common/include/toolboxes/MMS/CInviscidVortexSolution.hpp index c7a70fbaf02b..32617574f24c 100644 --- a/Common/include/toolboxes/MMS/CInviscidVortexSolution.hpp +++ b/Common/include/toolboxes/MMS/CInviscidVortexSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -37,7 +37,7 @@ * \brief Class to define the required data for the Inviscid Vortex. * \author E. van der Weide, T. Economon */ -class CInviscidVortexSolution: public CVerificationSolution { +class CInviscidVortexSolution final: public CVerificationSolution { protected: @@ -56,12 +56,12 @@ class CInviscidVortexSolution: public CVerificationSolution { su2double gamOvGm1; /*!< \brief Gamma over Gamma minus 1 */ public: - + /*! * \brief Constructor of the class. */ CInviscidVortexSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -73,7 +73,7 @@ class CInviscidVortexSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ @@ -87,7 +87,7 @@ class CInviscidVortexSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the boundary conditions state for an exact solution. @@ -97,5 +97,5 @@ class CInviscidVortexSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; }; diff --git a/Common/include/toolboxes/MMS/CMMSIncEulerSolution.hpp b/Common/include/toolboxes/MMS/CMMSIncEulerSolution.hpp index 4bbd3d74e8d3..fab3c557bf2c 100644 --- a/Common/include/toolboxes/MMS/CMMSIncEulerSolution.hpp +++ b/Common/include/toolboxes/MMS/CMMSIncEulerSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -38,32 +38,32 @@ * incompressible Euler equations. * \author T. Economon, E. van der Weide */ -class CMMSIncEulerSolution: public CVerificationSolution { - +class CMMSIncEulerSolution final: public CVerificationSolution { + protected: - + /*--- Variables that define the solution and MMS source term. ---*/ su2double Density; /*!< \brief Density, must be constant. */ su2double Temperature; /*!< \brief Temperature, just to be safe. */ - + /*--- Constants, which describe this manufactured solution. This is a solution where the primitive variables vary as a combination of sine and cosine functions. The solution is from Salari K, and Knupp P, "Code verification by the method of manufactured solutions," SAND 2000-1444, Sandia National Laboratories, Albuquerque, NM, 2000. ---*/ - + su2double P_0; /*!< \brief Parameter for the pressure solution. */ su2double u_0; /*!< \brief Parameter for the x-velocity solution. */ su2double v_0; /*!< \brief Parameter for the y-velocity solution. */ su2double epsilon; /*!< \brief Parameter for the velocity solutions. */ - + public: - + /*! * \brief Constructor of the class. */ CMMSIncEulerSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -75,12 +75,12 @@ class CMMSIncEulerSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ ~CMMSIncEulerSolution(void); - + /*! * \brief Get the exact solution at the current position and time. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -89,8 +89,8 @@ class CMMSIncEulerSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); - + su2double *val_solution) const override; + /*! * \brief Get the boundary conditions state for an exact solution. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -99,8 +99,8 @@ class CMMSIncEulerSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); - + su2double *val_solution) const override; + /*! * \brief Get the source term for the manufactured solution (MMS). * \param[in] val_coords - Cartesian coordinates of the current position. @@ -109,11 +109,11 @@ class CMMSIncEulerSolution: public CVerificationSolution { */ void GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source); - + su2double *val_source) const override; + /*! * \brief Whether or not this verification solution is a manufactured solution. * \return - True, because this is a manufactured solution. */ - bool IsManufacturedSolution(void); + bool IsManufacturedSolution(void) const override; }; diff --git a/Common/include/toolboxes/MMS/CMMSIncNSSolution.hpp b/Common/include/toolboxes/MMS/CMMSIncNSSolution.hpp index ba9610214dcf..975980f39057 100644 --- a/Common/include/toolboxes/MMS/CMMSIncNSSolution.hpp +++ b/Common/include/toolboxes/MMS/CMMSIncNSSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -38,33 +38,33 @@ * laminar incompressible Navier-Stokes equations. * \author T. Economon, E. van der Weide */ -class CMMSIncNSSolution: public CVerificationSolution { - +class CMMSIncNSSolution final: public CVerificationSolution { + protected: - + /*--- Variables that define the solution and MMS source term. ---*/ su2double Viscosity; /*!< \brief Viscosity, must be constant. */ su2double Density; /*!< \brief Density, must be constant. */ su2double Temperature; /*!< \brief Temperature, just to be safe. */ - + /*--- Constants, which describe this manufactured solution. This is a viscous solution where the primitive variables vary as a combination of sine and cosine functions. The solution is from Salari K, and Knupp P, "Code verification by the method of manufactured solutions," SAND 2000-1444, Sandia National Laboratories, Albuquerque, NM, 2000. ---*/ - + su2double P_0; /*!< \brief Parameter for the pressure solution. */ su2double u_0; /*!< \brief Parameter for the x-velocity solution. */ su2double v_0; /*!< \brief Parameter for the y-velocity solution. */ su2double epsilon; /*!< \brief Parameter for the velocity solutions. */ - + public: - + /*! * \brief Constructor of the class. */ CMMSIncNSSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -76,12 +76,12 @@ class CMMSIncNSSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ ~CMMSIncNSSolution(void); - + /*! * \brief Get the exact solution at the current position and time. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -90,8 +90,8 @@ class CMMSIncNSSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); - + su2double *val_solution) const override; + /*! * \brief Get the boundary conditions state for an exact solution. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -100,8 +100,8 @@ class CMMSIncNSSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); - + su2double *val_solution) const override; + /*! * \brief Get the source term for the manufactured solution (MMS). * \param[in] val_coords - Cartesian coordinates of the current position. @@ -110,11 +110,11 @@ class CMMSIncNSSolution: public CVerificationSolution { */ void GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source); - + su2double *val_source) const override; + /*! * \brief Whether or not this verification solution is a manufactured solution. * \return - True, because this is a manufactured solution. */ - bool IsManufacturedSolution(void); + bool IsManufacturedSolution(void) const override; }; diff --git a/Common/include/toolboxes/MMS/CMMSNSTwoHalfCirclesSolution.hpp b/Common/include/toolboxes/MMS/CMMSNSTwoHalfCirclesSolution.hpp index 6322e69fd65a..09e50d5e9e42 100644 --- a/Common/include/toolboxes/MMS/CMMSNSTwoHalfCirclesSolution.hpp +++ b/Common/include/toolboxes/MMS/CMMSNSTwoHalfCirclesSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -38,7 +38,7 @@ laminar Navier-Stokes equations on the domain between two half circles. * \author E. van der Weide, T. Economon */ -class CMMSNSTwoHalfCirclesSolution: public CVerificationSolution { +class CMMSNSTwoHalfCirclesSolution final: public CVerificationSolution { protected: /*--- Variables that define the solution and MMS source term. ---*/ @@ -64,12 +64,12 @@ class CMMSNSTwoHalfCirclesSolution: public CVerificationSolution { su2double a_T2; /*!< \brief Parameter for the temperature solution. */ public: - + /*! * \brief Constructor of the class. */ CMMSNSTwoHalfCirclesSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -81,7 +81,7 @@ class CMMSNSTwoHalfCirclesSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ @@ -95,7 +95,7 @@ class CMMSNSTwoHalfCirclesSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the boundary conditions state for an exact solution. @@ -105,7 +105,7 @@ class CMMSNSTwoHalfCirclesSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the source term for the manufactured solution (MMS). @@ -115,11 +115,11 @@ class CMMSNSTwoHalfCirclesSolution: public CVerificationSolution { */ void GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source); + su2double *val_source) const override; /*! * \brief Whether or not this verification solution is a manufactured solution. * \return - True, because this is a manufactured solution. */ - bool IsManufacturedSolution(void); + bool IsManufacturedSolution(void) const override; }; diff --git a/Common/include/toolboxes/MMS/CMMSNSTwoHalfSpheresSolution.hpp b/Common/include/toolboxes/MMS/CMMSNSTwoHalfSpheresSolution.hpp index d70a9341a2e0..428fa645dace 100644 --- a/Common/include/toolboxes/MMS/CMMSNSTwoHalfSpheresSolution.hpp +++ b/Common/include/toolboxes/MMS/CMMSNSTwoHalfSpheresSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -25,7 +25,7 @@ * You should have received a copy of the GNU Lesser General Public * License along with SU2. If not, see . */ - + #pragma once @@ -38,7 +38,7 @@ laminar Navier-Stokes equations on the domain between two half spheres. * \author E. van der Weide, T. Economon */ -class CMMSNSTwoHalfSpheresSolution: public CVerificationSolution { +class CMMSNSTwoHalfSpheresSolution final: public CVerificationSolution { protected: /*--- Variables that define the solution and MMS source term. ---*/ @@ -65,12 +65,12 @@ class CMMSNSTwoHalfSpheresSolution: public CVerificationSolution { su2double a_T2; /*!< \brief Parameter for the temperature solution. */ public: - + /*! * \brief Constructor of the class. */ CMMSNSTwoHalfSpheresSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -82,7 +82,7 @@ class CMMSNSTwoHalfSpheresSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ @@ -96,7 +96,7 @@ class CMMSNSTwoHalfSpheresSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the boundary conditions state for an exact solution. @@ -106,7 +106,7 @@ class CMMSNSTwoHalfSpheresSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the source term for the manufactured solution (MMS). @@ -116,11 +116,11 @@ class CMMSNSTwoHalfSpheresSolution: public CVerificationSolution { */ void GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source); + su2double *val_source) const override; /*! * \brief Whether or not this verification solution is a manufactured solution. * \return - True, because this is a manufactured solution. */ - bool IsManufacturedSolution(void); + bool IsManufacturedSolution(void) const override; }; diff --git a/Common/include/toolboxes/MMS/CMMSNSUnitQuadSolution.hpp b/Common/include/toolboxes/MMS/CMMSNSUnitQuadSolution.hpp index 827d5d507ab5..5284dccf8297 100644 --- a/Common/include/toolboxes/MMS/CMMSNSUnitQuadSolution.hpp +++ b/Common/include/toolboxes/MMS/CMMSNSUnitQuadSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -38,7 +38,7 @@ laminar Navier-Stokes equations on a unit quad. * \author E. van der Weide, T. Economon */ -class CMMSNSUnitQuadSolution: public CVerificationSolution { +class CMMSNSUnitQuadSolution final: public CVerificationSolution { protected: @@ -69,7 +69,7 @@ class CMMSNSUnitQuadSolution: public CVerificationSolution { su2double P_0; /*!< \brief Parameter for the pressure solution. */ su2double P_x; /*!< \brief Parameter for the pressure solution. */ su2double P_xy; /*!< \brief Parameter for the pressure solution. */ - su2double P_y; /*!< \brief Parameter for the pressure solution. */ + su2double P_y; /*!< \brief Parameter for the pressure solution. */ su2double rho_0; /*!< \brief Parameter for the density solution. */ su2double rho_x; /*!< \brief Parameter for the density solution. */ su2double rho_xy; /*!< \brief Parameter for the density solution. */ @@ -84,12 +84,12 @@ class CMMSNSUnitQuadSolution: public CVerificationSolution { su2double v_y; /*!< \brief Parameter for the y-velocity solution. */ public: - + /*! * \brief Constructor of the class. */ CMMSNSUnitQuadSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -101,7 +101,7 @@ class CMMSNSUnitQuadSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ @@ -115,7 +115,7 @@ class CMMSNSUnitQuadSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the boundary conditions state for an exact solution. @@ -125,7 +125,7 @@ class CMMSNSUnitQuadSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the source term for the manufactured solution (MMS). @@ -135,11 +135,11 @@ class CMMSNSUnitQuadSolution: public CVerificationSolution { */ void GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source); + su2double *val_source) const override; /*! * \brief Whether or not this verification solution is a manufactured solution. * \return - True, because this is a manufactured solution. */ - bool IsManufacturedSolution(void); + bool IsManufacturedSolution(void) const override; }; diff --git a/Common/include/toolboxes/MMS/CMMSNSUnitQuadSolutionWallBC.hpp b/Common/include/toolboxes/MMS/CMMSNSUnitQuadSolutionWallBC.hpp index 96d677b595b6..08479baf3639 100644 --- a/Common/include/toolboxes/MMS/CMMSNSUnitQuadSolutionWallBC.hpp +++ b/Common/include/toolboxes/MMS/CMMSNSUnitQuadSolutionWallBC.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -38,7 +38,7 @@ laminar Navier-Stokes equations on a unit quad with wall boundary conditions. * \author E. van der Weide, T. Economon */ -class CMMSNSUnitQuadSolutionWallBC: public CVerificationSolution { +class CMMSNSUnitQuadSolutionWallBC final: public CVerificationSolution { protected: @@ -65,12 +65,12 @@ class CMMSNSUnitQuadSolutionWallBC: public CVerificationSolution { su2double a_T2; /*!< \brief Parameter for the temperature solution. */ public: - + /*! * \brief Constructor of the class. */ CMMSNSUnitQuadSolutionWallBC(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -82,7 +82,7 @@ class CMMSNSUnitQuadSolutionWallBC: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ @@ -96,7 +96,7 @@ class CMMSNSUnitQuadSolutionWallBC: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the boundary conditions state for an exact solution. @@ -106,7 +106,7 @@ class CMMSNSUnitQuadSolutionWallBC: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the source term for the manufactured solution (MMS). @@ -116,11 +116,11 @@ class CMMSNSUnitQuadSolutionWallBC: public CVerificationSolution { */ void GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source); + su2double *val_source) const override; /*! * \brief Whether or not this verification solution is a manufactured solution. * \return - True, because this is a manufactured solution. */ - bool IsManufacturedSolution(void); + bool IsManufacturedSolution(void) const override; }; diff --git a/Common/include/toolboxes/MMS/CNSUnitQuadSolution.hpp b/Common/include/toolboxes/MMS/CNSUnitQuadSolution.hpp index 6f63b740c4df..f0a84469ae47 100644 --- a/Common/include/toolboxes/MMS/CNSUnitQuadSolution.hpp +++ b/Common/include/toolboxes/MMS/CNSUnitQuadSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -38,7 +38,7 @@ on a unit quad, heat conduction is neglected. * \author E. van der Weide, T. Economon */ -class CNSUnitQuadSolution: public CVerificationSolution { +class CNSUnitQuadSolution final: public CVerificationSolution { protected: @@ -48,12 +48,12 @@ class CNSUnitQuadSolution: public CVerificationSolution { su2double Viscosity; /*!< \brief Viscosity, must be constant. */ public: - + /*! * \brief Constructor of the class. */ CNSUnitQuadSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -65,7 +65,7 @@ class CNSUnitQuadSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ @@ -79,8 +79,8 @@ class CNSUnitQuadSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); - + su2double *val_solution) const override; + /*! * \brief Get the boundary conditions state for an exact solution. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -89,5 +89,5 @@ class CNSUnitQuadSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; }; diff --git a/Common/include/toolboxes/MMS/CRinglebSolution.hpp b/Common/include/toolboxes/MMS/CRinglebSolution.hpp index 885927708fc2..a2235cd908a0 100644 --- a/Common/include/toolboxes/MMS/CRinglebSolution.hpp +++ b/Common/include/toolboxes/MMS/CRinglebSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -37,7 +37,7 @@ * \brief Class to define the required data for the Ringleb flow. * \author E. van der Weide, T. Economon */ -class CRinglebSolution: public CVerificationSolution { +class CRinglebSolution final: public CVerificationSolution { protected: @@ -48,12 +48,12 @@ class CRinglebSolution: public CVerificationSolution { su2double tGamOvGm1; /*!< \brief 2 Gamma over Gamma minus 1 */ public: - + /*! * \brief Constructor of the class. */ CRinglebSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -65,7 +65,7 @@ class CRinglebSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ @@ -79,7 +79,7 @@ class CRinglebSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the boundary conditions state for an exact solution. @@ -89,5 +89,5 @@ class CRinglebSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; }; diff --git a/Common/include/toolboxes/MMS/CTGVSolution.hpp b/Common/include/toolboxes/MMS/CTGVSolution.hpp index d244f9f2b287..ababc85d683e 100644 --- a/Common/include/toolboxes/MMS/CTGVSolution.hpp +++ b/Common/include/toolboxes/MMS/CTGVSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -37,25 +37,25 @@ * \brief Class to define the required data for the Taylor Green Vortex. * \author E. van der Weide, T. Economon */ -class CTGVSolution: public CVerificationSolution { - +class CTGVSolution final: public CVerificationSolution { + protected: - + /*--- TGV specific conditions. ---*/ - + su2double tgvLength; /*!< \brief Taylor-Green length scale. */ su2double tgvVelocity; /*!< \brief Taylor-Green velocity. */ su2double tgvDensity; /*!< \brief Taylor-Green density. */ su2double tgvPressure; /*!< \brief Taylor-Green pressure. */ su2double ovGm1; /*!< \brief 1 over Gamma minus 1 */ - + public: - + /*! * \brief Constructor of the class. */ CTGVSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -67,12 +67,12 @@ class CTGVSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ ~CTGVSolution(void); - + /*! * \brief Get the exact solution at the current position and time. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -81,11 +81,11 @@ class CTGVSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); - + su2double *val_solution) const override; + /*! * \brief Whether or not the exact solution is known for this verification solution. * \return - False, because the exact solution is not known for the TGV case. */ - bool ExactSolutionKnown(void); + bool ExactSolutionKnown(void) const override; }; diff --git a/Common/include/toolboxes/MMS/CUserDefinedSolution.hpp b/Common/include/toolboxes/MMS/CUserDefinedSolution.hpp index b636001691a1..51743ebdec7c 100644 --- a/Common/include/toolboxes/MMS/CUserDefinedSolution.hpp +++ b/Common/include/toolboxes/MMS/CUserDefinedSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -36,15 +36,15 @@ * \brief Class to define the required data for a user defined solution. * \author E. van der Weide, T. Economon */ -class CUserDefinedSolution: public CVerificationSolution { +class CUserDefinedSolution final: public CVerificationSolution { public: - + /*! * \brief Constructor of the class. */ CUserDefinedSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -56,7 +56,7 @@ class CUserDefinedSolution: public CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig* config); - + /*! * \brief Destructor of the class. */ @@ -70,7 +70,7 @@ class CUserDefinedSolution: public CVerificationSolution { */ void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the boundary conditions state for an exact solution. @@ -80,7 +80,7 @@ class CUserDefinedSolution: public CVerificationSolution { */ void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); + su2double *val_solution) const override; /*! * \brief Get the source term for the manufactured solution (MMS). @@ -90,11 +90,11 @@ class CUserDefinedSolution: public CVerificationSolution { */ void GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source); + su2double *val_source) const override; /*! * \brief Whether or not this verification solution is a manufactured solution. * \return - True if this is a manufactured solution and false otherwise. */ - bool IsManufacturedSolution(void); + bool IsManufacturedSolution(void) const override; }; diff --git a/Common/include/toolboxes/MMS/CVerificationSolution.hpp b/Common/include/toolboxes/MMS/CVerificationSolution.hpp index 98149b563cb2..d992c5a69ebc 100644 --- a/Common/include/toolboxes/MMS/CVerificationSolution.hpp +++ b/Common/include/toolboxes/MMS/CVerificationSolution.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -38,14 +38,14 @@ * \author T. Economon, E. van der Weide */ class CVerificationSolution { - + protected: int rank; /*!< \brief MPI Rank. */ int size; /*!< \brief MPI Size. */ - + unsigned short nDim; /*!< \brief Number of dimension of the problem. */ unsigned short nVar; /*!< \brief Number of variables of the problem */ - + unsigned short Kind_Solver; /*!< \brief The kind of solver we are running. */ private: @@ -54,14 +54,14 @@ class CVerificationSolution { su2double *Error_Max; /*!< \brief Vector with the global max error for each variable in a verification case. */ unsigned long *Error_Point_Max; /*!< \brief Global index for the node with the max error in a verification case. */ su2double **Error_Point_Max_Coord; /*!< \brief Coordinates for the node with the max error in a verification case. */ - + public: - + /*! * \brief Constructor of the class. */ CVerificationSolution(void); - + /*! * \overload * \param[in] val_nDim - Number of dimensions of the problem. @@ -73,7 +73,7 @@ class CVerificationSolution { unsigned short val_nvar, unsigned short val_iMesh, CConfig *config); - + /*! * \brief Destructor of the class. */ @@ -87,16 +87,16 @@ class CVerificationSolution { */ virtual void GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution); - + su2double *val_solution) const; + /*! * \brief Get the exact solution at the current position and t = 0. * \param[in] val_coords - Cartesian coordinates of the current position. * \param[in] val_solution - Array where the exact solution is stored. */ void GetInitialCondition(const su2double *val_coords, - su2double *val_solution); - + su2double *val_solution) const; + /*! * \brief Get the boundary conditions state for an exact solution. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -105,8 +105,8 @@ class CVerificationSolution { */ virtual void GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution); - + su2double *val_solution) const; + /*! * \brief Get the source term for the manufactured solution (MMS). * \param[in] val_coords - Cartesian coordinates of the current position. @@ -115,22 +115,22 @@ class CVerificationSolution { */ virtual void GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source); + su2double *val_source) const; /*! * \brief Whether or not this verification solution is a manufactured solution. * \return - False as default value. Overwrite this function for a manufactured solution. */ - virtual bool IsManufacturedSolution(void); + virtual bool IsManufacturedSolution(void) const; /*! * \brief Whether or not the exact solution is known for this verification solution. * \return - True as default value. Overwrite this function if the exact solution is not known. */ - virtual bool ExactSolutionKnown(void); - + virtual bool ExactSolutionKnown(void) const; + /*! * \brief Get the local error defined as the local solution minus the verification solution. * \param[in] val_coords - Cartesian coordinates of the current position. @@ -140,65 +140,75 @@ class CVerificationSolution { void GetLocalError(const su2double *val_coords, const su2double val_t, const su2double *GetLocalErrorval_solution, - su2double *val_error); + su2double *val_error) const; /*! * \brief Set the global RMS error for verification cases. * \param[in] val_var - Index of the variable. * \param[in] val_error - Value of the RMS error to store in the position val_var. */ - void SetError_RMS(unsigned short val_var, su2double val_error); + void SetError_RMS(unsigned short val_var, su2double val_error) { Error_RMS[val_var] = val_error; } /*! * \brief Increments the global RMS error for verification cases. * \param[in] val_var - Index of the variable. * \param[in] val_error - Value of the RMS error to store in the position val_var. */ - void AddError_RMS(unsigned short val_var, su2double val_error); + void AddError_RMS(unsigned short val_var, su2double val_error) { Error_RMS[val_var] += val_error; } /*! * \brief Get the global RMS error for verification cases. * \param[in] val_var - Index of the variable. * \return Value of global RMS error for the variable in the position val_var. */ - su2double GetError_RMS(unsigned short val_var); + su2double GetError_RMS(unsigned short val_var) const { return Error_RMS[val_var]; } /*! * \brief Set the global maximum error for verification cases. * \param[in] val_var - Index of the variable. * \param[in] val_error - Value of the maximum error to store in the position val_var. */ - void SetError_Max(unsigned short val_var, su2double val_error, unsigned long val_point); + void SetError_Max(unsigned short val_var, su2double val_error, unsigned long val_point) { + Error_Max[val_var] = val_error; + Error_Point_Max[val_var] = val_point; + } - /*! + /*! * \brief Increment the global maximum error for verification cases. * \param[in] val_var - Index of the variable. * \param[in] val_error - Value of the maximum error to store in the position val_var. * \param[in] val_point - Value of the point index for the max error. * \param[in] val_coord - Location (x, y, z) of the max error point. */ - void AddError_Max(unsigned short val_var, su2double val_error, unsigned long val_point, su2double* val_coord); + void AddError_Max(unsigned short val_var, su2double val_error, unsigned long val_point, const su2double* val_coord) { + if (val_error > Error_Max[val_var]) { + Error_Max[val_var] = val_error; + Error_Point_Max[val_var] = val_point; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Error_Point_Max_Coord[val_var][iDim] = val_coord[iDim]; + } + } /*! * \brief Get the global maximum error for verification cases. * \param[in] val_var - Index of the variable. * \return Value of global maximum error for the variable in the position val_var. */ - su2double GetError_Max(unsigned short val_var); + su2double GetError_Max(unsigned short val_var) const { return Error_Max[val_var]; } /*! * \brief Get the global index of the node with the max error for verification cases. * \param[in] val_var - Index of the variable. * \return Global index of the point with the max error for the variable in the position val_var. */ - unsigned long GetError_Point_Max(unsigned short val_var); + unsigned long GetError_Point_Max(unsigned short val_var) const { return Error_Point_Max[val_var]; } /*! * \brief Get the coordinates of the node with the max error for verification cases. * \param[in] val_var - Index of the variable. * \return Coordinates of the point with the max error for the variable in the position val_var. */ - su2double* GetError_Point_Max_Coord(unsigned short val_var); + const su2double* GetError_Point_Max_Coord(unsigned short val_var) const { return Error_Point_Max_Coord[val_var]; } /*! * \brief Calculate the global error metrics for verification cases. @@ -208,5 +218,3 @@ class CVerificationSolution { void SetVerificationError(unsigned long nDOFsGlobal, CConfig *config); }; - -#include "CVerificationSolution.inl" diff --git a/Common/include/toolboxes/MMS/CVerificationSolution.inl b/Common/include/toolboxes/MMS/CVerificationSolution.inl deleted file mode 100644 index ced45443d3bf..000000000000 --- a/Common/include/toolboxes/MMS/CVerificationSolution.inl +++ /dev/null @@ -1,25 +0,0 @@ -inline void CVerificationSolution::SetError_RMS(unsigned short val_var, su2double val_error) { Error_RMS[val_var] = val_error; } - -inline void CVerificationSolution::AddError_RMS(unsigned short val_var, su2double val_error) { Error_RMS[val_var] += val_error; } - -inline su2double CVerificationSolution::GetError_RMS(unsigned short val_var) { return Error_RMS[val_var]; } - -inline void CVerificationSolution::SetError_Max(unsigned short val_var, su2double val_error, unsigned long val_point) { - Error_Max[val_var] = val_error; - Error_Point_Max[val_var] = val_point; -} - -inline void CVerificationSolution::AddError_Max(unsigned short val_var, su2double val_error, unsigned long val_point, su2double* val_coord) { - if (val_error > Error_Max[val_var]) { - Error_Max[val_var] = val_error; - Error_Point_Max[val_var] = val_point; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Error_Point_Max_Coord[val_var][iDim] = val_coord[iDim]; - } -} - -inline su2double CVerificationSolution::GetError_Max(unsigned short val_var) { return Error_Max[val_var]; } - -inline unsigned long CVerificationSolution::GetError_Point_Max(unsigned short val_var) { return Error_Point_Max[val_var]; } - -inline su2double* CVerificationSolution::GetError_Point_Max_Coord(unsigned short val_var) { return Error_Point_Max_Coord[val_var]; } diff --git a/Common/include/toolboxes/graph_toolbox.hpp b/Common/include/toolboxes/graph_toolbox.hpp index 76dffc1f39ab..ecdbacedfb5c 100644 --- a/Common/include/toolboxes/graph_toolbox.hpp +++ b/Common/include/toolboxes/graph_toolbox.hpp @@ -34,6 +34,7 @@ #include #include #include +#include /*! * \enum ConnectivityType @@ -398,11 +399,13 @@ CEdgeToNonZeroMap mapEdgesToSparsePattern(Geometry_t& geometry, * pattern is returned. * \param[in] pattern - Sparse pattern to be colored. * \param[in] groupSize - Size of the outer index groups, default 1. + * \param[in] balanceColors - Try to balance number of indexes per color, + * tends to result in worse locality (thus false by default). * \param[out] indexColor - Optional, vector with colors given to the outer indices. * \return Coloring in the same type of the input pattern. */ template -T colorSparsePattern(const T& pattern, size_t groupSize = 1, +T colorSparsePattern(const T& pattern, size_t groupSize = 1, bool balanceColors = false, std::vector* indexColor = nullptr) { static_assert(std::is_integral::value,""); @@ -423,13 +426,16 @@ T colorSparsePattern(const T& pattern, size_t groupSize = 1, /*--- Start with one color, with no indices assigned. ---*/ std::vector colorSize(1,0); - Color_t color, nColor = 1; + Color_t nColor = 1; { /*--- For each color keep track of the inner indices that are in it. ---*/ std::vector > innerInColor; innerInColor.emplace_back(nInner, false); + /*--- Order in which we look for space in the colors to insert a new group. ---*/ + std::vector searchOrder(MaxColors); + auto outerPtr = pattern.outerPtr(); auto innerIdx = pattern.innerIdx(); @@ -437,23 +443,40 @@ T colorSparsePattern(const T& pattern, size_t groupSize = 1, { Index_t grpEnd = std::min(iOuter+grpSz, nOuter); - for(color = 0; color < nColor; ++color) + searchOrder.resize(nColor); + std::iota(searchOrder.begin(), searchOrder.end(), 0); + + /*--- Balance sizes by looking for space in smaller colors first. ---*/ + if(balanceColors) { + std::sort(searchOrder.begin(), searchOrder.end(), + [&colorSize](Color_t a, Color_t b){return colorSize[a] < colorSize[b];}); + } + + auto it = searchOrder.begin(); + + for(; it != searchOrder.end(); ++it) { bool free = true; /*--- Traverse entire group as a large outer index. ---*/ for(Index_t k = outerPtr[iOuter]; k < outerPtr[grpEnd] && free; ++k) { - free = !innerInColor[color][innerIdx[k]-minIdx]; + free = !innerInColor[*it][innerIdx[k]-minIdx]; } /*--- If none of the inner indices in the group appears in * this color yet, it is assigned to the group. ---*/ if(free) break; } - /*--- No color was free, make space for a new one. ---*/ - if(color == nColor) + Color_t color; + + if(it != searchOrder.end()) { - ++nColor; + /*--- Found a free color. ---*/ + color = *it; + } + else { + /*--- No color was free, make space for a new one. ---*/ + color = nColor++; if(nColor == MaxColors) return T(); colorSize.push_back(0); innerInColor.emplace_back(nInner, false); @@ -480,7 +503,7 @@ T colorSparsePattern(const T& pattern, size_t groupSize = 1, su2vector outerIdx(nOuter); Index_t k = 0; - for(color = 0; color < nColor; ++color) + for(Color_t color = 0; color < nColor; ++color) { colorPtr(color+1) = colorPtr(color)+colorSize[color]; @@ -495,3 +518,77 @@ T colorSparsePattern(const T& pattern, size_t groupSize = 1, /*--- Move compressed coloring into result pattern instance. ---*/ return T(std::move(colorPtr), std::move(outerIdx)); } + + +/*! + * \brief Create the natural coloring (equivalent to the normal sequential loop + * order) for a given number of inner indexes. + * \note This is to reduce overhead in "OpenMP-ready" code when only 1 thread is used. + * \param[in] numInnerIndexes - Number of indexes that are to be colored. + * \return Natural (sequential) coloring of the inner indices. + */ +template +T createNaturalColoring(Index_t numInnerIndexes) +{ + /*--- One color. ---*/ + su2vector outerPtr(2); + outerPtr(0) = 0; + outerPtr(1) = numInnerIndexes; + + /*--- Containing all indexes in ascending order. ---*/ + su2vector innerIdx(numInnerIndexes); + std::iota(innerIdx.data(), innerIdx.data()+numInnerIndexes, 0); + + return T(std::move(outerPtr), std::move(innerIdx)); +} + + +/*! + * \brief A way to represent one grid color that allows range-for syntax. + */ +template +struct GridColor +{ + static_assert(std::is_integral::value,""); + + const T size; + const T* const indices; + + GridColor(const T* idx = nullptr, T sz = 0) : size(sz), indices(idx) { } + + inline const T* begin() const {return indices;} + inline const T* end() const {return indices+size;} +}; + + +/*! + * \brief A way to represent natural coloring {0,1,2,...,size-1} with zero + * overhead (behaves like looping with an integer index, after optimization...). + */ +template +struct DummyGridColor +{ + static_assert(std::is_integral::value,""); + + T size; + struct { + inline T operator[] (T i) const {return i;} + } + indices; + + DummyGridColor(T sz = 0) : size(sz) { } + + struct IteratorLikeInt { + T i; + inline IteratorLikeInt(T pos = 0) : i(pos) {} + inline IteratorLikeInt& operator++ () {++i; return *this;} + inline IteratorLikeInt operator++ (int) {auto j=i++; return IteratorLikeInt(j);} + inline T operator* () const {return i;} + inline T operator-> () const {return i;} + inline bool operator==(const IteratorLikeInt& other) const {return i==other.i;} + inline bool operator!=(const IteratorLikeInt& other) const {return i!=other.i;} + }; + inline IteratorLikeInt begin() const {return IteratorLikeInt(0);} + inline IteratorLikeInt end() const {return IteratorLikeInt(size);} +}; diff --git a/Common/lib/Makefile.am b/Common/lib/Makefile.am index e8e1745efb4b..71e5453849b3 100644 --- a/Common/lib/Makefile.am +++ b/Common/lib/Makefile.am @@ -98,6 +98,7 @@ lib_sources = \ ../src/wall_model.cpp \ ../src/toolboxes/printing_toolbox.cpp \ ../src/toolboxes/CLinearPartitioner.cpp \ + ../src/toolboxes/C1DInterpolation.cpp \ ../src/toolboxes/MMS/CVerificationSolution.cpp \ ../src/toolboxes/MMS/CIncTGVSolution.cpp \ ../src/toolboxes/MMS/CInviscidVortexSolution.cpp \ diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 0f5ef1891764..ca118d53ccb0 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -2816,6 +2816,9 @@ void CConfig::SetConfig_Options() { /* DESCRIPTION: Level of fill for PaStiX incomplete LU factorization. */ addUnsignedShortOption("PASTIX_FILL_LEVEL", pastix_fill_lvl, 1); + /* DESCRIPTION: Size of the edge groups colored for OpenMP parallelization of edge loops. */ + addUnsignedLongOption("EDGE_COLORING_GROUP_SIZE", edgeColorGroupSize, 512); + /* END_CONFIG_OPTIONS */ } @@ -5561,15 +5564,21 @@ void CConfig::SetOutput(unsigned short val_software, unsigned short val_izone) { cout <<"based on the physical case: "; } switch (Kind_Solver) { - case EULER: case DISC_ADJ_EULER: case FEM_EULER: case DISC_ADJ_FEM_EULER: + case EULER: case DISC_ADJ_EULER: + case INC_EULER: case DISC_ADJ_INC_EULER: + case FEM_EULER: case DISC_ADJ_FEM_EULER: if (Kind_Regime == COMPRESSIBLE) cout << "Compressible Euler equations." << endl; if (Kind_Regime == INCOMPRESSIBLE) cout << "Incompressible Euler equations." << endl; break; - case NAVIER_STOKES: case DISC_ADJ_NAVIER_STOKES: case FEM_NAVIER_STOKES: case DISC_ADJ_FEM_NS: + case NAVIER_STOKES: case DISC_ADJ_NAVIER_STOKES: + case INC_NAVIER_STOKES: case DISC_ADJ_INC_NAVIER_STOKES: + case FEM_NAVIER_STOKES: case DISC_ADJ_FEM_NS: if (Kind_Regime == COMPRESSIBLE) cout << "Compressible Laminar Navier-Stokes' equations." << endl; if (Kind_Regime == INCOMPRESSIBLE) cout << "Incompressible Laminar Navier-Stokes' equations." << endl; break; - case RANS: case DISC_ADJ_RANS: case FEM_RANS: case DISC_ADJ_FEM_RANS: + case RANS: case DISC_ADJ_RANS: + case INC_RANS: case DISC_ADJ_INC_RANS: + case FEM_RANS: case DISC_ADJ_FEM_RANS: if (Kind_Regime == COMPRESSIBLE) cout << "Compressible RANS equations." << endl; if (Kind_Regime == INCOMPRESSIBLE) cout << "Incompressible RANS equations." << endl; cout << "Turbulence model: "; diff --git a/Common/src/geometry/CGeometry.cpp b/Common/src/geometry/CGeometry.cpp index 731a95131afe..41b2f2501621 100644 --- a/Common/src/geometry/CGeometry.cpp +++ b/Common/src/geometry/CGeometry.cpp @@ -73,13 +73,6 @@ CGeometry::CGeometry(void) { nNewElem_Bound = NULL; Marker_All_SendRecv = NULL; - XCoordList.clear(); - Xcoord_plane.clear(); - Ycoord_plane.clear(); - Zcoord_plane.clear(); - FaceArea_plane.clear(); - Plane_points.clear(); - /*--- Arrays for defining the linear partitioning ---*/ beg_node = NULL; @@ -3360,7 +3353,7 @@ void CGeometry::FilterValuesAtElementCG(const vector &filter_radius, the recursion limit is reached and the full neighborhood is not considered. ---*/ unsigned long limited_searches = 0; - SU2_OMP(parallel reduction(+:limited_searches)) + SU2_OMP_PARALLEL_(reduction(+:limited_searches)) { /*--- Initialize ---*/ @@ -4045,7 +4038,14 @@ const CEdgeToNonZeroMapUL& CGeometry::GetEdgeToSparsePatternMap(void) const CCompressedSparsePatternUL& CGeometry::GetEdgeColoring(void) { - if (edgeColoring.empty()) { + if (edgeColoring.empty() && nEdge) { + + /*--- When not using threading, and for coarse grids, use the natural coloring. ---*/ + if ((omp_get_max_threads() == 1) || (MGLevel != MESH_0)) { + edgeColoring = createNaturalColoring(nEdge); + return edgeColoring; + } + /*--- Create a temporary sparse pattern from the edges. ---*/ /// TODO: Try to avoid temporary once grid information is made contiguous. su2vector outerPtr(nEdge+1); @@ -4060,8 +4060,9 @@ const CCompressedSparsePatternUL& CGeometry::GetEdgeColoring(void) CCompressedSparsePatternUL pattern(move(outerPtr), move(innerIdx)); - /*--- Color the edges. ---*/ - edgeColoring = colorSparsePattern(pattern, edgeColorGroupSize); + /*--- Color the edges, only balance sizes on coarse levels. ---*/ + bool balanceColors = (MGLevel != MESH_0); + edgeColoring = colorSparsePattern(pattern, edgeColorGroupSize, balanceColors); if(edgeColoring.empty()) SU2_MPI::Error("Edge coloring failed.", CURRENT_FUNCTION); @@ -4071,7 +4072,14 @@ const CCompressedSparsePatternUL& CGeometry::GetEdgeColoring(void) const CCompressedSparsePatternUL& CGeometry::GetElementColoring(void) { - if (elemColoring.empty()) { + if (elemColoring.empty() && nElem) { + + /*--- When not using threading use the natural coloring. ---*/ + if (omp_get_max_threads() == 1) { + elemColoring = createNaturalColoring(nElem); + return elemColoring; + } + /*--- Create a temporary sparse pattern from the elements. ---*/ /// TODO: Try to avoid temporary once grid information is made contiguous. vector outerPtr(nElem+1); diff --git a/Common/src/geometry/CPhysicalGeometry.cpp b/Common/src/geometry/CPhysicalGeometry.cpp index ad15b62ee425..8d074e63b2b4 100644 --- a/Common/src/geometry/CPhysicalGeometry.cpp +++ b/Common/src/geometry/CPhysicalGeometry.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -124,6 +124,8 @@ CPhysicalGeometry::CPhysicalGeometry(CConfig *config, unsigned short val_iZone, #endif #endif + edgeColorGroupSize = config->GetEdgeColoringGroupSize(); + /*--- Arrays for defining the turbomachinery structure ---*/ nSpanWiseSections = NULL; @@ -311,6 +313,8 @@ CPhysicalGeometry::CPhysicalGeometry(CGeometry *geometry, #endif #endif + edgeColorGroupSize = config->GetEdgeColoringGroupSize(); + /*--- Arrays for defining the turbomachinery structure ---*/ nSpanWiseSections = NULL; @@ -7985,11 +7989,11 @@ void CPhysicalGeometry::MatchPeriodic(CConfig *config, su2double rotMatrix[3][3] = {{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}}; su2double Theta, Phi, Psi, cosTheta, sinTheta, cosPhi, sinPhi, cosPsi, sinPsi; su2double rotCoord[3] = {0.0, 0.0, 0.0}; - + bool pointOnAxis = false; - + bool chkSamePoint = false; - + su2double distToAxis = 0.0; /*--- Tolerance for distance-based match to report warning. ---*/ @@ -8199,7 +8203,7 @@ void CPhysicalGeometry::MatchPeriodic(CConfig *config, rotMatrix[2][1]*dy + rotMatrix[2][2]*dz + translation[2]); - /*--- Check if the point lies on the axis of rotation. If it does, + /*--- Check if the point lies on the axis of rotation. If it does, the rotated coordinate and the original coordinate are the same. ---*/ pointOnAxis = false; @@ -8254,7 +8258,7 @@ void CPhysicalGeometry::MatchPeriodic(CConfig *config, and also perform checks just to be sure that this is an independent periodic point (even if on the same rank), unless it lies on the axis of rotation. ---*/ - + chkSamePoint = false; chkSamePoint = (((dist < mindist) && (iProcessor != rank)) || ((dist < mindist) && (iProcessor == rank) && diff --git a/Common/src/linear_algebra/CSysMatrix.cpp b/Common/src/linear_algebra/CSysMatrix.cpp index 5755dbdef576..af3635438a3d 100644 --- a/Common/src/linear_algebra/CSysMatrix.cpp +++ b/Common/src/linear_algebra/CSysMatrix.cpp @@ -189,6 +189,24 @@ void CSysMatrix::Initialize(unsigned long npoint, unsigned long npoi omp_partitions[part] = part * pts_per_part; omp_partitions[omp_num_parts] = nPointDomain; + /*--- For coarse grid levels setup a structure that allows doing a column sum efficiently, + * essentially the transpose of the col_ind, this allows populating the matrix by setting + * the off-diagonal entries and then setting the diagonal ones as the sum of column + * (excluding the diagonal itself). We use the fact that the pattern is symmetric. ---*/ + + if ((geometry->GetMGLevel() != MESH_0) && (omp_get_max_threads() > 1)) { + + col_ptr.resize(nnz, nullptr); + + SU2_OMP_PARALLEL_(for schedule(static,omp_heavy_size)) + for (auto iPoint = 0ul; iPoint < nPoint; ++iPoint) { + for (auto k = row_ptr[iPoint]; k < row_ptr[iPoint+1]; ++k) { + auto jPoint = col_ind[k]; + col_ptr[k] = GetBlock(jPoint, iPoint); + } + } + } + /*--- Generate MKL Kernels ---*/ #ifdef USE_MKL @@ -1307,6 +1325,21 @@ void CSysMatrix::EnforceSolutionAtNode(const unsigned long node_i, c } +template +void CSysMatrix::SetDiagonalAsColumnSum() { + + SU2_OMP_FOR_DYN(omp_heavy_size) + for (auto iPoint = 0ul; iPoint < nPoint; ++iPoint) { + + auto block_ii = &matrix[dia_ptr[iPoint]*nVar*nEqn]; + + for (auto k = row_ptr[iPoint]; k < row_ptr[iPoint+1]; ++k) { + auto block_ji = col_ptr[k]; + if (block_ji != block_ii) MatrixSubtraction(block_ii, block_ji, block_ii); + } + } +} + template template void CSysMatrix::MatrixMatrixAddition(OtherType alpha, const CSysMatrix& B) { diff --git a/Common/src/linear_algebra/CSysSolve.cpp b/Common/src/linear_algebra/CSysSolve.cpp index f38ad6d212f0..fafd401fedee 100644 --- a/Common/src/linear_algebra/CSysSolve.cpp +++ b/Common/src/linear_algebra/CSysSolve.cpp @@ -751,8 +751,12 @@ void CSysSolve::HandleTemporariesIn(const CSysVector & Lin /*--- When the type is the same the temporaties are not required ---*/ /*--- Set the pointers ---*/ - LinSysRes_ptr = &LinSysRes; - LinSysSol_ptr = &LinSysSol; + SU2_OMP_MASTER + { + LinSysRes_ptr = &LinSysRes; + LinSysSol_ptr = &LinSysSol; + } + SU2_OMP_BARRIER } template<> @@ -760,8 +764,12 @@ void CSysSolve::HandleTemporariesOut(CSysVector & LinSysSo /*--- When the type is the same the temporaties are not required ---*/ /*--- Reset the pointers ---*/ - LinSysRes_ptr = nullptr; - LinSysSol_ptr = nullptr; + SU2_OMP_MASTER + { + LinSysRes_ptr = nullptr; + LinSysSol_ptr = nullptr; + } + SU2_OMP_BARRIER } #ifdef CODI_REVERSE_TYPE @@ -774,8 +782,12 @@ void CSysSolve::HandleTemporariesIn(const CSysVector & LinSysSol_tmp.PassiveCopy(LinSysSol); /*--- Set the pointers ---*/ - LinSysRes_ptr = &LinSysRes_tmp; - LinSysSol_ptr = &LinSysSol_tmp; + SU2_OMP_MASTER + { + LinSysRes_ptr = &LinSysRes_tmp; + LinSysSol_ptr = &LinSysSol_tmp; + } + SU2_OMP_BARRIER } template<> @@ -786,8 +798,12 @@ void CSysSolve::HandleTemporariesOut(CSysVector & LinS LinSysSol.PassiveCopy(LinSysSol_tmp); /*--- Reset the pointers ---*/ - LinSysRes_ptr = nullptr; - LinSysSol_ptr = nullptr; + SU2_OMP_MASTER + { + LinSysRes_ptr = nullptr; + LinSysSol_ptr = nullptr; + } + SU2_OMP_BARRIER } #endif @@ -878,68 +894,53 @@ unsigned long CSysSolve::Solve(CSysMatrix & Jacobian, co break; } - /*--- Start a thread-parallel section covering the preparation of the - * preconditioner and the solution of the linear solver. - * Beware of shared variables, i.e. defined outside the section or - * members of ANY class used therein, they should be treated as - * read-only or explicitly synchronized if written to. ---*/ + /*--- Build preconditioner. ---*/ - unsigned long IterLinSol = 0; + precond->Build(); - SU2_OMP_PARALLEL - { - /*--- Build preconditioner in parallel. ---*/ - precond->Build(); + /*--- Solve system. ---*/ - /*--- Thread-local variables. ---*/ - unsigned long iter = 0; - ScalarType residual = 0.0, norm0 = 0.0; + unsigned long IterLinSol = 0; + ScalarType residual = 0.0, norm0 = 0.0; - switch (KindSolver) { - case BCGSTAB: - iter = BCGSTAB_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, MaxIter, residual, ScreenOutput, config); - break; - case FGMRES: - iter = FGMRES_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, MaxIter, residual, ScreenOutput, config); - break; - case CONJUGATE_GRADIENT: - iter = CG_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, MaxIter, residual, ScreenOutput, config); - break; - case RESTARTED_FGMRES: - norm0 = LinSysRes_ptr->norm(); - while (iter < MaxIter) { - /*--- Enforce a hard limit on total number of iterations ---*/ - unsigned long IterLimit = min(RestartIter, MaxIter-iter); - iter += FGMRES_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, IterLimit, residual, ScreenOutput, config); - if ( residual < SolverTol*norm0 ) break; - } - break; - case SMOOTHER: - iter = Smoother_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, MaxIter, residual, ScreenOutput, config); - break; - case PASTIX_LDLT : case PASTIX_LU: - Jacobian.BuildPastixPreconditioner(geometry, config, KindSolver); - Jacobian.ComputePastixPreconditioner(*LinSysRes_ptr, *LinSysSol_ptr, geometry, config); - iter = 1; - break; - default: - SU2_MPI::Error("Unknown type of linear solver.",CURRENT_FUNCTION); - } + switch (KindSolver) { + case BCGSTAB: + IterLinSol = BCGSTAB_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, MaxIter, residual, ScreenOutput, config); + break; + case FGMRES: + IterLinSol = FGMRES_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, MaxIter, residual, ScreenOutput, config); + break; + case CONJUGATE_GRADIENT: + IterLinSol = CG_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, MaxIter, residual, ScreenOutput, config); + break; + case RESTARTED_FGMRES: + norm0 = LinSysRes_ptr->norm(); + while (IterLinSol < MaxIter) { + /*--- Enforce a hard limit on total number of iterations ---*/ + unsigned long IterLimit = min(RestartIter, MaxIter-IterLinSol); + IterLinSol += FGMRES_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, IterLimit, residual, ScreenOutput, config); + if ( residual < SolverTol*norm0 ) break; + } + break; + case SMOOTHER: + IterLinSol = Smoother_LinSolver(*LinSysRes_ptr, *LinSysSol_ptr, mat_vec, *precond, SolverTol, MaxIter, residual, ScreenOutput, config); + break; + case PASTIX_LDLT : case PASTIX_LU: + Jacobian.BuildPastixPreconditioner(geometry, config, KindSolver); + Jacobian.ComputePastixPreconditioner(*LinSysRes_ptr, *LinSysSol_ptr, geometry, config); + IterLinSol = 1; + break; + default: + SU2_MPI::Error("Unknown type of linear solver.",CURRENT_FUNCTION); + } - /*--- Only one thread modifies shared variables, synchronization - * is not required as we are exiting the parallel section. ---*/ - SU2_OMP_MASTER - { - IterLinSol = iter; - Residual = residual; - } + SU2_OMP_MASTER + Residual = residual; - } // end SU2_OMP_PARALLEL + HandleTemporariesOut(LinSysSol); delete precond; - HandleTemporariesOut(LinSysSol); - if(TapeActive) { bool RequiresTranspose = !mesh_deform; // jacobian is symmetric diff --git a/Common/src/linear_algebra/CSysVector.cpp b/Common/src/linear_algebra/CSysVector.cpp index eb30b02e9a2c..0a5fbedfc09a 100644 --- a/Common/src/linear_algebra/CSysVector.cpp +++ b/Common/src/linear_algebra/CSysVector.cpp @@ -207,53 +207,34 @@ void CSysVector::CopyToArray(ScalarType* u_array) const { template ScalarType CSysVector::dot(const CSysVector & u) const { -#if !defined(CODI_FORWARD_TYPE) && !defined(CODI_REVERSE_TYPE) /*--- All threads get the same "view" of the vectors and shared variable. ---*/ SU2_OMP_BARRIER dotRes = 0.0; SU2_OMP_BARRIER - /*--- Reduction over all threads in this mpi rank using the shared variable. ---*/ + /*--- Local dot product for each thread. ---*/ ScalarType sum = 0.0; PARALLEL_FOR for(auto i=0ul; i::W::Allreduce(&sum, &dotRes, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); } +#endif /*--- Make view of result consistent across threads. ---*/ SU2_OMP_BARRIER -#endif // MPI -#else // CODI_TYPE - /*--- Compatible version, no OMP reductions, no atomics, master does everything. ---*/ - SU2_OMP_BARRIER - SU2_OMP_MASTER - { - ScalarType sum = 0.0; - for(auto i=0ul; i::W::Allreduce(&sum, &dotRes, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); -#else - dotRes = sum; -#endif // MPI - } - SU2_OMP_BARRIER -#endif // CODI + return dotRes; } diff --git a/Common/src/toolboxes/C1DInterpolation.cpp b/Common/src/toolboxes/C1DInterpolation.cpp index 52b63408ac0f..c7d2c31bbd1f 100644 --- a/Common/src/toolboxes/C1DInterpolation.cpp +++ b/Common/src/toolboxes/C1DInterpolation.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -24,167 +24,177 @@ * You should have received a copy of the GNU Lesser General Public * License along with SU2. If not, see . */ - + #include "../../include/toolboxes/C1DInterpolation.hpp" su2double CAkimaInterpolation::EvaluateSpline(su2double Point_Interp){ - Point_Match = false; - for (int i=0; i=x[i] && Point_Interp<=x[i+1]) - Point_Match = true; + Point_Match = false; - if (Point_Match == false){ - cout<<"WARNING: Extrapolating data for radius: "<=x[i] && Point_Interp<=x[i+1]) + Point_Match = true; - int i=0, j=n-1; + if (Point_Match == false){ + cout<<"WARNING: Extrapolating data for radius: "<1){ - int m=(i+j) / 2 ; - if (Point_Interp>x[m]) {i=m;} - else {j=m;} - } + int i=0, j=n-1; + + while (j-i>1){ + int m = (i+j) / 2; + if (Point_Interp>x[m]) {i = m;} + else {j = m;} + } - su2double h=Point_Interp-x[i] ; - return y[i]+h*(b[i]+h*(c[i]+h*d[i])) ; + su2double h=Point_Interp-x[i]; + + return y[i]+h*(b[i]+h*(c[i]+h*d[i])); } su2double CLinearInterpolation::EvaluateSpline(su2double Point_Interp){ - Point_Match = false; - for (int i=0; i=x[i] && Point_Interp<=x[i+1]){ - Point_Match = true; - return (Point_Interp-x[i])*dydx[i]+y[i]; - } + Point_Match = false; + + for (int i=0; i=x[i] && Point_Interp<=x[i+1]){ + Point_Match = true; + return (Point_Interp-x[i])*dydx[i]+y[i]; } - return 0; + } + return 0; } void CLinearInterpolation::SetSpline(const vector &X, const vector &Data){ - n = X.size(); - su2double h; - x.resize(n); - y.resize(n); - dydx.resize(n-1); - - x=X; - y=Data; - - for (int i=0; i &X,const vector &Data){ - - n = X.size(); - vector h (n-1); - vector p (n-1); - - /*---calculating finite differences (h) and gradients (p) ---*/ - for (int i=0; i &X,const vector &Data){ + + n = X.size(); + vector h (n-1); + vector p (n-1); + + /*---calculating finite differences (h) and gradients (p) ---*/ + for (int i=0; i CorrectedInletValues(const vector &Inlet_Interpolated , - su2double Theta , - unsigned short nDim, - su2double *Coord, - unsigned short nVar_Turb, - ENUM_INLET_INTERPOLATIONTYPE Interpolation_Type){ +vector CorrectedInletValues(const vector &Inlet_Interpolated , + su2double Theta , + unsigned short nDim, + const su2double *Coord, + unsigned short nVar_Turb, + ENUM_INLET_INTERPOLATIONTYPE Interpolation_Type){ - unsigned short size_columns=Inlet_Interpolated.size()+nDim; - vector Inlet_Values(size_columns); - su2double unit_r, unit_Theta, unit_m, Alpha, Phi; + unsigned short size_columns=Inlet_Interpolated.size()+nDim; + vector Inlet_Values(size_columns); + su2double unit_r, unit_Theta, unit_m, Alpha, Phi; - /*---For x,y,z,T,P columns---*/ - for (int i=0;i& Inlet_Data_Interpolated, string Marker, + unsigned long nVertex, unsigned short nDim, unsigned short nColumns){ - return Inlet_Values; -} + ofstream myfile; + myfile.precision(16); + myfile.open("Interpolated_Data_"+Marker+".dat",ios_base::out); -void PrintInletInterpolatedData(const vector& Inlet_Data_Interpolated, string Marker, unsigned long nVertex, unsigned short nDim, unsigned short nColumns){ - ofstream myfile; - myfile.precision(16); - myfile.open("Interpolated_Data_"+Marker+".dat",ios_base::out); - - if (myfile.is_open()){ - for (unsigned long iVertex = 0; iVertex < nVertex; iVertex++) { - for (unsigned short iVar=0; iVar < nColumns; iVar++){ - myfile<GetDensity_FreeStreamND(); tgvViscosity = config->GetViscosity_FreeStreamND(); - + /*--- We keep a copy of the freestream temperature just to be safe when we set the solution, even though this is an isothermal case. ---*/ - + Temperature = config->GetTemperature_FreeStreamND(); - + /*--- Perform some sanity and error checks for this solution here. ---*/ - + if((config->GetTime_Marching() != TIME_STEPPING) && (config->GetTime_Marching() != DT_STEPPING_1ST) && (config->GetTime_Marching() != DT_STEPPING_2ND)) SU2_MPI::Error("Unsteady mode must be selected for the incompressible Taylor Green Vortex", CURRENT_FUNCTION); - + if(Kind_Solver != INC_EULER && Kind_Solver != INC_NAVIER_STOKES && Kind_Solver != INC_RANS ) SU2_MPI::Error("Incompressible flow equations must be selected for the incompressible Taylor Green Vortex", CURRENT_FUNCTION); - + if(Kind_Solver != INC_NAVIER_STOKES) SU2_MPI::Error("Navier Stokes equations must be selected for the incompressible Taylor Green Vortex", CURRENT_FUNCTION); - + if(config->GetKind_FluidModel() != CONSTANT_DENSITY) SU2_MPI::Error("Constant density fluid model must be selected for the incompressible Taylor Green Vortex", CURRENT_FUNCTION); - + if(config->GetKind_ViscosityModel() != CONSTANT_VISCOSITY) SU2_MPI::Error("Constant viscosity must be selected for the incompressible Taylor Green Vortex", CURRENT_FUNCTION); - + if(config->GetEnergy_Equation()) SU2_MPI::Error("Energy equation must be disabled (isothermal) for the incompressible Taylor Green Vortex", CURRENT_FUNCTION); - + if(nDim != 2) SU2_MPI::Error("2D calculation required for the incompressible Taylor Green Vortex", CURRENT_FUNCTION); @@ -99,34 +99,34 @@ CIncTGVSolution::~CIncTGVSolution(void) { } void CIncTGVSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { - + su2double *val_solution) const { + /*--- The exact solution is prescribed on the boundaries. ---*/ GetSolution(val_coords, val_t, val_solution); } void CIncTGVSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { - + su2double *val_solution) const { + /* The exact solution is set for the incompressible Taylor-Green vortex case. This is the classic solution from the original work of Taylor and Green for the specific 2D situation where the exact solution can be derived for an incompressible flow. */ - + /* Store the termporal term more easily (Taylor expansion). */ su2double F = 1.0 - 2.0*(tgvViscosity/tgvDensity)*val_t; - + /* Compute the primitive variables. */ su2double u = tgvVelocity * F * (sin(val_coords[0]/tgvLength)* cos(val_coords[1]/tgvLength)); su2double v = -tgvVelocity * F * (cos(val_coords[0]/tgvLength)* sin(val_coords[1]/tgvLength)); - + su2double B = (cos(2.0*val_coords[0]/tgvLength) + cos(2.0*val_coords[1]/tgvLength)); su2double p = -(tgvDensity/4.0)*B*F*F; - + /* Compute the conservative variables. Note that both 2D and 3D cases are treated correctly. */ val_solution[0] = p; diff --git a/Common/src/toolboxes/MMS/CInviscidVortexSolution.cpp b/Common/src/toolboxes/MMS/CInviscidVortexSolution.cpp index d4f2a9c1857d..db415e565c52 100644 --- a/Common/src/toolboxes/MMS/CInviscidVortexSolution.cpp +++ b/Common/src/toolboxes/MMS/CInviscidVortexSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -34,7 +34,7 @@ CInviscidVortexSolution::CInviscidVortexSolution(unsigned short val_nDim, unsigned short val_iMesh, CConfig* config) : CVerificationSolution(val_nDim, val_nVar, val_iMesh, config) { - + /*--- Write a message that the solution is initialized for the inviscid vortex test case. ---*/ if ((rank == MASTER_NODE) && (val_iMesh == MESH_0)) { @@ -96,7 +96,7 @@ CInviscidVortexSolution::~CInviscidVortexSolution(void) { } void CInviscidVortexSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /*--- For the case that the inviscid vortex is run with boundary conditions (other possibility is with periodic conditions), @@ -106,7 +106,7 @@ void CInviscidVortexSolution::GetBCState(const su2double *val_coords, void CInviscidVortexSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /* Compute the free stream velocities in x- and y-direction. */ const su2double VelInf = MachVortex*sqrt(Gamma); diff --git a/Common/src/toolboxes/MMS/CMMSIncEulerSolution.cpp b/Common/src/toolboxes/MMS/CMMSIncEulerSolution.cpp index bc44270851aa..5cb74458a7ec 100644 --- a/Common/src/toolboxes/MMS/CMMSIncEulerSolution.cpp +++ b/Common/src/toolboxes/MMS/CMMSIncEulerSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -34,7 +34,7 @@ CMMSIncEulerSolution::CMMSIncEulerSolution(unsigned short val_nDim, unsigned short val_iMesh, CConfig* config) : CVerificationSolution(val_nDim, val_nVar, val_iMesh, config) { - + /*--- Write a message that the solution is initialized for the manufactured solution for the incompressible Navier-Stokes equations. ---*/ if ((rank == MASTER_NODE) && (val_iMesh == MESH_0)) { @@ -44,39 +44,39 @@ CMMSIncEulerSolution::CMMSIncEulerSolution(unsigned short val_nDim, cout << " of the incompressible Euler equations!!!" << endl; cout << endl << flush; } - + /*--- Coefficients, needed to determine the solution. ---*/ Density = config->GetDensity_FreeStreamND(); Temperature = config->GetTemperature_FreeStreamND(); - + /*--- Constants, which describe this manufactured solution. This is a solution where the primitive variables vary as a combination of sine and cosine functions. The solution is from Salari K, and Knupp P, "Code verification by the method of manufactured solutions," SAND 2000-1444, Sandia National Laboratories, Albuquerque, NM, 2000. ---*/ - + P_0 = 1.0; u_0 = 1.0; v_0 = 1.0; epsilon = 0.001; - + /*--- Perform some sanity and error checks for this solution here. ---*/ if(config->GetTime_Marching() != STEADY) SU2_MPI::Error("Steady mode must be selected for the MMS incompressible Euler case", CURRENT_FUNCTION); - + if(Kind_Solver != INC_EULER && Kind_Solver != INC_NAVIER_STOKES && Kind_Solver != INC_RANS ) SU2_MPI::Error("Incompressible flow equations must be selected for the MMS incompressible Euler case", CURRENT_FUNCTION); - + if(Kind_Solver != INC_EULER) SU2_MPI::Error("Euler equations must be selected for the MMS incompressible Euler case", CURRENT_FUNCTION); - + if(config->GetKind_FluidModel() != CONSTANT_DENSITY) SU2_MPI::Error("Constant density fluid model must be selected for the MMS incompressible Euler case", CURRENT_FUNCTION); - + if(config->GetEnergy_Equation()) SU2_MPI::Error("Energy equation must be disabled (isothermal) for the MMS incompressible Euler case", CURRENT_FUNCTION); @@ -86,25 +86,25 @@ CMMSIncEulerSolution::~CMMSIncEulerSolution(void) { } void CMMSIncEulerSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { - + su2double *val_solution) const { + /*--- The exact solution is prescribed on the boundaries. ---*/ GetSolution(val_coords, val_t, val_solution); } void CMMSIncEulerSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { - + su2double *val_solution) const { + /* Easier storage of the x- and y-coordinates. */ const su2double x = val_coords[0]; const su2double y = val_coords[1]; - + /* Compute the primitives from the defined solution. */ const su2double u = u_0*(sin(x*x + y*y) + epsilon); const su2double v = v_0*(cos(x*x + y*y) + epsilon); const su2double p = P_0*(sin(x*x + y*y) + 2.0); - + /* For the incompressible solver, we return the primitive variables directly, as they are used for the working variables in the solver. Note that the implementation below is valid for both 2D and 3D. */ @@ -113,17 +113,17 @@ void CMMSIncEulerSolution::GetSolution(const su2double *val_coords, val_solution[2] = v; val_solution[3] = 0.0; val_solution[nVar-1] = Temperature; - + } void CMMSIncEulerSolution::GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source) { - + su2double *val_source) const { + /*--- Easier storage of the x- and y-coordinates. ---*/ const su2double x = val_coords[0]; const su2double y = val_coords[1]; - + /*--- The expressions for the source terms are generated automatically by the sympy package in python.---*/ val_source[0] = 2*Density*(u_0*x*cos(pow(x, 2) + pow(y, 2)) - v_0*y*sin(pow(x, 2) + pow(y, 2))); @@ -131,9 +131,9 @@ void CMMSIncEulerSolution::GetMMSSourceTerm(const su2double *val_coords, val_source[2] = -2*Density*u_0*v_0*x*(epsilon + sin(pow(x, 2) + pow(y, 2)))*sin(pow(x, 2) + pow(y, 2)) + 2*Density*u_0*v_0*x*(epsilon + cos(pow(x, 2) + pow(y, 2)))*cos(pow(x, 2) + pow(y, 2)) - 4*Density*pow(v_0, 2)*y*(epsilon + cos(pow(x, 2) + pow(y, 2)))*sin(pow(x, 2) + pow(y, 2)) + 2*P_0*y*cos(pow(x, 2) + pow(y, 2)); val_source[3] = 0.0; val_source[nVar-1] = 0.0; - + } -bool CMMSIncEulerSolution::IsManufacturedSolution(void) { +bool CMMSIncEulerSolution::IsManufacturedSolution(void) const { return true; } diff --git a/Common/src/toolboxes/MMS/CMMSIncNSSolution.cpp b/Common/src/toolboxes/MMS/CMMSIncNSSolution.cpp index 40e81118a453..cef44403346b 100644 --- a/Common/src/toolboxes/MMS/CMMSIncNSSolution.cpp +++ b/Common/src/toolboxes/MMS/CMMSIncNSSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -34,7 +34,7 @@ CMMSIncNSSolution::CMMSIncNSSolution(unsigned short val_nDim, unsigned short val_iMesh, CConfig* config) : CVerificationSolution(val_nDim, val_nVar, val_iMesh, config) { - + /*--- Write a message that the solution is initialized for the manufactured solution for the incompressible Navier-Stokes equations. ---*/ if ((rank == MASTER_NODE) && (val_iMesh == MESH_0)) { @@ -44,44 +44,44 @@ CMMSIncNSSolution::CMMSIncNSSolution(unsigned short val_nDim, cout << " of the incompressible Navier-Stokes equations!!!" << endl; cout << endl << flush; } - + /*--- Coefficients, needed to determine the solution. ---*/ Viscosity = config->GetViscosity_FreeStreamND(); Density = config->GetDensity_FreeStreamND(); Temperature = config->GetTemperature_FreeStreamND(); - + /*--- Constants, which describe this manufactured solution. This is a viscous solution where the primitive variables vary as a combination of sine and cosine functions. The solution is from Salari K, and Knupp P, "Code verification by the method of manufactured solutions," SAND 2000-1444, Sandia National Laboratories, Albuquerque, NM, 2000. ---*/ - + P_0 = 1.0; u_0 = 1.0; v_0 = 1.0; epsilon = 0.001; - + /*--- Perform some sanity and error checks for this solution here. ---*/ if(config->GetTime_Marching() != STEADY) SU2_MPI::Error("Steady mode must be selected for the MMS incompressible NS case", CURRENT_FUNCTION); - + if(Kind_Solver != INC_EULER && Kind_Solver != INC_NAVIER_STOKES && Kind_Solver != INC_RANS ) SU2_MPI::Error("Incompressible flow equations must be selected for the MMS incompressible NS case", CURRENT_FUNCTION); - + if(Kind_Solver != INC_NAVIER_STOKES) SU2_MPI::Error("Navier Stokes equations must be selected for the MMS incompressible NS case", CURRENT_FUNCTION); - + if(config->GetKind_FluidModel() != CONSTANT_DENSITY) SU2_MPI::Error("Constant density fluid model must be selected for the MMS incompressible NS case", CURRENT_FUNCTION); - + if(config->GetKind_ViscosityModel() != CONSTANT_VISCOSITY) SU2_MPI::Error("Constant viscosity must be selected for the MMS incompressible NS case", CURRENT_FUNCTION); - + if(config->GetEnergy_Equation()) SU2_MPI::Error("Energy equation must be disabled (isothermal) for the MMS incompressible NS case", CURRENT_FUNCTION); @@ -91,25 +91,25 @@ CMMSIncNSSolution::~CMMSIncNSSolution(void) { } void CMMSIncNSSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { - + su2double *val_solution) const { + /*--- The exact solution is prescribed on the boundaries. ---*/ GetSolution(val_coords, val_t, val_solution); } void CMMSIncNSSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { - + su2double *val_solution) const { + /* Easier storage of the x- and y-coordinates. */ const su2double x = val_coords[0]; const su2double y = val_coords[1]; - + /* Compute the primitives from the defined solution. */ const su2double u = u_0*(sin(x*x + y*y) + epsilon); const su2double v = v_0*(cos(x*x + y*y) + epsilon); const su2double p = P_0*(sin(x*x + y*y) + 2.0); - + /* For the incompressible solver, we return the primitive variables directly, as they are used for the working variables in the solver. Note that the implementation below is valid for both 2D and 3D. */ @@ -118,17 +118,17 @@ void CMMSIncNSSolution::GetSolution(const su2double *val_coords, val_solution[2] = v; val_solution[3] = 0.0; val_solution[nVar-1] = Temperature; - + } void CMMSIncNSSolution::GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source) { - + su2double *val_source) const { + /*--- Easier storage of the x- and y-coordinates. ---*/ const su2double x = val_coords[0]; const su2double y = val_coords[1]; - + /*--- The expressions for the source terms are generated automatically by the sympy package in python.---*/ val_source[0] = 2*Density*(u_0*x*cos(pow(x, 2) + pow(y, 2)) - v_0*y*sin(pow(x, 2) + pow(y, 2))); @@ -136,9 +136,9 @@ void CMMSIncNSSolution::GetMMSSourceTerm(const su2double *val_coords, val_source[2] = -2*Density*u_0*v_0*x*(epsilon + sin(pow(x, 2) + pow(y, 2)))*sin(pow(x, 2) + pow(y, 2)) + 2*Density*u_0*v_0*x*(epsilon + cos(pow(x, 2) + pow(y, 2)))*cos(pow(x, 2) + pow(y, 2)) - 4*Density*pow(v_0, 2)*y*(epsilon + cos(pow(x, 2) + pow(y, 2)))*sin(pow(x, 2) + pow(y, 2)) + 2*P_0*y*cos(pow(x, 2) + pow(y, 2)) + 0.666666666666667*Viscosity*(-4*u_0*x*y*sin(pow(x, 2) + pow(y, 2)) + 8.0*v_0*pow(y, 2)*cos(pow(x, 2) + pow(y, 2)) + 4.0*v_0*sin(pow(x, 2) + pow(y, 2))) + 2*Viscosity*(2*u_0*x*y*sin(pow(x, 2) + pow(y, 2)) + 2*v_0*pow(x, 2)*cos(pow(x, 2) + pow(y, 2)) + v_0*sin(pow(x, 2) + pow(y, 2))); val_source[3] = 0.0; val_source[nVar-1] = 0.0; - + } -bool CMMSIncNSSolution::IsManufacturedSolution(void) { +bool CMMSIncNSSolution::IsManufacturedSolution(void) const { return true; } diff --git a/Common/src/toolboxes/MMS/CMMSNSTwoHalfCirclesSolution.cpp b/Common/src/toolboxes/MMS/CMMSNSTwoHalfCirclesSolution.cpp index ed45f201d6a1..57a7aaca5857 100644 --- a/Common/src/toolboxes/MMS/CMMSNSTwoHalfCirclesSolution.cpp +++ b/Common/src/toolboxes/MMS/CMMSNSTwoHalfCirclesSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -34,7 +34,7 @@ CMMSNSTwoHalfCirclesSolution::CMMSNSTwoHalfCirclesSolution(unsigned short val_nD unsigned short val_iMesh, CConfig* config) : CVerificationSolution(val_nDim, val_nVar, val_iMesh, config) { - + /*--- Write a message that the solution is initialized for the manufactured solution for the Navier-Stokes equations between two half circles. ---*/ if ((rank == MASTER_NODE) && (val_iMesh == MESH_0)) { @@ -111,7 +111,7 @@ CMMSNSTwoHalfCirclesSolution::~CMMSNSTwoHalfCirclesSolution(void) { } void CMMSNSTwoHalfCirclesSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /*--- The exact solution is prescribed on the boundaries. ---*/ GetSolution(val_coords, val_t, val_solution); @@ -119,7 +119,7 @@ void CMMSNSTwoHalfCirclesSolution::GetBCState(const su2double *val_coords, void CMMSNSTwoHalfCirclesSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /* Easier storage of the x- and y-coordinates. */ const su2double x = val_coords[0]; @@ -158,7 +158,7 @@ void CMMSNSTwoHalfCirclesSolution::GetSolution(const su2double *val_coords, void CMMSNSTwoHalfCirclesSolution::GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source) { + su2double *val_source) const { /*--- Abbreviate Pi and the coordinates. ---*/ const su2double Pi = PI_NUMBER; @@ -264,7 +264,7 @@ void CMMSNSTwoHalfCirclesSolution::GetMMSSourceTerm(const su2double *val_coords, const su2double t261 = t248 * t246 * t34 / 0.4e1 + 0.8e1 * (t25 * t252 + t25 * t254) * rho_0 + t246 * t34 / 0.4e1; const su2double t262 = v_0 * t261; const su2double t267 = -0.4e1 * t193 * t2 * TWall * t65 - 0.4e1 * t193 * TWall * t65 * t3 - 0.8e1 * t193 * t201 - + 0.64e2 / 0.3e1 * t8 * t12 * t22 * t76 - 0.4e1 * t9 * t213 + 0.4e1 * t13 * t213 + + 0.64e2 / 0.3e1 * t8 * t12 * t22 * t76 - 0.4e1 * t9 * t213 + 0.4e1 * t13 * t213 - 0.4e1 * t17 * t218 + 0.4e1 * t19 * t218 + 0.128e3 / 0.3e1 * t8 * t11 * Viscosity * t6 * t161 * t138 + 0.64e2 / 0.3e1 * t231 * t230 * t173 * t172 - 0.32e2 / 0.3e1 * t237 * t236 * t82 * t76 - 0.4e1 * t8 * t236 * t113 - 0.4e1 * t19 * t262 + 0.4e1 * t17 * t262; @@ -292,7 +292,7 @@ void CMMSNSTwoHalfCirclesSolution::GetMMSSourceTerm(const su2double *val_coords, + t11 * a_T2 * x * t285 - Pi * t7 * t183 - 0.2e1 * a_T2 * t51 * x * t292 - t53 / 0.2e1) * t201 + 0.4e1 * t300 * t2 * t190 * t11 * TWall * t81 + 0.64e2 / 0.3e1 * t317 * u_0 * t70 * x * t66 - 0.32e2 / 0.3e1 * x * t11 * t311 * t310 + 0.4e1 * t317 * u_0 * (t248 * t62 * t34 / 0.4e1 - + 0.16e2 * (-t9 * t252 - t9 * t254 + t27 * t364 + t27 * t367) * rho_0 + t64) + + 0.16e2 * (-t9 * t252 - t9 * t254 + t27 * t364 + t27 * t367) * rho_0 + t64) + 0.4e1 * t317 * v_0 * (t248 * t158 * t34 / 0.4e1 + 0.16e2 * (t141 * t364 + t141 * t367 - t17 * t252 - t17 * t254) * rho_0 + t160); @@ -300,7 +300,7 @@ void CMMSNSTwoHalfCirclesSolution::GetMMSSourceTerm(const su2double *val_coords, Note the scaling for the correct non-dimensionalization. ---*/ val_source[0] = -0.4e1 * t13 * t1 + 0.4e1 * t9 * t1 + 0.4e1 * t17 * t15 - 0.4e1 * t19 * t15; val_source[1] = 0.32e2 * t27 * t11 * t23 - 0.32e2 * t9 * t30 * t23 + t64 + 0.16e2 / 0.3e1 * t70 * x * t66 - + 0.16e2 / 0.3e1 * t6 * u_0 * t76 - 0.8e1 / 0.3e1 * x * t82 * t76 + 0.32e2 * t16 * t87 * t86 + + 0.16e2 / 0.3e1 * t6 * u_0 * t76 - 0.8e1 / 0.3e1 * x * t82 * t76 + 0.32e2 * t16 * t87 * t86 - 0.32e2 * t16 * t92 * t91 - t113; val_source[2] = 0.32e2 * t7 * t87 * t86 - 0.32e2 * t7 * t92 * t91 - t137 + 0.32e2 * t141 * t11 * t139 - 0.32e2 * t17 * t30 * t139 + t160 + 0.32e2 / 0.3e1 * Viscosity * t6 * t161 * v_0 @@ -314,6 +314,6 @@ void CMMSNSTwoHalfCirclesSolution::GetMMSSourceTerm(const su2double *val_coords, val_source[nDim+1] /= Velocity_Ref*Pressure_Ref; } -bool CMMSNSTwoHalfCirclesSolution::IsManufacturedSolution(void) { +bool CMMSNSTwoHalfCirclesSolution::IsManufacturedSolution(void) const { return true; } diff --git a/Common/src/toolboxes/MMS/CMMSNSTwoHalfSpheresSolution.cpp b/Common/src/toolboxes/MMS/CMMSNSTwoHalfSpheresSolution.cpp index e56638f15ec2..4eb8446b4ce1 100644 --- a/Common/src/toolboxes/MMS/CMMSNSTwoHalfSpheresSolution.cpp +++ b/Common/src/toolboxes/MMS/CMMSNSTwoHalfSpheresSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -34,7 +34,7 @@ CMMSNSTwoHalfSpheresSolution::CMMSNSTwoHalfSpheresSolution(unsigned short val_nD unsigned short val_iMesh, CConfig* config) : CVerificationSolution(val_nDim, val_nVar, val_iMesh, config) { - + /*--- Write a message that the solution is initialized for the manufactured solution for the Navier-Stokes equations between two half spheres. ---*/ if ((rank == MASTER_NODE) && (val_iMesh == MESH_0)) { @@ -117,7 +117,7 @@ CMMSNSTwoHalfSpheresSolution::~CMMSNSTwoHalfSpheresSolution(void) { } void CMMSNSTwoHalfSpheresSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /*--- The exact solution is prescribed on the boundaries. ---*/ GetSolution(val_coords, val_t, val_solution); @@ -125,7 +125,7 @@ void CMMSNSTwoHalfSpheresSolution::GetBCState(const su2double *val_coords, void CMMSNSTwoHalfSpheresSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /* Easier storage of the x-, y- and z-coordinates. */ const su2double x = val_coords[0]; @@ -166,7 +166,7 @@ void CMMSNSTwoHalfSpheresSolution::GetSolution(const su2double *val_coords, void CMMSNSTwoHalfSpheresSolution::GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source) { + su2double *val_source) const { /*--- Abbreviate Pi and the coordinates. ---*/ const su2double Pi = PI_NUMBER; @@ -370,7 +370,7 @@ void CMMSNSTwoHalfSpheresSolution::GetMMSSourceTerm(const su2double *val_coords, const su2double t616 = 0.4e1 * t18 * t528 - 0.4e1 * t20 * t528 + 0.4e1 * t24 * t533 - 0.4e1 * t26 * t533 + 0.12e2 * t541 * t12 * t7 * t410 + 0.320e3 / 0.3e1 * t545 * t155 * t112 + 0.320e3 / 0.3e1 * t545 * Viscosity * t111 * t231 + 0.64e2 * t545 * t29 * t112 - + 0.64e2 / 0.3e1 * t545 * t29 * t84 + 0.4e1 * t541 * t2 * t558 + 0.4e1 * t541 * t3 * t558 + + 0.64e2 / 0.3e1 * t545 * t29 * t84 + 0.4e1 * t541 * t2 * t558 + 0.4e1 * t541 * t3 * t558 + 0.4e1 * t541 * t72 * t486 + 0.4e1 * t305 * u_0 * (t508 * t70 * t41 + 0.16e2 * (-t10 * t511 - t10 * t513 - t10 * t515 + t34 * t570 + t34 * t573 + t34 * t576) * rho_0 + t71) + 0.4e1 * t305 * v_0 * (t508 * t176 * t41 + 0.16e2 * (t158 * t570 + t158 * t573 + t158 * t576 @@ -391,6 +391,6 @@ void CMMSNSTwoHalfSpheresSolution::GetMMSSourceTerm(const su2double *val_coords, val_source[4] /= Velocity_Ref*Pressure_Ref; } -bool CMMSNSTwoHalfSpheresSolution::IsManufacturedSolution(void) { +bool CMMSNSTwoHalfSpheresSolution::IsManufacturedSolution(void) const { return true; } diff --git a/Common/src/toolboxes/MMS/CMMSNSUnitQuadSolution.cpp b/Common/src/toolboxes/MMS/CMMSNSUnitQuadSolution.cpp index b01e7da5ca09..6f56f0ff9e82 100644 --- a/Common/src/toolboxes/MMS/CMMSNSUnitQuadSolution.cpp +++ b/Common/src/toolboxes/MMS/CMMSNSUnitQuadSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -34,7 +34,7 @@ CMMSNSUnitQuadSolution::CMMSNSUnitQuadSolution(unsigned short val_nDim, unsigned short val_iMesh, CConfig* config) : CVerificationSolution(val_nDim, val_nVar, val_iMesh, config) { - + /*--- Write a message that the solution is initialized for the manufactured solution for the Navier-Stokes equations on a unit quad. ---*/ if ((rank == MASTER_NODE) && (val_iMesh == MESH_0)) { @@ -120,7 +120,7 @@ CMMSNSUnitQuadSolution::~CMMSNSUnitQuadSolution(void) { } void CMMSNSUnitQuadSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /*--- The exact solution is prescribed on the boundaries. ---*/ GetSolution(val_coords, val_t, val_solution); @@ -128,7 +128,7 @@ void CMMSNSUnitQuadSolution::GetBCState(const su2double *val_coords, void CMMSNSUnitQuadSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /* Easier storage of the x- and y-coordinates. */ const su2double x = val_coords[0]; @@ -167,7 +167,7 @@ void CMMSNSUnitQuadSolution::GetSolution(const su2double *val_coords, void CMMSNSUnitQuadSolution::GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source) { + su2double *val_source) const { /*--- The source code for the source terms is generated in Maple. See the file CMMSNSUnitQuadSolution.mw in the directory @@ -378,6 +378,6 @@ void CMMSNSUnitQuadSolution::GetMMSSourceTerm(const su2double *val_coords, val_source[nDim+1] = t564 + t565 + t566 + t567; } -bool CMMSNSUnitQuadSolution::IsManufacturedSolution(void) { +bool CMMSNSUnitQuadSolution::IsManufacturedSolution(void) const { return true; } diff --git a/Common/src/toolboxes/MMS/CMMSNSUnitQuadSolutionWallBC.cpp b/Common/src/toolboxes/MMS/CMMSNSUnitQuadSolutionWallBC.cpp index 0fde9ad55dbe..2d005ee02fd8 100644 --- a/Common/src/toolboxes/MMS/CMMSNSUnitQuadSolutionWallBC.cpp +++ b/Common/src/toolboxes/MMS/CMMSNSUnitQuadSolutionWallBC.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -26,7 +26,7 @@ */ #include "../../../include/toolboxes/MMS/CMMSNSUnitQuadSolutionWallBC.hpp" - + CMMSNSUnitQuadSolutionWallBC::CMMSNSUnitQuadSolutionWallBC(void) : CVerificationSolution() { } CMMSNSUnitQuadSolutionWallBC::CMMSNSUnitQuadSolutionWallBC(unsigned short val_nDim, @@ -34,7 +34,7 @@ CMMSNSUnitQuadSolutionWallBC::CMMSNSUnitQuadSolutionWallBC(unsigned short val_nD unsigned short val_iMesh, CConfig* config) : CVerificationSolution(val_nDim, val_nVar, val_iMesh, config) { - + /*--- Write a message that the solution is initialized for the manufactured solution for the Navier-Stokes equations on a unit quad with no-slip wall boundary conditions. ---*/ @@ -114,7 +114,7 @@ CMMSNSUnitQuadSolutionWallBC::~CMMSNSUnitQuadSolutionWallBC(void) { } void CMMSNSUnitQuadSolutionWallBC::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /*--- The exact solution is prescribed on the boundaries. ---*/ GetSolution(val_coords, val_t, val_solution); @@ -122,7 +122,7 @@ void CMMSNSUnitQuadSolutionWallBC::GetBCState(const su2double *val_coords, void CMMSNSUnitQuadSolutionWallBC::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /* Easier storage of the y-coordinate. */ const su2double y = val_coords[1]; @@ -158,7 +158,7 @@ void CMMSNSUnitQuadSolutionWallBC::GetSolution(const su2double *val_coords, void CMMSNSUnitQuadSolutionWallBC::GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source) { + su2double *val_source) const { /*--- Abbreviate Pi and the y-coordinate. ---*/ const su2double Pi = PI_NUMBER; @@ -231,6 +231,6 @@ void CMMSNSUnitQuadSolutionWallBC::GetMMSSourceTerm(const su2double *val_coords, val_source[nDim+1] /= Velocity_Ref*Pressure_Ref; } -bool CMMSNSUnitQuadSolutionWallBC::IsManufacturedSolution(void) { +bool CMMSNSUnitQuadSolutionWallBC::IsManufacturedSolution(void) const { return true; } diff --git a/Common/src/toolboxes/MMS/CNSUnitQuadSolution.cpp b/Common/src/toolboxes/MMS/CNSUnitQuadSolution.cpp index f48b2f84b8c6..26a8c778f8bf 100644 --- a/Common/src/toolboxes/MMS/CNSUnitQuadSolution.cpp +++ b/Common/src/toolboxes/MMS/CNSUnitQuadSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -38,7 +38,7 @@ CNSUnitQuadSolution::CNSUnitQuadSolution(unsigned short val_nDim, /*--- Write a message that the solution is initialized for the Navier-Stokes case on a unit quad. Note that heat conduction is neglected for this case. ---*/ - + if ((rank == MASTER_NODE) && (val_iMesh == MESH_0)) { cout << endl; cout << "Warning: Fluid properties and solution are being " << endl; @@ -94,7 +94,7 @@ CNSUnitQuadSolution::~CNSUnitQuadSolution(void) { } void CNSUnitQuadSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /*--- The exact solution is prescribed on the boundaries. ---*/ GetSolution(val_coords, val_t, val_solution); @@ -102,7 +102,7 @@ void CNSUnitQuadSolution::GetBCState(const su2double *val_coords, void CNSUnitQuadSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /*--- Compute the flow direction and the coordinates in the rotated frame. ---*/ diff --git a/Common/src/toolboxes/MMS/CRinglebSolution.cpp b/Common/src/toolboxes/MMS/CRinglebSolution.cpp index 69e4b0aac266..a5e6f4d9a65f 100644 --- a/Common/src/toolboxes/MMS/CRinglebSolution.cpp +++ b/Common/src/toolboxes/MMS/CRinglebSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -76,7 +76,7 @@ CRinglebSolution::~CRinglebSolution(void) { } void CRinglebSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /*--- The exact solution is prescribed on the boundaries for the Ringleb flow. Note that a (much) more difficult test case is to @@ -87,7 +87,7 @@ void CRinglebSolution::GetBCState(const su2double *val_coords, void CRinglebSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { /* Easier storage of the coordinates and abbreviate y*y. */ const su2double x = val_coords[0], y = val_coords[1]; @@ -150,7 +150,7 @@ void CRinglebSolution::GetSolution(const su2double *val_coords, /* Check if the Newton algorithm actually converged. */ if(iter == iterMax) SU2_MPI::Error("Newton algorithm did not converge", CURRENT_FUNCTION); - + /* Compute the speed of sound, density and pressure. */ const su2double a = sqrt(1.0 - 0.5*Gm1*q*q); const su2double rho = pow(a,tovGm1); diff --git a/Common/src/toolboxes/MMS/CTGVSolution.cpp b/Common/src/toolboxes/MMS/CTGVSolution.cpp index 87d62d0011b6..b17ccb718f1c 100644 --- a/Common/src/toolboxes/MMS/CTGVSolution.cpp +++ b/Common/src/toolboxes/MMS/CTGVSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -34,35 +34,35 @@ CTGVSolution::CTGVSolution(unsigned short val_nDim, unsigned short val_iMesh, CConfig* config) : CVerificationSolution(val_nDim, val_nVar, val_iMesh, config) { - + /*--- Write a message that the solution is initialized for the Taylor-Green vortex test case. ---*/ - + if ((rank == MASTER_NODE) && (val_iMesh == MESH_0)) { cout << endl; cout << "Warning: Fluid properties and solution are being " << endl; cout << " initialized for the Taylor-Green vortex case!!!" << endl; cout << endl << flush; } - + /*--- Store TGV specific parameters here. ---*/ - + tgvLength = 1.0; // Taylor-Green length scale. tgvVelocity = 1.0; // Taylor-Green velocity. tgvDensity = 1.0; // Taylor-Green density. tgvPressure = 100.0; // Taylor-Green pressure. - + /*--- Useful coefficient in which Gamma is present. ---*/ - + ovGm1 = 1.0/(config->GetGamma() - 1.0); - + /*--- Perform some sanity and error checks for this solution here. ---*/ if((config->GetTime_Marching() != TIME_STEPPING) && (config->GetTime_Marching() != DT_STEPPING_1ST) && (config->GetTime_Marching() != DT_STEPPING_2ND)) SU2_MPI::Error("Unsteady mode must be selected for the Taylor Green Vortex", - CURRENT_FUNCTION); + CURRENT_FUNCTION); if(Kind_Solver != EULER && Kind_Solver != NAVIER_STOKES && Kind_Solver != RANS && Kind_Solver != FEM_EULER && Kind_Solver != FEM_NAVIER_STOKES && Kind_Solver != FEM_RANS && @@ -93,19 +93,19 @@ CTGVSolution::~CTGVSolution(void) { } void CTGVSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { - + su2double *val_solution) const { + /* The initial conditions are set for the Taylor-Green vortex case, which is a DNS case that features vortex breakdown into turbulence. These particular settings are for the typical Re = 1600 case (M = 0.08) with an initial temperature of 300 K. Note that this condition works in both 2D and 3D. */ - + su2double val_coordsZ = 0.0; if (nDim == 3) val_coordsZ = val_coords[2]; - + /* Compute the primitive variables. */ - + su2double rho = tgvDensity; su2double u = tgvVelocity * (sin(val_coords[0]/tgvLength)* cos(val_coords[1]/tgvLength)* @@ -113,17 +113,17 @@ void CTGVSolution::GetSolution(const su2double *val_coords, su2double v = -tgvVelocity * (cos(val_coords[0]/tgvLength)* sin(val_coords[1]/tgvLength)* cos(val_coordsZ /tgvLength)); - + su2double factorA = cos(2.0*val_coordsZ/tgvLength) + 2.0; su2double factorB = (cos(2.0*val_coords[0]/tgvLength) + cos(2.0*val_coords[1]/tgvLength)); - + su2double p = (tgvPressure + tgvDensity*(pow(tgvVelocity,2.0)/16.0)*factorA*factorB); - + /* Compute the conservative variables. Note that both 2D and 3D cases are treated correctly. */ - + val_solution[0] = rho; val_solution[1] = rho*u; val_solution[2] = rho*v; @@ -131,4 +131,4 @@ void CTGVSolution::GetSolution(const su2double *val_coords, val_solution[nVar-1] = p*ovGm1 + 0.5*rho*(u*u + v*v); } -bool CTGVSolution::ExactSolutionKnown(void) {return false;} +bool CTGVSolution::ExactSolutionKnown(void) const {return false;} diff --git a/Common/src/toolboxes/MMS/CUserDefinedSolution.cpp b/Common/src/toolboxes/MMS/CUserDefinedSolution.cpp index aa080483af6e..ec9424e431b2 100644 --- a/Common/src/toolboxes/MMS/CUserDefinedSolution.cpp +++ b/Common/src/toolboxes/MMS/CUserDefinedSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -34,10 +34,10 @@ CUserDefinedSolution::CUserDefinedSolution(unsigned short val_nDim, unsigned short val_iMesh, CConfig* config) : CVerificationSolution(val_nDim, val_nVar, val_iMesh, config) { - + /*--- Write a message that the solution is initialized for a user-defined verification case. ---*/ - + if ((rank == MASTER_NODE) && (val_iMesh == MESH_0)) { cout << endl; cout << "Warning: Fluid properties and solution are being " << endl; @@ -52,26 +52,26 @@ CUserDefinedSolution::~CUserDefinedSolution(void) { } void CUserDefinedSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { SU2_MPI::Error("User must implement this function", CURRENT_FUNCTION); } void CUserDefinedSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { SU2_MPI::Error("User must implement this function", CURRENT_FUNCTION); } void CUserDefinedSolution::GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source) { + su2double *val_source) const { SU2_MPI::Error("User must implement this function", CURRENT_FUNCTION); } -bool CUserDefinedSolution::IsManufacturedSolution(void) { +bool CUserDefinedSolution::IsManufacturedSolution(void) const { SU2_MPI::Error("User must implement this function", CURRENT_FUNCTION); return false; /* True if manufactured. */ } diff --git a/Common/src/toolboxes/MMS/CVerificationSolution.cpp b/Common/src/toolboxes/MMS/CVerificationSolution.cpp index 97091564f2dd..dcb9f40f1238 100644 --- a/Common/src/toolboxes/MMS/CVerificationSolution.cpp +++ b/Common/src/toolboxes/MMS/CVerificationSolution.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -41,16 +41,16 @@ CVerificationSolution::CVerificationSolution(unsigned short val_nDim, unsigned short val_iMesh, CConfig* config) { /*--- Store the kind of solver ---*/ - + Kind_Solver = config->GetKind_Solver(); - + /*--- Store the rank and size for the calculation. ---*/ - + size = SU2_MPI::GetSize(); rank = SU2_MPI::GetRank(); - + /*--- Store the dimension and number of variables. ---*/ - + nDim = val_nDim; nVar = val_nVar; @@ -88,28 +88,28 @@ CVerificationSolution::~CVerificationSolution(void) { void CVerificationSolution::GetSolution(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { SU2_MPI::Error("Function must be overwritten by the derived class", CURRENT_FUNCTION); } void CVerificationSolution::GetInitialCondition(const su2double *val_coords, - su2double *val_solution) { - + su2double *val_solution) const { + /*--- Initial conditions call the GetSolution() method at t = 0. ---*/ GetSolution(val_coords, 0.0, val_solution); } void CVerificationSolution::GetBCState(const su2double *val_coords, const su2double val_t, - su2double *val_solution) { + su2double *val_solution) const { SU2_MPI::Error("Function must be overwritten by the derived class", CURRENT_FUNCTION); } void CVerificationSolution::GetMMSSourceTerm(const su2double *val_coords, const su2double val_t, - su2double *val_source) { + su2double *val_source) const { /* Default implementation of the source terms for the method of manufactured solutions. Simply set them to zero. */ @@ -117,26 +117,26 @@ void CVerificationSolution::GetMMSSourceTerm(const su2double *val_coords, val_source[iVar] = 0.0; } -bool CVerificationSolution::IsManufacturedSolution(void) {return false;} +bool CVerificationSolution::IsManufacturedSolution(void) const {return false;} -bool CVerificationSolution::ExactSolutionKnown(void) {return true;} +bool CVerificationSolution::ExactSolutionKnown(void) const {return true;} void CVerificationSolution::GetLocalError(const su2double *val_coords, const su2double val_t, const su2double *val_solution, - su2double *val_error) { - + su2double *val_error) const { + /*--- Get the value of the verification solution first. Use val_error to store this solution. ---*/ - + GetSolution(val_coords, val_t, val_error); - + /*--- Compute the local error as the difference between the current numerical solution and the verification solution. ---*/ - + for (unsigned short iVar=0; iVarGetVolume()); - AD::SetPreaccIn(node->GetPeriodicVolume()); + AD::StartPreacc(); + AD::SetPreaccIn(node->GetVolume()); + AD::SetPreaccIn(node->GetPeriodicVolume()); - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - AD::SetPreaccIn(field(iPoint,iVar)); + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + AD::SetPreaccIn(field(iPoint,iVar)); - /*--- Clear the gradient. --*/ + /*--- Clear the gradient. --*/ - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - for (size_t iDim = 0; iDim < nDim; ++iDim) - gradient(iPoint, iVar, iDim) = 0.0; + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + for (size_t iDim = 0; iDim < nDim; ++iDim) + gradient(iPoint, iVar, iDim) = 0.0; - /*--- Handle averaging and division by volume in one constant. ---*/ + /*--- Handle averaging and division by volume in one constant. ---*/ - su2double halfOnVol = 0.5 / (node->GetVolume()+node->GetPeriodicVolume()); + su2double halfOnVol = 0.5 / (node->GetVolume()+node->GetPeriodicVolume()); - /*--- Add a contribution due to each neighbor. ---*/ + /*--- Add a contribution due to each neighbor. ---*/ - for (size_t iNeigh = 0; iNeigh < node->GetnPoint(); ++iNeigh) - { - size_t iEdge = node->GetEdge(iNeigh); - size_t jPoint = node->GetPoint(iNeigh); - - /*--- Determine if edge points inwards or outwards of iPoint. - * If inwards we need to flip the area vector. ---*/ + for (size_t iNeigh = 0; iNeigh < node->GetnPoint(); ++iNeigh) + { + size_t iEdge = node->GetEdge(iNeigh); + size_t jPoint = node->GetPoint(iNeigh); - su2double dir = (iPoint == geometry.edge[iEdge]->GetNode(0))? 1.0 : -1.0; - su2double weight = dir * halfOnVol; + /*--- Determine if edge points inwards or outwards of iPoint. + * If inwards we need to flip the area vector. ---*/ - const su2double* area = geometry.edge[iEdge]->GetNormal(); - AD::SetPreaccIn(area, nDim); + su2double dir = (iPoint == geometry.edge[iEdge]->GetNode(0))? 1.0 : -1.0; + su2double weight = dir * halfOnVol; - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - { - AD::SetPreaccIn(field(jPoint,iVar)); + const su2double* area = geometry.edge[iEdge]->GetNormal(); + AD::SetPreaccIn(area, nDim); - su2double flux = weight * (field(iPoint,iVar) + field(jPoint,iVar)); - - for (size_t iDim = 0; iDim < nDim; ++iDim) - gradient(iPoint, iVar, iDim) += flux * area[iDim]; - } + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + { + AD::SetPreaccIn(field(jPoint,iVar)); - } + su2double flux = weight * (field(iPoint,iVar) + field(jPoint,iVar)); - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) for (size_t iDim = 0; iDim < nDim; ++iDim) - AD::SetPreaccOut(gradient(iPoint,iVar,iDim)); + gradient(iPoint, iVar, iDim) += flux * area[iDim]; + } - AD::EndPreacc(); } - /*--- Add boundary fluxes. ---*/ + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + for (size_t iDim = 0; iDim < nDim; ++iDim) + AD::SetPreaccOut(gradient(iPoint,iVar,iDim)); - for (size_t iMarker = 0; iMarker < geometry.GetnMarker(); ++iMarker) + AD::EndPreacc(); + } + + /*--- Add boundary fluxes. ---*/ + + for (size_t iMarker = 0; iMarker < geometry.GetnMarker(); ++iMarker) + { + if ((config.GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && + (config.GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) { - if ((config.GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && - (config.GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) - { - /*--- Work is shared in inner loop as two markers - * may try to update the same point. ---*/ + /*--- Work is shared in inner loop as two markers + * may try to update the same point. ---*/ - SU2_OMP_FOR_STAT(OMP_MAX_CHUNK) - for (size_t iVertex = 0; iVertex < geometry.GetnVertex(iMarker); ++iVertex) - { - size_t iPoint = geometry.vertex[iMarker][iVertex]->GetNode(); - auto node = geometry.node[iPoint]; + SU2_OMP_FOR_STAT(32) + for (size_t iVertex = 0; iVertex < geometry.GetnVertex(iMarker); ++iVertex) + { + size_t iPoint = geometry.vertex[iMarker][iVertex]->GetNode(); + auto node = geometry.node[iPoint]; - /*--- Halo points do not need to be considered. ---*/ + /*--- Halo points do not need to be considered. ---*/ - if (!node->GetDomain()) continue; + if (!node->GetDomain()) continue; - su2double volume = node->GetVolume() + node->GetPeriodicVolume(); + su2double volume = node->GetVolume() + node->GetPeriodicVolume(); - const su2double* area = geometry.vertex[iMarker][iVertex]->GetNormal(); + const su2double* area = geometry.vertex[iMarker][iVertex]->GetNormal(); - for (size_t iVar = varBegin; iVar < varEnd; iVar++) - { - su2double flux = field(iPoint,iVar) / volume; + for (size_t iVar = varBegin; iVar < varEnd; iVar++) + { + su2double flux = field(iPoint,iVar) / volume; - for (size_t iDim = 0; iDim < nDim; iDim++) - gradient(iPoint, iVar, iDim) -= flux * area[iDim]; - } + for (size_t iDim = 0; iDim < nDim; iDim++) + gradient(iPoint, iVar, iDim) -= flux * area[iDim]; } } } - - } // end SU2_OMP_PARALLEL + } /*--- If no solver was provided we do not communicate ---*/ - if (solver == nullptr) return; - - /*--- Account for periodic contributions. ---*/ - - for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic()/2; ++iPeriodic) + SU2_OMP_MASTER + if (solver != nullptr) { - solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm); - solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm); - } + /*--- Account for periodic contributions. ---*/ - /*--- Obtain the gradients at halo points from the MPI ranks that own them. ---*/ + for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic()/2; ++iPeriodic) + { + solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm); + solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm); + } - solver->InitiateComms(&geometry, &config, kindMpiComm); - solver->CompleteComms(&geometry, &config, kindMpiComm); + /*--- Obtain the gradients at halo points from the MPI ranks that own them. ---*/ + + solver->InitiateComms(&geometry, &config, kindMpiComm); + solver->CompleteComms(&geometry, &config, kindMpiComm); + } + SU2_OMP_BARRIER } diff --git a/SU2_CFD/include/gradients/computeGradientsLeastSquares.hpp b/SU2_CFD/include/gradients/computeGradientsLeastSquares.hpp index 5db466a82922..d9e6b402bd5e 100644 --- a/SU2_CFD/include/gradients/computeGradientsLeastSquares.hpp +++ b/SU2_CFD/include/gradients/computeGradientsLeastSquares.hpp @@ -70,246 +70,241 @@ void computeGradientsLeastSquares(CSolver* solver, omp_get_max_threads(), OMP_MAX_CHUNK); #endif - /*--- Start OpenMP parallel section. ---*/ + /*--- First loop over non-halo points of the grid. ---*/ - SU2_OMP_PARALLEL + SU2_OMP_FOR_DYN(chunkSize) + for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint) { - /*--- First loop over non-halo points of the grid. ---*/ + auto node = geometry.node[iPoint]; + const su2double* coord_i = node->GetCoord(); - SU2_OMP_FOR_DYN(chunkSize) - for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint) - { - auto node = geometry.node[iPoint]; - const su2double* coord_i = node->GetCoord(); + AD::StartPreacc(); + AD::SetPreaccIn(coord_i, nDim); - AD::StartPreacc(); - AD::SetPreaccIn(coord_i, nDim); + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + AD::SetPreaccIn(field(iPoint,iVar)); - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - AD::SetPreaccIn(field(iPoint,iVar)); + /*--- Clear gradient and Rmatrix. ---*/ - /*--- Clear gradient and Rmatrix. ---*/ + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + for (size_t iDim = 0; iDim < nDim; ++iDim) + gradient(iPoint, iVar, iDim) = 0.0; - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - for (size_t iDim = 0; iDim < nDim; ++iDim) - gradient(iPoint, iVar, iDim) = 0.0; + for (size_t iDim = 0; iDim < nDim; ++iDim) + for (size_t jDim = 0; jDim < nDim; ++jDim) + Rmatrix(iPoint, iDim, jDim) = 0.0; - for (size_t iDim = 0; iDim < nDim; ++iDim) - for (size_t jDim = 0; jDim < nDim; ++jDim) - Rmatrix(iPoint, iDim, jDim) = 0.0; + for (size_t iNeigh = 0; iNeigh < node->GetnPoint(); ++iNeigh) + { + size_t jPoint = node->GetPoint(iNeigh); + + const su2double* coord_j = geometry.node[jPoint]->GetCoord(); + AD::SetPreaccIn(coord_j, nDim); - for (size_t iNeigh = 0; iNeigh < node->GetnPoint(); ++iNeigh) - { - size_t jPoint = node->GetPoint(iNeigh); + /*--- Distance vector from iPoint to jPoint ---*/ - const su2double* coord_j = geometry.node[jPoint]->GetCoord(); - AD::SetPreaccIn(coord_j, nDim); + su2double dist_ij[MAXNDIM] = {0.0}; - /*--- Distance vector from iPoint to jPoint ---*/ + for (size_t iDim = 0; iDim < nDim; ++iDim) + dist_ij[iDim] = coord_j[iDim] - coord_i[iDim]; + + /*--- Compute inverse weight, default 1 (unweighted). ---*/ - su2double dist_ij[MAXNDIM] = {0.0}; + su2double weight = 1.0; + if (weighted) + { + weight = 0.0; for (size_t iDim = 0; iDim < nDim; ++iDim) - dist_ij[iDim] = coord_j[iDim] - coord_i[iDim]; + weight += dist_ij[iDim] * dist_ij[iDim]; + } - /*--- Compute inverse weight, default 1 (unweighted). ---*/ + /*--- Sumations for entries of upper triangular matrix R. ---*/ - su2double weight = 1.0; + if (weight > 0.0) + { + weight = 1.0 / weight; + + Rmatrix(iPoint,0,0) += dist_ij[0]*dist_ij[0]*weight; + Rmatrix(iPoint,0,1) += dist_ij[0]*dist_ij[1]*weight; + Rmatrix(iPoint,1,1) += dist_ij[1]*dist_ij[1]*weight; - if (weighted) + if (nDim == 3) { - weight = 0.0; - for (size_t iDim = 0; iDim < nDim; ++iDim) - weight += dist_ij[iDim] * dist_ij[iDim]; + Rmatrix(iPoint,0,2) += dist_ij[0]*dist_ij[2]*weight; + Rmatrix(iPoint,1,2) += dist_ij[1]*dist_ij[2]*weight; + Rmatrix(iPoint,2,1) += dist_ij[0]*dist_ij[2]*weight; + Rmatrix(iPoint,2,2) += dist_ij[2]*dist_ij[2]*weight; } - /*--- Sumations for entries of upper triangular matrix R. ---*/ + /*--- Entries of c:= transpose(A)*b ---*/ - if (weight > 0.0) + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) { - weight = 1.0 / weight; - - Rmatrix(iPoint,0,0) += dist_ij[0]*dist_ij[0]*weight; - Rmatrix(iPoint,0,1) += dist_ij[0]*dist_ij[1]*weight; - Rmatrix(iPoint,1,1) += dist_ij[1]*dist_ij[1]*weight; + AD::SetPreaccIn(field(jPoint,iVar)); - if (nDim == 3) - { - Rmatrix(iPoint,0,2) += dist_ij[0]*dist_ij[2]*weight; - Rmatrix(iPoint,1,2) += dist_ij[1]*dist_ij[2]*weight; - Rmatrix(iPoint,2,1) += dist_ij[0]*dist_ij[2]*weight; - Rmatrix(iPoint,2,2) += dist_ij[2]*dist_ij[2]*weight; - } + su2double delta_ij = weight * (field(jPoint,iVar) - field(iPoint,iVar)); - /*--- Entries of c:= transpose(A)*b ---*/ - - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - { - AD::SetPreaccIn(field(jPoint,iVar)); - - su2double delta_ij = weight * (field(jPoint,iVar) - field(iPoint,iVar)); - - for (size_t iDim = 0; iDim < nDim; ++iDim) - gradient(iPoint, iVar, iDim) += dist_ij[iDim] * delta_ij; - } + for (size_t iDim = 0; iDim < nDim; ++iDim) + gradient(iPoint, iVar, iDim) += dist_ij[iDim] * delta_ij; } } + } - for (size_t iDim = 0; iDim < nDim; ++iDim) - for (size_t jDim = 0; jDim < nDim; ++jDim) - AD::SetPreaccOut(Rmatrix(iPoint, iDim, jDim)); + for (size_t iDim = 0; iDim < nDim; ++iDim) + for (size_t jDim = 0; jDim < nDim; ++jDim) + AD::SetPreaccOut(Rmatrix(iPoint, iDim, jDim)); - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - for (size_t iDim = 0; iDim < nDim; ++iDim) - AD::SetPreaccOut(gradient(iPoint, iVar, iDim)); + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + for (size_t iDim = 0; iDim < nDim; ++iDim) + AD::SetPreaccOut(gradient(iPoint, iVar, iDim)); - AD::EndPreacc(); - } + AD::EndPreacc(); + } - /*--- Correct the gradient values across any periodic boundaries. ---*/ + /*--- Correct the gradient values across any periodic boundaries. ---*/ - if (solver != nullptr) + SU2_OMP_MASTER + if (solver != nullptr) + { + for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic()/2; ++iPeriodic) { - SU2_OMP_MASTER - { - for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic()/2; ++iPeriodic) - { - solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm); - solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm); - } - } - SU2_OMP_BARRIER + solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm); + solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm); } + } + SU2_OMP_BARRIER - /*--- Second loop over points of the grid to compute final gradient. ---*/ + /*--- Second loop over points of the grid to compute final gradient. ---*/ - SU2_OMP_FOR_DYN(chunkSize) - for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint) - { - /*--- Entries of upper triangular matrix R. ---*/ - - su2double r11 = Rmatrix(iPoint,0,0); - su2double r12 = Rmatrix(iPoint,0,1); - su2double r22 = Rmatrix(iPoint,1,1); - su2double r13 = 0.0, r23 = 0.0, r23_a = 0.0, r23_b = 0.0, r33 = 0.0; - - AD::StartPreacc(); - AD::SetPreaccIn(r11); - AD::SetPreaccIn(r12); - AD::SetPreaccIn(r22); - - if (r11 >= 0.0) r11 = sqrt(r11); - if (r11 >= 0.0) r12 /= r11; else r12 = 0.0; - su2double tmp = r22-r12*r12; - if (tmp >= 0.0) r22 = sqrt(tmp); else r22 = 0.0; - - if (nDim == 3) { - r13 = Rmatrix(iPoint,0,2); - r23_a = Rmatrix(iPoint,1,2); - r23_b = Rmatrix(iPoint,2,1); - r33 = Rmatrix(iPoint,2,2); - - AD::SetPreaccIn(r13); - AD::SetPreaccIn(r23_a); - AD::SetPreaccIn(r23_b); - AD::SetPreaccIn(r33); - - if (r11 >= 0.0) r13 /= r11; else r13 = 0.0; - - if ((r22 >= 0.0) && (r11*r22 >= 0.0)) { - r23 = r23_a/r22 - r23_b*r12/(r11*r22); - } else { - r23 = 0.0; - } - - tmp = r33 - r23*r23 - r13*r13; - if (tmp >= 0.0) r33 = sqrt(tmp); else r33 = 0.0; + SU2_OMP_FOR_DYN(chunkSize) + for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint) + { + /*--- Entries of upper triangular matrix R. ---*/ + + su2double r11 = Rmatrix(iPoint,0,0); + su2double r12 = Rmatrix(iPoint,0,1); + su2double r22 = Rmatrix(iPoint,1,1); + su2double r13 = 0.0, r23 = 0.0, r23_a = 0.0, r23_b = 0.0, r33 = 0.0; + + AD::StartPreacc(); + AD::SetPreaccIn(r11); + AD::SetPreaccIn(r12); + AD::SetPreaccIn(r22); + + if (r11 >= 0.0) r11 = sqrt(r11); + if (r11 >= 0.0) r12 /= r11; else r12 = 0.0; + su2double tmp = r22-r12*r12; + if (tmp >= 0.0) r22 = sqrt(tmp); else r22 = 0.0; + + if (nDim == 3) { + r13 = Rmatrix(iPoint,0,2); + r23_a = Rmatrix(iPoint,1,2); + r23_b = Rmatrix(iPoint,2,1); + r33 = Rmatrix(iPoint,2,2); + + AD::SetPreaccIn(r13); + AD::SetPreaccIn(r23_a); + AD::SetPreaccIn(r23_b); + AD::SetPreaccIn(r33); + + if (r11 >= 0.0) r13 /= r11; else r13 = 0.0; + + if ((r22 >= 0.0) && (r11*r22 >= 0.0)) { + r23 = r23_a/r22 - r23_b*r12/(r11*r22); + } else { + r23 = 0.0; } - /*--- Compute determinant ---*/ + tmp = r33 - r23*r23 - r13*r13; + if (tmp >= 0.0) r33 = sqrt(tmp); else r33 = 0.0; + } - su2double detR2 = (r11*r22)*(r11*r22); - if (nDim == 3) detR2 *= r33*r33; + /*--- Compute determinant ---*/ - /*--- Detect singular matrices ---*/ + su2double detR2 = (r11*r22)*(r11*r22); + if (nDim == 3) detR2 *= r33*r33; - bool singular = false; + /*--- Detect singular matrices ---*/ - if (detR2 <= EPS) { - detR2 = 1.0; - singular = true; - } + bool singular = false; - /*--- S matrix := inv(R)*traspose(inv(R)) ---*/ + if (detR2 <= EPS) { + detR2 = 1.0; + singular = true; + } - su2double Smatrix[MAXNDIM][MAXNDIM]; + /*--- S matrix := inv(R)*traspose(inv(R)) ---*/ - if (singular) { - for (size_t iDim = 0; iDim < nDim; ++iDim) - for (size_t jDim = 0; jDim < nDim; ++jDim) - Smatrix[iDim][jDim] = 0.0; - } - else { - if (nDim == 2) { - Smatrix[0][0] = (r12*r12+r22*r22)/detR2; - Smatrix[0][1] = -r11*r12/detR2; - Smatrix[1][0] = Smatrix[0][1]; - Smatrix[1][1] = r11*r11/detR2; - } - else { - su2double z11 = r22*r33; - su2double z12 =-r12*r33; - su2double z13 = r12*r23-r13*r22; - su2double z22 = r11*r33; - su2double z23 =-r11*r23; - su2double z33 = r11*r22; - - Smatrix[0][0] = (z11*z11+z12*z12+z13*z13)/detR2; - Smatrix[0][1] = (z12*z22+z13*z23)/detR2; - Smatrix[0][2] = (z13*z33)/detR2; - Smatrix[1][0] = Smatrix[0][1]; - Smatrix[1][1] = (z22*z22+z23*z23)/detR2; - Smatrix[1][2] = (z23*z33)/detR2; - Smatrix[2][0] = Smatrix[0][2]; - Smatrix[2][1] = Smatrix[1][2]; - Smatrix[2][2] = (z33*z33)/detR2; - } - } + su2double Smatrix[MAXNDIM][MAXNDIM]; + if (singular) { for (size_t iDim = 0; iDim < nDim; ++iDim) for (size_t jDim = 0; jDim < nDim; ++jDim) - AD::SetPreaccOut(Smatrix[iDim][jDim]); + Smatrix[iDim][jDim] = 0.0; + } + else { + if (nDim == 2) { + Smatrix[0][0] = (r12*r12+r22*r22)/detR2; + Smatrix[0][1] = -r11*r12/detR2; + Smatrix[1][0] = Smatrix[0][1]; + Smatrix[1][1] = r11*r11/detR2; + } + else { + su2double z11 = r22*r33; + su2double z12 =-r12*r33; + su2double z13 = r12*r23-r13*r22; + su2double z22 = r11*r33; + su2double z23 =-r11*r23; + su2double z33 = r11*r22; + + Smatrix[0][0] = (z11*z11+z12*z12+z13*z13)/detR2; + Smatrix[0][1] = (z12*z22+z13*z23)/detR2; + Smatrix[0][2] = (z13*z33)/detR2; + Smatrix[1][0] = Smatrix[0][1]; + Smatrix[1][1] = (z22*z22+z23*z23)/detR2; + Smatrix[1][2] = (z23*z33)/detR2; + Smatrix[2][0] = Smatrix[0][2]; + Smatrix[2][1] = Smatrix[1][2]; + Smatrix[2][2] = (z33*z33)/detR2; + } + } - AD::EndPreacc(); + for (size_t iDim = 0; iDim < nDim; ++iDim) + for (size_t jDim = 0; jDim < nDim; ++jDim) + AD::SetPreaccOut(Smatrix[iDim][jDim]); - /*--- Computation of the gradient: S*c ---*/ + AD::EndPreacc(); - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - { - su2double Cvector[MAXNDIM]; + /*--- Computation of the gradient: S*c ---*/ - for (size_t iDim = 0; iDim < nDim; ++iDim) - { - Cvector[iDim] = 0.0; - for (size_t jDim = 0; jDim < nDim; ++jDim) - Cvector[iDim] += Smatrix[iDim][jDim] * gradient(iPoint, iVar, jDim); - } + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + { + su2double Cvector[MAXNDIM]; - for (size_t iDim = 0; iDim < nDim; ++iDim) - gradient(iPoint, iVar, iDim) = Cvector[iDim]; + for (size_t iDim = 0; iDim < nDim; ++iDim) + { + Cvector[iDim] = 0.0; + for (size_t jDim = 0; jDim < nDim; ++jDim) + Cvector[iDim] += Smatrix[iDim][jDim] * gradient(iPoint, iVar, jDim); } - } - } // end SU2_OMP_PARALLEL + for (size_t iDim = 0; iDim < nDim; ++iDim) + gradient(iPoint, iVar, iDim) = Cvector[iDim]; + } + } /*--- If no solver was provided we do not communicate ---*/ - if (solver == nullptr) return; - - /*--- Obtain the gradients at halo points from the MPI ranks that own them. ---*/ + SU2_OMP_MASTER + if (solver != nullptr) + { + /*--- Obtain the gradients at halo points from the MPI ranks that own them. ---*/ - solver->InitiateComms(&geometry, &config, kindMpiComm); - solver->CompleteComms(&geometry, &config, kindMpiComm); + solver->InitiateComms(&geometry, &config, kindMpiComm); + solver->CompleteComms(&geometry, &config, kindMpiComm); + } + SU2_OMP_BARRIER } diff --git a/SU2_CFD/include/integration/CFEM_DG_Integration.hpp b/SU2_CFD/include/integration/CFEM_DG_Integration.hpp new file mode 100644 index 000000000000..a54c67d57043 --- /dev/null +++ b/SU2_CFD/include/integration/CFEM_DG_Integration.hpp @@ -0,0 +1,83 @@ +/*! + * \file CFEM_DG_Integration.hpp + * \brief Declaration of class for integration with the FEM DG solver. + * \author E. van der Weide, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "CIntegration.hpp" + +/*! + * \class CFEM_DG_Integration + * \brief Class for integration with the FEM DG solver. + * \author E. van der Weide, T. Economon + * \version 7.0.1 "Blackbird" + */ +class CFEM_DG_Integration final : public CIntegration { +public: + /*! + * \brief Constructor of the class. + * \param[in] config - Definition of the particular problem. + */ + CFEM_DG_Integration(CConfig *config); + + /*! + * \brief Do the numerical integration (implicit) of the turbulence solver. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + void SingleGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) override; + +private: + /*! + * \brief Perform the spatial integration of the numerical system. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] solver - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + * \param[in] iStep - Current step of the Runge-Kutta iteration for the RK schemes + and the step in the local time stepping for ADER-DG. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + void Space_Integration(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, CConfig *config, + unsigned short iMesh, unsigned short iStep, unsigned short RunTime_EqSystem); + + /*! + * \brief Perform the time integration (explicit or implicit) of the numerical system. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] iStep - Current step of the Runge-Kutta iteration for the RK schemes + and the step in the local time stepping for ADER-DG. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] Iteration - Current iteration. + */ + void Time_Integration(CGeometry *geometry, CSolver **solver_container, CConfig *config, + unsigned short iStep, unsigned short RunTime_EqSystem); +}; diff --git a/SU2_CFD/include/integration/CIntegration.hpp b/SU2_CFD/include/integration/CIntegration.hpp new file mode 100644 index 000000000000..123c7fad3122 --- /dev/null +++ b/SU2_CFD/include/integration/CIntegration.hpp @@ -0,0 +1,194 @@ +/*! + * \file CIntegration.hpp + * \brief Declaration of the main routines to orchestrate space and time integration. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#include +#include +#include + +#include "../solvers/CSolver.hpp" +#include "../../../Common/include/geometry/CGeometry.hpp" +#include "../../../Common/include/CConfig.hpp" + +using namespace std; + +/*! + * \class CIntegration + * \brief Main class for doing the space integration, time integration, and monitoring + * of a system of Partial Differential Equations (PDE). + * \author F. Palacios + */ +class CIntegration { +protected: + int rank, /*!< \brief MPI Rank. */ + size; /*!< \brief MPI Size. */ + su2double + Cauchy_Value, /*!< \brief Summed value of the convergence indicator. */ + Cauchy_Func; /*!< \brief Current value of the convergence indicator at one iteration. */ + unsigned short Cauchy_Counter; /*!< \brief Number of elements of the Cauchy serial. */ + vector Cauchy_Serie; /*!< \brief Complete Cauchy serial. */ + su2double + Old_Func, /*!< \brief Old value of the objective function (the function which is monitored). */ + New_Func; /*!< \brief Current value of the objective function (the function which is monitored). */ + bool Convergence, /*!< \brief To indicate if the flow solver (direct, adjoint, or linearized) has converged or not. */ + Convergence_FSI, /*!< \brief To indicate if the FSI problem has converged or not. */ + Convergence_FullMG; /*!< \brief To indicate if the Full Multigrid has converged and it is necessary to add a new level. */ + su2double InitResidual; /*!< \brief Initial value of the residual to evaluate the convergence level. */ + + /*! + * \brief Do the space integration of the numerical system. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] solver - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + * \param[in] iRKStep - Current step of the Runge-Kutta iteration. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + void Space_Integration(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, + CConfig *config, unsigned short iMesh, unsigned short iRKStep, + unsigned short RunTime_EqSystem); + + /*! + * \brief Do the time integration (explicit or implicit) of the numerical system. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] iRKStep - Current step of the Runge-Kutta iteration. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + void Time_Integration(CGeometry *geometry, CSolver **solver_container, CConfig *config, + unsigned short iRKStep, unsigned short RunTime_EqSystem); + +public: + /*! + * \brief Constructor of the class. + */ + CIntegration(CConfig *config); + + /*! + * \brief Destructor of the class. + */ + virtual ~CIntegration(void) = default; + + /*! + * \brief Get the value of the convergence. + * \return Level of convergence of the solution. + */ + inline su2double GetCauchy_Value(void) const { return Cauchy_Value; } + + /*! + * \brief Get the indicator of the convergence for the direct, adjoint and linearized problem. + * \return TRUE means that the convergence criteria is satisfied; + * otherwise FALSE. + */ + inline bool GetConvergence(void) const { return Convergence; } + + /*! + * \brief Get the indicator of the convergence for the Fluid-Structure Interaction problem. + * \return TRUE means that the convergence criteria is satisfied; + * otherwise FALSE. + */ + inline bool GetConvergence_FSI(void) const { return Convergence_FSI; } + + /*! + * \brief Set the indicator of the convergence. + * \param[in] value - TRUE means that the convergence criteria is satisfied; + * otherwise FALSE. + */ + inline void SetConvergence(bool value) { Convergence = value; } + + + /*! + * \brief Set the indicator of the convergence for FSI. + * \param[in] valueFSI - TRUE means that the convergence criteria for FSI is satisfied; + * otherwise FALSE. + */ + inline void SetConvergence_FSI(bool valueFSI) { Convergence_FSI = valueFSI; } + + + /*! + * \brief Get the indicator of the convergence for the full multigrid problem. + * \return TRUE means that the convergence criteria is satisfied; + * otherwise FALSE. + */ + inline bool GetConvergence_FullMG(void) const { return Convergence_FullMG; } + + /*! + * \brief Save the solution, and volume at different time steps. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solution - Flow solution. + * \param[in] config - Definition of the particular problem. + */ + void SetDualTime_Solver(CGeometry *geometry, CSolver *solver, CConfig *config, unsigned short iMesh); + + /*! + * \brief Save the structural solution at different time steps. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Structural solution. + * \param[in] config - Definition of the particular problem. + */ + void SetStructural_Solver(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh); + + /*! + * \brief A virtual member. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + virtual void MultiGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) { }; + + /*! + * \brief A virtual member. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + virtual void SingleGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) { }; + + /*! + * \brief A virtual member. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + virtual void Structural_Iteration(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) { }; + +}; diff --git a/SU2_CFD/include/integration/CMultiGridIntegration.hpp b/SU2_CFD/include/integration/CMultiGridIntegration.hpp new file mode 100644 index 000000000000..9e8d57b9f416 --- /dev/null +++ b/SU2_CFD/include/integration/CMultiGridIntegration.hpp @@ -0,0 +1,184 @@ +/*! + * \file CMultiGridIntegration.hpp + * \brief Declaration of class for time integration using a multigrid method. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "CIntegration.hpp" + +/*! + * \class CMultiGridIntegration + * \brief Class for time integration using a multigrid method. + * \author F. Palacios + */ +class CMultiGridIntegration final : public CIntegration { +public: + /*! + * \brief Constructor of the class. + * \param[in] config - Definition of the particular problem. + */ + CMultiGridIntegration(CConfig *config); + + /*! + * \brief This subroutine calls the MultiGrid_Cycle and also prepare the multigrid levels and the monitoring. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] Iteration - Current iteration. + */ + void MultiGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) override; + +private: + /*! + * \brief Perform a Full-Approximation Storage (FAS) Multigrid. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + * \param[in] mu - Variable for controlling the kind of multigrid algorithm. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] Iteration - Current iteration. + */ + void MultiGrid_Cycle(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short iMesh, unsigned short mu, unsigned short RunTime_EqSystem, + unsigned short iZone, unsigned short iInst); + + /*! + * \brief Compute the forcing term. + * \param[in] sol_fine - Pointer to the solution on the fine grid. + * \param[in] sol_coarse - Pointer to the solution on the coarse grid. + * \param[in] geo_fine - Geometrical definition of the fine grid. + * \param[in] geo_coarse - Geometrical definition of the coarse grid. + * \param[in] config - Definition of the particular problem. + */ + void SetForcing_Term(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, + CGeometry *geo_coarse, CConfig *config, unsigned short iMesh); + + /*! + * \brief Add the truncation error to the residual. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] flow - Flow solution. + */ + void SetResidual_Term(CGeometry *geometry, CSolver *flow); + + /*! + * \brief Set the value of the corrected fine grid solution. + * \param[out] sol_fine - Pointer to the solution on the fine grid. + * \param[in] geo_fine - Geometrical definition of the fine grid. + * \param[in] config - Definition of the particular problem. + */ + void SetProlongated_Correction(CSolver *sol_fine, CGeometry *geo_fine, CConfig *config, unsigned short iMesh); + + /*! + * \brief Compute the gradient in coarse grid using the fine grid information. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] sol_fine - Pointer to the solution on the fine grid. + * \param[out] sol_coarse - Pointer to the solution on the coarse grid. + * \param[in] geo_fine - Geometrical definition of the fine grid. + * \param[in] geo_coarse - Geometrical definition of the coarse grid. + * \param[in] config - Definition of the particular problem. + */ + void SetRestricted_Gradient(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); + + /*! + * \brief Compute the non-dimensional parameters. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] Iteration - Current iteration. + * \param[in] monitor - value of the non-dimensional parameters for monitoring the convergence. + */ + void NonDimensional_Parameters(CGeometry **geometry, CSolver ***solver_container, CNumerics ****numerics_container, + CConfig *config, unsigned short FinestMesh, unsigned short RunTime_EqSystem, + su2double *monitor); + + /*! + * \brief Compute the fine solution from a coarse solution. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[out] sol_fine - Pointer to the solution on the fine grid. + * \param[in] sol_coarse - Pointer to the solution on the coarse grid. + * \param[in] geo_fine - Geometrical definition of the fine grid. + * \param[in] geo_coarse - Geometrical definition of the coarse grid. + * \param[in] config - Definition of the particular problem. + */ + void SetProlongated_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); + + /*! + * \brief Compute the fine grid correction from the coarse solution. + * \param[out] sol_fine - Pointer to the solution on the fine grid. + * \param[in] sol_coarse - Pointer to the solution on the coarse grid. + * \param[in] geo_fine - Geometrical definition of the fine grid. + * \param[in] geo_coarse - Geometrical definition of the coarse grid. + * \param[in] config - Definition of the particular problem. + */ + void GetProlongated_Correction(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); + + /*! + * \brief Do an implicit smoothing of the prolongated correction. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] solution - Container vector with all the solutions on the finest grid. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] val_nSmooth - Number of smoothing iterations. + * \param[in] val_smooth_coeff - Relaxation factor. + * \param[in] config - Definition of the particular problem. + */ + void SmoothProlongated_Correction(unsigned short RunTime_EqSystem, CSolver *solver, CGeometry *geometry, + unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config); + + /*! + * \brief Restrict solution from fine grid to a coarse grid. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] sol_fine - Pointer to the solution on the fine grid. + * \param[out] sol_coarse - Pointer to the solution on the coarse grid. + * \param[in] geo_fine - Geometrical definition of the fine grid. + * \param[in] geo_coarse - Geometrical definition of the coarse grid. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + * \param[in] InclSharedDomain - Include the shared domain in the interpolation. + */ + void SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); + + /*! + * \brief Initialize the adjoint solution using the primal problem. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] Iteration - Current iteration. + */ + void Adjoint_Setup(CGeometry ****geometry, CSolver *****solver_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned long Iteration, unsigned short iZone); + +}; diff --git a/SU2_CFD/include/integration/CSingleGridIntegration.hpp b/SU2_CFD/include/integration/CSingleGridIntegration.hpp new file mode 100644 index 000000000000..614d424b7ee3 --- /dev/null +++ b/SU2_CFD/include/integration/CSingleGridIntegration.hpp @@ -0,0 +1,84 @@ +/*! + * \file CSingleGridIntegration.hpp + * \brief Declaration of class for numerical integration of fine grid-only problems. + * \author A. Bueno. + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "CIntegration.hpp" + +/*! + * \class CSingleGridIntegration + * \brief Class for numerical integration of fine grid-only problems (e.g. turbulence). + * \author A. Bueno. + */ +class CSingleGridIntegration final : public CIntegration { +private: + /*! + * \brief Restrict solution from fine grid to a coarse grid. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] sol_fine - Pointer to the solution on the fine grid. + * \param[out] sol_coarse - Pointer to the solution on the coarse grid. + * \param[in] geo_fine - Geometrical definition of the fine grid. + * \param[in] geo_coarse - Geometrical definition of the coarse grid. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + * \param[in] InclSharedDomain - Include the shared domain in the interpolation. + */ + void SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); + + /*! + * \brief Restrict solution from fine grid to a coarse grid. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] sol_fine - Pointer to the solution on the fine grid. + * \param[out] sol_coarse - Pointer to the solution on the coarse grid. + * \param[in] geo_fine - Geometrical definition of the fine grid. + * \param[in] geo_coarse - Geometrical definition of the coarse grid. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - Index of the mesh in multigrid computations. + * \param[in] InclSharedDomain - Include the shared domain in the interpolation. + */ + void SetRestricted_EddyVisc(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); + +public: + /*! + * \brief Constructor of the class. + * \param[in] config - Definition of the particular problem. + */ + CSingleGridIntegration(CConfig *config); + + /*! + * \brief Do the numerical integration (implicit) of the turbulence solver. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + void SingleGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) override; + +}; diff --git a/SU2_CFD/include/integration/CStructuralIntegration.hpp b/SU2_CFD/include/integration/CStructuralIntegration.hpp new file mode 100644 index 000000000000..d83aae75b8e2 --- /dev/null +++ b/SU2_CFD/include/integration/CStructuralIntegration.hpp @@ -0,0 +1,77 @@ +/*! + * \file CStructuralIntegration.hpp + * \brief Declaration of class for numerical integration of structural problems. + * \author R. Sanchez. + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "CIntegration.hpp" + +/*! + * \class CStructuralIntegration + * \brief Class for numerical integration of structural problems. + * \author R. Sanchez. + */ +class CStructuralIntegration final : public CIntegration { +public: + /*! + * \brief Constructor of the class. + * \param[in] config - Definition of the particular problem. + */ + CStructuralIntegration(CConfig *config); + + /*! + * \brief Do the numerical integration (implicit) of the structural solver. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + void Structural_Iteration(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) override; + +private: + /*! + * \brief Do the space integration of the numerical system on a FEM framework. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] solver - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + */ + void Space_Integration_FEM(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, + CConfig *config, unsigned short RunTime_EqSystem); + + /*! + * \brief Do the time integration (explicit or implicit) of the numerical system on a FEM framework. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] RunTime_EqSystem - System of equations which is going to be solved. + * \param[in] Iteration - Current iteration. + */ + void Time_Integration_FEM(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, + CConfig *config, unsigned short RunTime_EqSystem); +}; diff --git a/SU2_CFD/include/integration_structure.hpp b/SU2_CFD/include/integration_structure.hpp deleted file mode 100644 index 203829c34702..000000000000 --- a/SU2_CFD/include/integration_structure.hpp +++ /dev/null @@ -1,709 +0,0 @@ -/*! - * \file integration_structure.hpp - * \brief Headers of the main subroutines for space and time integration. - * The subroutines and functions are in the integration_structure.cpp, - * integration_time.cpp, and integration_notime.cpp files. - * \author F. Palacios, T. Economon - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, 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/mpi_structure.hpp" - -#include -#include -#include - -#include "solvers/CSolver.hpp" -#include "../../Common/include/geometry/CGeometry.hpp" -#include "../../Common/include/CConfig.hpp" - -using namespace std; - -/*! - * \class CIntegration - * \brief Main class for doing the space integration, time integration, and monitoring - * of a system of Partial Differential Equations (PDE). - * \author F. Palacios - */ -class CIntegration { -protected: - int rank, /*!< \brief MPI Rank. */ - size; /*!< \brief MPI Size. */ - su2double - Cauchy_Value, /*!< \brief Summed value of the convergence indicator. */ - Cauchy_Func; /*!< \brief Current value of the convergence indicator at one iteration. */ - unsigned short Cauchy_Counter; /*!< \brief Number of elements of the Cauchy serial. */ - su2double *Cauchy_Serie; /*!< \brief Complete Cauchy serial. */ - su2double - Old_Func, /*!< \brief Old value of the objective function (the function which is monitored). */ - New_Func; /*!< \brief Current value of the objective function (the function which is monitored). */ - bool Convergence, /*!< \brief To indicate if the flow solver (direct, adjoint, or linearized) has converged or not. */ - Convergence_FSI, /*!< \brief To indicate if the FSI problem has converged or not. */ - Convergence_FullMG; /*!< \brief To indicate if the Full Multigrid has converged and it is necessary to add a new level. */ - su2double InitResidual; /*!< \brief Initial value of the residual to evaluate the convergence level. */ - -public: - - /*! - * \brief Constructor of the class. - */ - CIntegration(CConfig *config); - - /*! - * \brief Destructor of the class. - */ - virtual ~CIntegration(void); - - /*! - * \brief Do the space integration of the numerical system. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] solver - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] iRKStep - Current step of the Runge-Kutta iteration. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - void Space_Integration(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, CConfig *config, - unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem); - - /*! - * \brief Do the space integration of the numerical system on a FEM framework. - * \author R. Sanchez - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] solver - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - void Space_Integration_FEM(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, CConfig *config, - unsigned short RunTime_EqSystem); - - /*! - * \brief Do the time integration (explicit or implicit) of the numerical system. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iRKStep - Current step of the Runge-Kutta iteration. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - void Time_Integration(CGeometry *geometry, CSolver **solver_container, CConfig *config, - unsigned short iRKStep, unsigned short RunTime_EqSystem); - - /*! - * \brief Do the time integration (explicit or implicit) of the numerical system on a FEM framework. - * \author R. Sanchez - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] Iteration - Current iteration. - */ - void Time_Integration_FEM(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, CConfig *config, - unsigned short RunTime_EqSystem); - - /*! - * \brief Initialize the adjoint solution using the primal problem. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] Iteration - Current iteration. - */ - void Adjoint_Setup(CGeometry ****geometry, CSolver *****solver_container, CConfig **config, - unsigned short RunTime_EqSystem, unsigned long Iteration, unsigned short iZone); - - /*! - * \brief Average the scalar output in case there is a unsteady solution. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - * \param[in] Iteration - Current iteration. - * \param[in] monitor - Objective function to be averaged. - * \param[in] iMesh - Index of the mesh. - */ - void Average_Monitoring(CGeometry *geometry, CConfig *config, - unsigned long Iteration, su2double monitor, unsigned short iMesh); - - /*! - * \brief Get the value of the convergence. - * \return Level of convergence of the solution. - */ - su2double GetCauchy_Value(void); - - /*! - * \brief Get the indicator of the convergence for the direct, adjoint and linearized problem. - * \return TRUE means that the convergence criteria is satisfied; - * otherwise FALSE. - */ - bool GetConvergence(void); - - /*! - * \brief Get the indicator of the convergence for the Fluid-Structure Interaction problem. - * \return TRUE means that the convergence criteria is satisfied; - * otherwise FALSE. - */ - bool GetConvergence_FSI(void); - - /*! - * \brief Set the indicator of the convergence. - * \param[in] value - TRUE means that the convergence criteria is satisfied; - * otherwise FALSE. - */ - void SetConvergence(bool value); - - - /*! - * \brief Set the indicator of the convergence for FSI. - * \param[in] valueFSI - TRUE means that the convergence criteria for FSI is satisfied; - * otherwise FALSE. - */ - void SetConvergence_FSI(bool valueFSI); - - - /*! - * \brief Get the indicator of the convergence for the full multigrid problem. - * \return TRUE means that the convergence criteria is satisfied; - * otherwise FALSE. - */ - bool GetConvergence_FullMG(void); - - /*! - * \brief Save the solution, and volume at different time steps. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solution - Flow solution. - * \param[in] config - Definition of the particular problem. - */ - void SetDualTime_Solver(CGeometry *geometry, CSolver *solver, CConfig *config, unsigned short iMesh); - - /*! - * \brief Save the structural solution at different time steps. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solution - Structural solution. - * \param[in] config - Definition of the particular problem. - */ - void SetStructural_Solver(CGeometry *geometry, CSolver *solver, CConfig *config, unsigned short iMesh); - - /*! - * \brief Save the structural solution at different time steps. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Structural solution. - * \param[in] config - Definition of the particular problem. - */ - void SetFEM_StructuralSolver(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh); - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - virtual void MultiGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst); - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] mu - Variable for controlling the kind of multigrid algorithm. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - virtual void MultiGrid_Cycle(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short iMesh, unsigned short mu, unsigned short RunTime_EqSystem, - unsigned short iZone, unsigned short iInst); - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] monitor - value of the non-dimensional parameters for monitoring the convergence. - */ - virtual void NonDimensional_Parameters(CGeometry **geometry, CSolver ***solver_container, CNumerics ****numerics_container, - CConfig *config, unsigned short FinestMesh, unsigned short RunTime_EqSystem, - su2double *monitor); - - /*! - * \brief A virtual member. - * \param[out] sol_fine - Pointer to the solution on the fine grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] config - Definition of the particular problem. - */ - virtual void SetProlongated_Correction(CSolver *sol_fine, CGeometry *geo_fine, CConfig *config, unsigned short iMesh); - - /*! - * \brief A virtual member. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[out] sol_fine - Pointer to the solution on the fine grid. - * \param[in] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - */ - virtual void SetProlongated_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, - CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief A virtual member. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[out] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - */ - virtual void SetRestricted_Residual(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, - CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief A virtual member. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[out] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] InclSharedDomain - Include the shared domain in the interpolation. - */ - virtual void SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief A virtual member. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[out] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] InclSharedDomain - Include the shared domain in the interpolation. - */ - virtual void SetRestricted_EddyVisc(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief A virtual member. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[out] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - */ - virtual void SetRestricted_Gradient(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, - CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] flow - Flow solution. - */ - virtual void SetResidual_Term(CGeometry *geometry, CSolver *flow); - - /*! - * \brief A virtual member. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[in] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - */ - virtual void SetForcing_Term(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, - CConfig *config, unsigned short iMesh); - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - virtual void SingleGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst); - - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - virtual void Structural_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst); - - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] iMesh - Index of the mesh in multigrid computations. - */ - virtual void SetPotential_Solver(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iMesh, unsigned short iZone); - - /*! - * \brief A virtual member. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] solution - Container vector with all the solutions on the finest grid. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] val_nSmooth - Number of smoothing iterations. - * \param[in] val_smooth_coeff - Relaxation factor. - * \param[in] config - Definition of the particular problem. - */ - virtual void Smooth_Solution(unsigned short RunTime_EqSystem, CSolver *solver, CGeometry *geometry, - unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config); - -}; - -/*! - * \class CMultiGridIntegration - * \brief Class for doing the numerical integration using a multigrid method. - * \author F. Palacios - */ -class CMultiGridIntegration : public CIntegration { -protected: - -public: - - /*! - * \brief Constructor of the class. - * \param[in] config - Definition of the particular problem. - */ - CMultiGridIntegration(CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CMultiGridIntegration(void); - - /*! - * \brief This subroutine calls the MultiGrid_Cycle and also prepare the multigrid levels and the monitoring. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] Iteration - Current iteration. - */ - void MultiGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst); - - /*! - * \brief Perform a Full-Approximation Storage (FAS) Multigrid. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] mu - Variable for controlling the kind of multigrid algorithm. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] Iteration - Current iteration. - */ - void MultiGrid_Cycle(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short iMesh, unsigned short mu, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst); - - /*! - * \brief Compute the non-dimensional parameters. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] Iteration - Current iteration. - * \param[in] monitor - value of the non-dimensional parameters for monitoring the convergence. - */ - void NonDimensional_Parameters(CGeometry **geometry, CSolver ***solver_container, CNumerics ****numerics_container, - CConfig *config, unsigned short FinestMesh, unsigned short RunTime_EqSystem, - su2double *monitor); - - /*! - * \brief Compute the fine solution from a coarse solution. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[out] sol_fine - Pointer to the solution on the fine grid. - * \param[in] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - */ - void SetProlongated_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, - CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief Compute the fine grid correction from the coarse solution. - * \param[out] sol_fine - Pointer to the solution on the fine grid. - * \param[in] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - */ - void GetProlongated_Correction(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, - CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief Do an implicit smoothing of the prolongated correction. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] solution - Container vector with all the solutions on the finest grid. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] val_nSmooth - Number of smoothing iterations. - * \param[in] val_smooth_coeff - Relaxation factor. - * \param[in] config - Definition of the particular problem. - */ - void SmoothProlongated_Correction(unsigned short RunTime_EqSystem, CSolver *solver, CGeometry *geometry, - unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config); - - /*! - * \brief Do an implicit smoothing of the solution. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] solution - Container vector with all the solutions on the finest grid. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] val_nSmooth - Number of smoothing iterations. - * \param[in] val_smooth_coeff - Relaxation factor. - * \param[in] config - Definition of the particular problem. - */ - void Smooth_Solution(unsigned short RunTime_EqSystem, CSolver *solver, CGeometry *geometry, - unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config); - - /*! - * \brief Set the value of the corrected fine grid solution. - * \param[out] sol_fine - Pointer to the solution on the fine grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] config - Definition of the particular problem. - */ - void SetProlongated_Correction(CSolver *sol_fine, CGeometry *geo_fine, CConfig *config, unsigned short iMesh); - - /*! - * \brief Compute truncation error in the coarse grid using the fine grid information. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[out] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - */ - void SetRestricted_Residual(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, - CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief Restrict solution from fine grid to a coarse grid. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[out] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] InclSharedDomain - Include the shared domain in the interpolation. - */ - void SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief Compute the gradient in coarse grid using the fine grid information. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[out] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - */ - void SetRestricted_Gradient(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, - CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief Add the truncation error to the residual. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] flow - Flow solution. - */ - void SetResidual_Term(CGeometry *geometry, CSolver *flow); - - /*! - * \brief Compute the forcing term. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[in] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - */ - void SetForcing_Term(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, - CConfig *config, unsigned short iMesh); -}; - -/*! - * \class CSingleGridIntegration - * \brief Class for doing the numerical integration of the turbulence model. - * \author A. Bueno. - */ -class CSingleGridIntegration : public CIntegration { -public: - - /*! - * \brief Constructor of the class. - * \param[in] config - Definition of the particular problem. - */ - CSingleGridIntegration(CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSingleGridIntegration(void); - - /*! - * \brief Do the numerical integration (implicit) of the turbulence solver. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - void SingleGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst); - - /*! - * \brief Restrict solution from fine grid to a coarse grid. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[out] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] InclSharedDomain - Include the shared domain in the interpolation. - */ - void SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); - - /*! - * \brief Restrict solution from fine grid to a coarse grid. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] sol_fine - Pointer to the solution on the fine grid. - * \param[out] sol_coarse - Pointer to the solution on the coarse grid. - * \param[in] geo_fine - Geometrical definition of the fine grid. - * \param[in] geo_coarse - Geometrical definition of the coarse grid. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] InclSharedDomain - Include the shared domain in the interpolation. - */ - void SetRestricted_EddyVisc(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config); - -}; - - -/*! - * \class CStructuralIntegration - * \brief Class for doing the numerical integration of the structural model. - * \author R. Sanchez. - */ -class CStructuralIntegration : public CIntegration { -public: - - /*! - * \brief Constructor of the class. - * \param[in] config - Definition of the particular problem. - */ - CStructuralIntegration(CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CStructuralIntegration(void); - - /*! - * \brief Do the numerical integration (implicit) of the structural solver. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - void Structural_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst); - -}; - -/*! - * \class CFEM_DG_Integration - * \brief Class for integration with the FEM DG solver. - * \author E. van der Weide, T. Economon - * \version 7.0.1 "Blackbird" - */ -class CFEM_DG_Integration : public CIntegration { -public: - - /*! - * \brief Constructor of the class. - * \param[in] config - Definition of the particular problem. - */ - CFEM_DG_Integration(CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CFEM_DG_Integration(void); - - /*! - * \brief Do the numerical integration (implicit) of the turbulence solver. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] numerics_container - Description of the numerical method (the way in which the equations are solved). - * \param[in] config - Definition of the particular problem. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - void SingleGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst); - /*! - * \brief Perform the spatial integration of the numerical system. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] solver - Description of the numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] iStep - Current step of the Runge-Kutta iteration for the RK schemes - and the step in the local time stepping for ADER-DG. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - */ - void Space_Integration(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, CConfig *config, - unsigned short iMesh, unsigned short iStep, unsigned short RunTime_EqSystem); - - /*! - * \brief Perform the time integration (explicit or implicit) of the numerical system. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iStep - Current step of the Runge-Kutta iteration for the RK schemes - and the step in the local time stepping for ADER-DG. - * \param[in] RunTime_EqSystem - System of equations which is going to be solved. - * \param[in] Iteration - Current iteration. - */ - void Time_Integration(CGeometry *geometry, CSolver **solver_container, CConfig *config, - unsigned short iStep, unsigned short RunTime_EqSystem); -}; - -#include "integration_structure.inl" diff --git a/SU2_CFD/include/integration_structure.inl b/SU2_CFD/include/integration_structure.inl deleted file mode 100644 index 8c16529cc9b8..000000000000 --- a/SU2_CFD/include/integration_structure.inl +++ /dev/null @@ -1,83 +0,0 @@ -/*! - * \file integration_structure.inl - * \brief In-Line subroutines of the integration_structure.hpp file. - * \author F. Palacios, T. Economon - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, 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 - -inline su2double CIntegration::GetCauchy_Value(void) { return Cauchy_Value; } - -inline bool CIntegration::GetConvergence(void) { return Convergence; } - -inline bool CIntegration::GetConvergence_FSI(void) { return Convergence_FSI; } - -inline bool CIntegration::GetConvergence_FullMG(void) { return Convergence_FullMG; } - -inline void CIntegration::SetConvergence(bool value) { Convergence = value; } - -inline void CIntegration::SetConvergence_FSI(bool valueFSI) { Convergence_FSI = valueFSI; } - -inline void CIntegration::MultiGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) { } - -inline void CIntegration::MultiGrid_Cycle(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short iMesh, unsigned short mu, unsigned short RunTime_EqSystem, - unsigned short iZone, unsigned short iInst) { } - -inline void CIntegration::NonDimensional_Parameters(CGeometry **geometry, CSolver ***solver_container, CNumerics ****numerics_container, - CConfig *config, unsigned short FinestMesh, unsigned short RunTime_EqSystem, - su2double *monitor) { } - -inline void CIntegration::SetProlongated_Correction(CSolver *sol_fine, CGeometry *geo_fine, CConfig *config, unsigned short iMesh) { } - -inline void CIntegration::SetProlongated_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, - CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { } - -inline void CIntegration::SetRestricted_Residual(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, - CGeometry *geo_coarse, CConfig *config) { } - -inline void CIntegration::SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { } - -inline void CIntegration::SetRestricted_EddyVisc(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { } - -inline void CIntegration::SetRestricted_Gradient(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, - CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { } - -inline void CIntegration::SetResidual_Term(CGeometry *geometry, CSolver *flow) { } - -inline void CIntegration::SetForcing_Term(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, - CConfig *config, unsigned short iMesh) { } - -inline void CIntegration::SingleGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) { } - -inline void CIntegration::Structural_Iteration(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) { } - - -inline void CIntegration::SetPotential_Solver(CGeometry ****geometry, CSolver *****solver_container, CNumerics ******numerics_container, - CConfig **config, unsigned short RunTime_EqSystem, unsigned short iMesh, unsigned short iZone) { } - -inline void CIntegration::Smooth_Solution(unsigned short RunTime_EqSystem, CSolver *solver, CGeometry *geometry, unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config) { } diff --git a/SU2_CFD/include/iteration_structure.hpp b/SU2_CFD/include/iteration_structure.hpp index 388609f12a1d..e41869967d3a 100644 --- a/SU2_CFD/include/iteration_structure.hpp +++ b/SU2_CFD/include/iteration_structure.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -28,17 +28,14 @@ #pragma once -#include "../../Common/include/mpi_structure.hpp" - #include -#include "integration_structure.hpp" - -#include "output/COutput.hpp" -#include "numerics_structure.hpp" - +#include "../../Common/include/mpi_structure.hpp" +#include "../../Common/include/geometry/CGeometry.hpp" #include "../../Common/include/grid_movement_structure.hpp" +#include "output/COutput.hpp" #include "../../Common/include/CConfig.hpp" +#include "../include/integration/CIntegration.hpp" using namespace std; @@ -53,7 +50,7 @@ class CIteration { size; /*!< \brief MPI Size. */ unsigned short nZone; /*!< \brief Total number of zones in the problem. */ unsigned short nInst; /*!< \brief Total number of instances in the problem. */ - + bool multizone, /*!< \brief Flag for multizone problems. */ singlezone; /*!< \brief Flag for singlezone problems. */ @@ -62,12 +59,12 @@ class CIteration { UsedTime; public: - + /*! * \brief Constructor of the class. */ CIteration(CConfig *config); - + /*! * \brief Destructor of the class. */ @@ -103,7 +100,7 @@ class CIteration { CNumerics ***numerics_container, CConfig *config_container, unsigned short kind_recording); - + /*! * \brief A virtual member. * \param[in] ??? - Description here. @@ -119,7 +116,7 @@ class CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief A virtual member. * \param[in] output - Pointer to the COutput class. @@ -143,7 +140,7 @@ class CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief A virtual member. * \param[in] output - Pointer to the COutput class. @@ -191,7 +188,7 @@ class CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief A virtual member. * \param[in] output - Pointer to the COutput class. @@ -255,7 +252,7 @@ class CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief A virtual member. * \param[in] ??? - Description here. @@ -268,7 +265,7 @@ class CIteration { bool StopCalc, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief A virtual member. * \param[in] output - Pointer to the COutput class. @@ -358,18 +355,18 @@ class CIteration { */ class CFluidIteration : public CIteration { public: - + /*! * \brief Constructor of the class. * \param[in] config - Definition of the particular problem. */ CFluidIteration(CConfig *config); - + /*! * \brief Destructor of the class. */ ~CFluidIteration(void); - + /*! * \brief Preprocessing to prepare for an iteration of the physics. * \param[in] ??? - Description here. @@ -385,7 +382,7 @@ class CFluidIteration : public CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Perform a single iteration of the fluid system. * \param[in] output - Pointer to the COutput class. @@ -409,7 +406,7 @@ class CFluidIteration : public CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Iterate the fluid system for a number of Inner_Iter iterations. * \param[in] output - Pointer to the COutput class. @@ -449,7 +446,7 @@ class CFluidIteration : public CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Monitors the convergence and other metrics for the fluid system. * \param[in] ??? - Description here. @@ -465,7 +462,7 @@ class CFluidIteration : public CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Postprocesses the fluid system before heading to another physics system or the next iteration. * \param[in] solver - Container vector with all the solutions. @@ -483,7 +480,7 @@ class CFluidIteration : public CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Imposes a gust via the grid velocities. * \author S. Padron @@ -492,7 +489,7 @@ class CFluidIteration : public CIteration { * \param[in] solver - Container vector with all the solutions. */ void SetWind_GustField(CConfig *config, CGeometry **geometry, CSolver ***solver); - + /*! * \brief Reads and initializes the vortex positions, strengths and gradient. * \author S. Padron @@ -503,7 +500,7 @@ class CFluidIteration : public CIteration { * \param[in] r_core - Vector of vortex core size. */ void InitializeVortexDistribution(unsigned long &nVortex, vector& x0, vector& y0, vector& vort_strength, vector& r_core); - + /*! * \brief Fixed CL monitoring function @@ -512,7 +509,7 @@ class CFluidIteration : public CIteration { * \param[in] geometry - Geometrical definition of the problem. * \param[in] solver - Pointer to the flow solver * \param[in] config - Definition of the particular problem. - * \return Boolean indicating weather calculation should be stopped + * \return Boolean indicating weather calculation should be stopped */ bool MonitorFixed_CL(COutput *output, CGeometry *geometry, CSolver **solver, CConfig *config); }; @@ -583,18 +580,18 @@ class CTurboIteration : public CFluidIteration { */ class CFEMFluidIteration : public CFluidIteration { public: - + /*! * \brief Constructor of the class. * \param[in] config - Definition of the particular problem. */ CFEMFluidIteration(CConfig *config); - + /*! * \brief Destructor of the class. */ ~CFEMFluidIteration(void); - + /*! * \brief Preprocessing to prepare for an iteration of the physics. * \param[in] output - Pointer to the COutput class. @@ -641,7 +638,7 @@ class CFEMFluidIteration : public CFluidIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Updates the containers for the finite element flow system. * \param[in] ??? - Description here. @@ -657,7 +654,7 @@ class CFEMFluidIteration : public CFluidIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Postprocess routine for the finite element flow system. * \param[in] solver - Container vector with all the solutions. @@ -685,18 +682,18 @@ class CFEMFluidIteration : public CFluidIteration { class CHeatIteration : public CFluidIteration { public: - + /*! * \brief Constructor of the class. * \param[in] config - Definition of the particular problem. */ CHeatIteration(CConfig *config); - + /*! * \brief Destructor of the class. */ ~CHeatIteration(void); - + /*! * \brief Perform a single iteration of the heat system. * \param[in] output - Pointer to the COutput class. @@ -938,7 +935,6 @@ class CFEAIteration : public CIteration { unsigned short val_iZone, unsigned short val_iInst); - }; /*! @@ -948,18 +944,18 @@ class CFEAIteration : public CIteration { */ class CAdjFluidIteration : public CFluidIteration { public: - + /*! * \brief Constructor of the class. * \param[in] config - Definition of the particular problem. */ CAdjFluidIteration(CConfig *config); - + /*! * \brief Destructor of the class. */ ~CAdjFluidIteration(void); - + /*! * \brief Preprocessing to prepare for an iteration of the physics. * \param[in] ??? - Description here. @@ -975,7 +971,7 @@ class CAdjFluidIteration : public CFluidIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Perform a single iteration of the adjoint fluid system. * \param[in] output - Pointer to the COutput class. @@ -999,7 +995,7 @@ class CAdjFluidIteration : public CFluidIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Updates the containers for the adjoint fluid system. * \param[in] ??? - Description here. @@ -1015,9 +1011,9 @@ class CAdjFluidIteration : public CFluidIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - - + + }; /*! @@ -1034,18 +1030,18 @@ class CDiscAdjFluidIteration : public CIteration { bool turbulent; /*!< \brief Stores the turbulent flag. */ public: - + /*! * \brief Constructor of the class. * \param[in] config - Definition of the particular problem. */ CDiscAdjFluidIteration(CConfig *config); - + /*! * \brief Destructor of the class. */ ~CDiscAdjFluidIteration(void); - + /*! * \brief Preprocessing to prepare for an iteration of the physics. * \brief Perform a single iteration of the adjoint fluid system. @@ -1072,7 +1068,7 @@ class CDiscAdjFluidIteration : public CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Perform a single iteration of the adjoint fluid system. * \param[in] output - Pointer to the COutput class. @@ -1098,7 +1094,7 @@ class CDiscAdjFluidIteration : public CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Updates the containers for the discrete adjoint fluid system. @@ -1125,7 +1121,7 @@ class CDiscAdjFluidIteration : public CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Monitors the convergence and other metrics for the discrete adjoint fluid system. * \param[in] output - Pointer to the COutput class. @@ -1151,7 +1147,7 @@ class CDiscAdjFluidIteration : public CIteration { CFreeFormDefBox*** FFDBox, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Postprocess the discrete adjoint fluid iteration. * \param[in] output - Pointer to the COutput class. @@ -1492,7 +1488,7 @@ class CDiscAdjFEAIteration : public CIteration { */ void RegisterOutput(CSolver *****solver, CGeometry ****geometry, CConfig** config, unsigned short iZone, unsigned short iInst); using CIteration::RegisterOutput; - + /*! * \brief Initializes the adjoints of the output variables of the FEM iteration. * \param[in] solver - Container vector with all the solutions. @@ -1722,7 +1718,7 @@ class CDiscAdjHeatIteration : public CIteration { bool StopCalc, unsigned short val_iZone, unsigned short val_iInst); - + /*! * \brief Perform a single iteration of the adjoint fluid system. diff --git a/SU2_CFD/include/limiters/CLimiterDetails.hpp b/SU2_CFD/include/limiters/CLimiterDetails.hpp index f3ccf6e2972d..99e852eb44aa 100644 --- a/SU2_CFD/include/limiters/CLimiterDetails.hpp +++ b/SU2_CFD/include/limiters/CLimiterDetails.hpp @@ -1,6 +1,6 @@ /*! * \file CLimiterDetails.hpp - * \brief A template class that allows defining limiters via + * \brief A class template that allows defining limiters via * specialization of particular details. * \author P. Gomes * \version 7.0.1 "Blackbird" @@ -155,7 +155,7 @@ struct CLimiterDetails template<> struct CLimiterDetails { - su2activematrix fieldMin, fieldMax; + static su2activevector sharedMin, sharedMax; su2activevector eps2; /*! @@ -165,75 +165,68 @@ struct CLimiterDetails inline void preprocess(CGeometry& geometry, CConfig& config, size_t varBegin, size_t varEnd, const FieldType& field) { - /*--- Determine the max and min global value for each variable. - * Each thread initially works on one row of fieldMin/Max (the - * rows are padded to a multiple of 8 to avoid false sharing), - * then the master thread performs a reduction over all threads - * and mpi ranks onto row 0, the final result. ---*/ + /*--- Determine the max and min global value for each variable. ---*/ - size_t nThread = omp_get_num_threads(); - size_t nCols = roundUpDiv(varEnd,8)*8; + su2double largeNum = 0.1*std::numeric_limits::max(); + + /*--- Allocate the static members (shared between threads) to + * perform the reduction across all threads in the rank. ---*/ SU2_OMP_MASTER { - su2double largeNum = 0.1*std::numeric_limits::max(); - fieldMin.resize(nThread, nCols) = largeNum; - fieldMax.resize(nThread, nCols) =-largeNum; - eps2.resize(nCols); + sharedMin.resize(varEnd) = largeNum; + sharedMax.resize(varEnd) =-largeNum; } SU2_OMP_BARRIER /*--- Per thread reduction. ---*/ - SU2_OMP_FOR_STAT(512) + su2activevector localMin(varEnd), localMax(varEnd); + localMin = largeNum; + localMax =-largeNum; + + SU2_OMP(for schedule(static, 512) nowait) for(size_t iPoint = 0; iPoint < geometry.GetnPointDomain(); ++iPoint) { - size_t iThread = omp_get_thread_num(); - for(size_t iVar = varBegin; iVar < varEnd; ++iVar) { - fieldMin(iThread, iVar) = min(fieldMin(iThread, iVar), field(iPoint, iVar)); - fieldMax(iThread, iVar) = max(fieldMax(iThread, iVar), field(iPoint, iVar)); + localMin(iVar) = min(localMin(iVar), field(iPoint, iVar)); + localMax(iVar) = max(localMax(iVar), field(iPoint, iVar)); } } - SU2_OMP_MASTER - { - /*--- Per rank reduction. ---*/ + /*--- Per rank reduction. ---*/ - for(size_t iThread = 1; iThread < nThread; ++iThread) - { - for(size_t iVar = varBegin; iVar < varEnd; ++iVar) - { - fieldMin(0,iVar) = min(fieldMin(0,iVar), fieldMin(iThread, iVar)); - fieldMax(0,iVar) = max(fieldMax(0,iVar), fieldMax(iThread, iVar)); - } - } - - /*--- Global reduction, (re)using eps2 as the recv buffer. ---*/ - - SU2_MPI::Allreduce(fieldMin[0], eps2.data(), nCols, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); + SU2_OMP_CRITICAL + for(size_t iVar = varBegin; iVar < varEnd; ++iVar) + { + sharedMin(iVar) = min(sharedMin(iVar), localMin(iVar)); + sharedMax(iVar) = max(sharedMax(iVar), localMax(iVar)); + } + SU2_OMP_BARRIER - for(size_t iVar = varBegin; iVar < varEnd; ++iVar) - fieldMin(0,iVar) = eps2(iVar); + /*--- Global reduction. ---*/ - SU2_MPI::Allreduce(fieldMax[0], eps2.data(), nCols, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + SU2_OMP_MASTER + { + localMin = sharedMin; + SU2_MPI::Allreduce(localMin.data(), sharedMin.data(), varEnd, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); - for(size_t iVar = varBegin; iVar < varEnd; ++iVar) - fieldMax(0,iVar) = eps2(iVar); + localMax = sharedMax; + SU2_MPI::Allreduce(localMax.data(), sharedMax.data(), varEnd, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + } + SU2_OMP_BARRIER - /*--- Compute eps^2 ---*/ + /*--- Compute eps^2 (each thread has its own copy of it). ---*/ - su2double K = config.GetVenkat_LimiterCoeff(); + eps2.resize(varEnd); + su2double K = config.GetVenkat_LimiterCoeff(); - for(size_t iVar = varBegin; iVar < varEnd; ++iVar) - { - su2double range = fieldMax(0,iVar) - fieldMin(0,iVar); - eps2(iVar) = max(pow(K*range, 2), LimiterHelpers::epsilon()); - } + for(size_t iVar = varBegin; iVar < varEnd; ++iVar) + { + su2double range = sharedMax(iVar) - sharedMin(iVar); + eps2(iVar) = max(pow(K*range, 2), LimiterHelpers::epsilon()); } - SU2_OMP_BARRIER - } /*! diff --git a/SU2_CFD/include/limiters/computeLimiters.hpp b/SU2_CFD/include/limiters/computeLimiters.hpp index 2db8361c8fce..36820d1fa292 100644 --- a/SU2_CFD/include/limiters/computeLimiters.hpp +++ b/SU2_CFD/include/limiters/computeLimiters.hpp @@ -58,13 +58,10 @@ computeLimiters_impl(solver, kindMpiComm, \ switch (LimiterKind) { case NO_LIMITER: { - SU2_OMP_PARALLEL - { - SU2_OMP_FOR_STAT(512) - for(size_t iPoint = 0; iPoint < geometry.GetnPoint(); ++iPoint) - for(size_t iVar = varBegin; iVar < varEnd; ++iVar) - limiter(iPoint, iVar) = 1.0; - } + SU2_OMP_FOR_STAT(512) + for(size_t iPoint = 0; iPoint < geometry.GetnPoint(); ++iPoint) + for(size_t iVar = varBegin; iVar < varEnd; ++iVar) + limiter(iPoint, iVar) = 1.0; break; } case BARTH_JESPERSEN: diff --git a/SU2_CFD/include/limiters/computeLimiters_impl.hpp b/SU2_CFD/include/limiters/computeLimiters_impl.hpp index c2f5a1a68e6f..fbe5fd061250 100644 --- a/SU2_CFD/include/limiters/computeLimiters_impl.hpp +++ b/SU2_CFD/include/limiters/computeLimiters_impl.hpp @@ -1,7 +1,8 @@ /*! * \file computeLimiters_impl.hpp - * \brief Generic and general computation of limiters. - * \note Common methods are derived by defining only small details. + * \brief Generic computation of limiters. + * \note Common methods are derived by defining small details + * via specialization of CLimiterDetails. * \author P. Gomes * \version 7.0.1 "Blackbird" * @@ -28,7 +29,7 @@ /*! - * \brief General limiter computation for methods based on one limiter + * \brief Generic limiter computation for methods based on one limiter * value per point (as opposed to one per edge) and per variable. * \note This implementation can be used to derive most common methods * by specializing the limiter functions (e.g. Venkatakrishnan) @@ -79,8 +80,6 @@ void computeLimiters_impl(CSolver* solver, if (varEnd > MAXNVAR) SU2_MPI::Error("Number of variables is too large, increase MAXNVAR.", CURRENT_FUNCTION); - CLimiterDetails limiterDetails; - size_t nPointDomain = geometry.GetnPointDomain(); size_t nPoint = geometry.GetnPoint(); size_t nDim = geometry.GetnDim(); @@ -109,135 +108,129 @@ void computeLimiters_impl(CSolver* solver, } #endif - /*--- Start OpenMP parallel section. ---*/ + CLimiterDetails limiterDetails; - SU2_OMP_PARALLEL - { - limiterDetails.preprocess(geometry, config, varBegin, varEnd, field); + limiterDetails.preprocess(geometry, config, varBegin, varEnd, field); - /*--- Courtesy barrier in case someone forgets preprocess is parallel. ---*/ - SU2_OMP_BARRIER + /*--- Initialize all min/max field values if we have + * periodic comms. otherwise do it inside main loop. ---*/ - /*--- Initialize all min/max field values if we have - * periodic comms. otherwise do it inside main loop. ---*/ + if (periodic) + { + SU2_OMP_FOR_STAT(chunkSize) + for (size_t iPoint = 0; iPoint < nPoint; ++iPoint) + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + fieldMax(iPoint,iVar) = fieldMin(iPoint,iVar) = field(iPoint,iVar); - if (periodic) + SU2_OMP_MASTER { - SU2_OMP_FOR_STAT(chunkSize) - for (size_t iPoint = 0; iPoint < nPoint; ++iPoint) - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - fieldMax(iPoint,iVar) = fieldMin(iPoint,iVar) = field(iPoint,iVar); - - SU2_OMP_MASTER + for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic()/2; ++iPeriodic) { - for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic()/2; ++iPeriodic) - { - solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm1); - solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm1); - } + solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm1); + solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm1); } - SU2_OMP_BARRIER } + SU2_OMP_BARRIER + } - /*--- Compute limiter for each point. ---*/ + /*--- Compute limiter for each point. ---*/ - SU2_OMP_FOR_DYN(chunkSize) - for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint) - { - auto node = geometry.node[iPoint]; - const su2double* coord_i = node->GetCoord(); + SU2_OMP_FOR_DYN(chunkSize) + for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint) + { + auto node = geometry.node[iPoint]; + const su2double* coord_i = node->GetCoord(); - AD::StartPreacc(); - AD::SetPreaccIn(coord_i, nDim); + AD::StartPreacc(); + AD::SetPreaccIn(coord_i, nDim); - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - { - AD::SetPreaccIn(field(iPoint,iVar)); - - if (periodic) { - /*--- Started outside loop, so counts as input. ---*/ - AD::SetPreaccIn(fieldMax(iPoint,iVar)); - AD::SetPreaccIn(fieldMin(iPoint,iVar)); - } - else { - /*--- Initialize min/max now for iPoint if not periodic. ---*/ - fieldMax(iPoint,iVar) = field(iPoint,iVar); - fieldMin(iPoint,iVar) = field(iPoint,iVar); - } + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + { + AD::SetPreaccIn(field(iPoint,iVar)); - for(size_t iDim = 0; iDim < nDim; ++iDim) - AD::SetPreaccIn(gradient(iPoint,iVar,iDim)); + if (periodic) { + /*--- Started outside loop, so counts as input. ---*/ + AD::SetPreaccIn(fieldMax(iPoint,iVar)); + AD::SetPreaccIn(fieldMin(iPoint,iVar)); + } + else { + /*--- Initialize min/max now for iPoint if not periodic. ---*/ + fieldMax(iPoint,iVar) = field(iPoint,iVar); + fieldMin(iPoint,iVar) = field(iPoint,iVar); } - /*--- Initialize min/max projection out of iPoint. ---*/ + for(size_t iDim = 0; iDim < nDim; ++iDim) + AD::SetPreaccIn(gradient(iPoint,iVar,iDim)); + } - su2double projMax[MAXNVAR], projMin[MAXNVAR]; + /*--- Initialize min/max projection out of iPoint. ---*/ - for (size_t iVar = varBegin; iVar < varEnd; ++iVar) - projMax[iVar] = projMin[iVar] = 0.0; + su2double projMax[MAXNVAR], projMin[MAXNVAR]; - /*--- Compute max/min projection and values over direct neighbors. ---*/ + for (size_t iVar = varBegin; iVar < varEnd; ++iVar) + projMax[iVar] = projMin[iVar] = 0.0; - for(size_t iNeigh = 0; iNeigh < node->GetnPoint(); ++iNeigh) - { - size_t jPoint = node->GetPoint(iNeigh); + /*--- Compute max/min projection and values over direct neighbors. ---*/ - const su2double* coord_j = geometry.node[jPoint]->GetCoord(); - AD::SetPreaccIn(coord_j, nDim); + for(size_t iNeigh = 0; iNeigh < node->GetnPoint(); ++iNeigh) + { + size_t jPoint = node->GetPoint(iNeigh); - /*--- Distance vector from iPoint to face (middle of the edge). ---*/ + const su2double* coord_j = geometry.node[jPoint]->GetCoord(); + AD::SetPreaccIn(coord_j, nDim); - su2double dist_ij[MAXNDIM] = {0.0}; + /*--- Distance vector from iPoint to face (middle of the edge). ---*/ - for(size_t iDim = 0; iDim < nDim; ++iDim) - dist_ij[iDim] = 0.5 * (coord_j[iDim] - coord_i[iDim]); + su2double dist_ij[MAXNDIM] = {0.0}; - /*--- Project each variable, update min/max. ---*/ + for(size_t iDim = 0; iDim < nDim; ++iDim) + dist_ij[iDim] = 0.5 * (coord_j[iDim] - coord_i[iDim]); - for(size_t iVar = varBegin; iVar < varEnd; ++iVar) - { - su2double proj = 0.0; + /*--- Project each variable, update min/max. ---*/ - for(size_t iDim = 0; iDim < nDim; ++iDim) - proj += dist_ij[iDim] * gradient(iPoint,iVar,iDim); + for(size_t iVar = varBegin; iVar < varEnd; ++iVar) + { + su2double proj = 0.0; - projMax[iVar] = max(projMax[iVar], proj); - projMin[iVar] = min(projMin[iVar], proj); + for(size_t iDim = 0; iDim < nDim; ++iDim) + proj += dist_ij[iDim] * gradient(iPoint,iVar,iDim); - AD::SetPreaccIn(field(jPoint,iVar)); + projMax[iVar] = max(projMax[iVar], proj); + projMin[iVar] = min(projMin[iVar], proj); - fieldMax(iPoint,iVar) = max(fieldMax(iPoint,iVar), field(jPoint,iVar)); - fieldMin(iPoint,iVar) = min(fieldMin(iPoint,iVar), field(jPoint,iVar)); - } - } + AD::SetPreaccIn(field(jPoint,iVar)); - /*--- Compute the geometric factor. ---*/ + fieldMax(iPoint,iVar) = max(fieldMax(iPoint,iVar), field(jPoint,iVar)); + fieldMin(iPoint,iVar) = min(fieldMin(iPoint,iVar), field(jPoint,iVar)); + } + } - su2double geoFactor = limiterDetails.geometricFactor(iPoint, geometry); + /*--- Compute the geometric factor. ---*/ - /*--- Final limiter computation for each variable, get the min limiter - * out of the positive/negative projections and deltas. ---*/ + su2double geoFactor = limiterDetails.geometricFactor(iPoint, geometry); - for(size_t iVar = varBegin; iVar < varEnd; ++iVar) - { - su2double limMax = limiterDetails.limiterFunction(iVar, projMax[iVar], - fieldMax(iPoint,iVar) - field(iPoint,iVar)); + /*--- Final limiter computation for each variable, get the min limiter + * out of the positive/negative projections and deltas. ---*/ - su2double limMin = limiterDetails.limiterFunction(iVar, projMin[iVar], - fieldMin(iPoint,iVar) - field(iPoint,iVar)); + for(size_t iVar = varBegin; iVar < varEnd; ++iVar) + { + su2double limMax = limiterDetails.limiterFunction(iVar, projMax[iVar], + fieldMax(iPoint,iVar) - field(iPoint,iVar)); - limiter(iPoint,iVar) = geoFactor * min(limMax, limMin); + su2double limMin = limiterDetails.limiterFunction(iVar, projMin[iVar], + fieldMin(iPoint,iVar) - field(iPoint,iVar)); - AD::SetPreaccOut(limiter(iPoint,iVar)); - } + limiter(iPoint,iVar) = geoFactor * min(limMax, limMin); - AD::EndPreacc(); + AD::SetPreaccOut(limiter(iPoint,iVar)); } - } // end SU2_OMP_PARALLEL + AD::EndPreacc(); + } /*--- If no solver was provided we do not communicate. ---*/ + SU2_OMP_MASTER if (solver != nullptr) { /*--- Account for periodic effects, take the minimum limiter on each periodic pair. ---*/ @@ -253,8 +246,10 @@ void computeLimiters_impl(CSolver* solver, solver->InitiateComms(&geometry, &config, kindMpiComm); solver->CompleteComms(&geometry, &config, kindMpiComm); } + SU2_OMP_BARRIER #ifdef CODI_REVERSE_TYPE if (tapeActive) AD::StartRecording(); #endif + } diff --git a/SU2_CFD/include/numerics/CNumerics.hpp b/SU2_CFD/include/numerics/CNumerics.hpp new file mode 100644 index 000000000000..c05fef7cee57 --- /dev/null +++ b/SU2_CFD/include/numerics/CNumerics.hpp @@ -0,0 +1,1302 @@ +/*! + * \file CNumerics.hpp + * \brief Delaration of the base numerics class, the + * implementation is in the CNumerics.cpp file. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#pragma once + +#include +#include +#include +#include + +#include "../../../Common/include/CConfig.hpp" + +using namespace std; + +class CElement; +class CFluidModel; + +/*! + * \class CNumerics + * \brief Class for defining the numerical methods. + * \author F. Palacios, T. Economon + */ +class CNumerics { +protected: + enum : size_t {MAXNDIM = 3}; /*!< \brief Max number of space dimensions, used in some static arrays. */ + + unsigned short nDim, nVar; /*!< \brief Number of dimensions and variables. */ + su2double Gamma; /*!< \brief Fluid's Gamma constant (ratio of specific heats). */ + su2double Gamma_Minus_One; /*!< \brief Fluids's Gamma - 1.0 . */ + su2double Minf; /*!< \brief Free stream Mach number . */ + su2double Gas_Constant; /*!< \brief Gas constant. */ + su2double *Vector; /*!< \brief Auxiliary vector. */ + su2double Prandtl_Lam; /*!< \brief Laminar Prandtl's number. */ + su2double Prandtl_Turb; /*!< \brief Turbulent Prandtl's number. */ + su2double + **Flux_Tensor, /*!< \brief Flux tensor (used for viscous and inviscid purposes. */ + *Proj_Flux_Tensor; /*!< \brief Flux tensor projected in a direction. */ + su2double + **tau, /*!< \brief Viscous stress tensor. */ + **delta, /*!< \brief Identity matrix. */ + **delta3; /*!< \brief 3 row Identity matrix. */ + su2double + *Diffusion_Coeff_i, /*!< \brief Species diffusion coefficients at point i. */ + *Diffusion_Coeff_j; /*!< \brief Species diffusion coefficients at point j. */ + su2double + Laminar_Viscosity_i, /*!< \brief Laminar viscosity at point i. */ + Laminar_Viscosity_j, /*!< \brief Laminar viscosity at point j. */ + Laminar_Viscosity_id, /*!< \brief Variation of laminar viscosity at point i. */ + Laminar_Viscosity_jd; /*!< \brief Variation of laminar viscosity at point j. */ + su2double + Thermal_Conductivity_i, /*!< \brief Thermal conductivity at point i. */ + Thermal_Conductivity_j, /*!< \brief Thermal conductivity at point j. */ + Thermal_Diffusivity_i, /*!< \brief Thermal diffusivity at point i. */ + Thermal_Diffusivity_j; /*!< \brief Thermal diffusivity at point j. */ + su2double + Cp_i, /*!< \brief Cp at point i. */ + Cp_j; /*!< \brief Cp at point j. */ + su2double + Eddy_Viscosity_i, /*!< \brief Eddy viscosity at point i. */ + Eddy_Viscosity_j; /*!< \brief Eddy viscosity at point j. */ + su2double + turb_ke_i, /*!< \brief Turbulent kinetic energy at point i. */ + turb_ke_j; /*!< \brief Turbulent kinetic energy at point j. */ + su2double + Pressure_i, /*!< \brief Pressure at point i. */ + Pressure_j; /*!< \brief Pressure at point j. */ + su2double + GravityForce_i, /*!< \brief Gravity force at point i. */ + GravityForce_j; /*!< \brief Gravity force at point j. */ + su2double + Density_i, /*!< \brief Density at point i. */ + Density_j; /*!< \brief Density at point j. */ + su2double + DensityInc_i, /*!< \brief Incompressible density at point i. */ + DensityInc_j; /*!< \brief Incompressible density at point j. */ + su2double + BetaInc2_i, /*!< \brief Beta incompressible at point i. */ + BetaInc2_j; /*!< \brief Beta incompressible at point j. */ + su2double + Lambda_i, /*!< \brief Spectral radius at point i. */ + Lambda_j; /*!< \brief Spectral radius at point j. */ + su2double + LambdaComb_i, /*!< \brief Spectral radius at point i. */ + LambdaComb_j; /*!< \brief Spectral radius at point j. */ + su2double + SoundSpeed_i, /*!< \brief Sound speed at point i. */ + SoundSpeed_j; /*!< \brief Sound speed at point j. */ + su2double + Enthalpy_i, /*!< \brief Enthalpy at point i. */ + Enthalpy_j; /*!< \brief Enthalpy at point j. */ + su2double + dist_i, /*!< \brief Distance of point i to the nearest wall. */ + dist_j; /*!< \brief Distance of point j to the nearest wall. */ + su2double + Temp_i, /*!< \brief Temperature at point i. */ + Temp_j; /*!< \brief Temperature at point j. */ + su2double + *Und_Lapl_i, /*!< \brief Undivided laplacians at point i. */ + *Und_Lapl_j; /*!< \brief Undivided laplacians at point j. */ + su2double + Sensor_i, /*!< \brief Pressure sensor at point i. */ + Sensor_j; /*!< \brief Pressure sensor at point j. */ + su2double + *GridVel_i, /*!< \brief Grid velocity at point i. */ + *GridVel_j; /*!< \brief Grid velocity at point j. */ + su2double + *U_i, /*!< \brief Vector of conservative variables at point i. */ + *U_id, /*!< \brief Vector of derivative of conservative variables at point i. */ + *U_j, /*!< \brief Vector of conservative variables at point j. */ + *U_jd; /*!< \brief Vector of derivative of conservative variables at point j. */ + su2double + *V_i, /*!< \brief Vector of primitive variables at point i. */ + *V_j; /*!< \brief Vector of primitive variables at point j. */ + su2double + *S_i, /*!< \brief Vector of secondary variables at point i. */ + *S_j; /*!< \brief Vector of secondary variables at point j. */ + su2double + *Psi_i, /*!< \brief Vector of adjoint variables at point i. */ + *Psi_j; /*!< \brief Vector of adjoint variables at point j. */ + su2double + *DeltaU_i, /*!< \brief Vector of linearized variables at point i. */ + *DeltaU_j; /*!< \brief Vector of linearized variables at point j. */ + su2double + *TurbVar_i, /*!< \brief Vector of turbulent variables at point i. */ + *TurbVar_id, /*!< \brief Vector of derivative of turbulent variables at point i. */ + *TurbVar_j, /*!< \brief Vector of turbulent variables at point j. */ + *TurbVar_jd; /*!< \brief Vector of derivative of turbulent variables at point j. */ + su2double + *TransVar_i, /*!< \brief Vector of turbulent variables at point i. */ + *TransVar_j; /*!< \brief Vector of turbulent variables at point j. */ + su2double + *TurbPsi_i, /*!< \brief Vector of adjoint turbulent variables at point i. */ + *TurbPsi_j; /*!< \brief Vector of adjoint turbulent variables at point j. */ + su2double + **ConsVar_Grad_i, /*!< \brief Gradient of conservative variables at point i. */ + **ConsVar_Grad_j, /*!< \brief Gradient of conservative variables at point j. */ + **ConsVar_Grad; /*!< \brief Gradient of conservative variables which is a scalar. */ + su2double + **PrimVar_Grad_i, /*!< \brief Gradient of primitive variables at point i. */ + **PrimVar_Grad_j; /*!< \brief Gradient of primitive variables at point j. */ + su2double + **PsiVar_Grad_i, /*!< \brief Gradient of adjoint variables at point i. */ + **PsiVar_Grad_j; /*!< \brief Gradient of adjoint variables at point j. */ + su2double + **TurbVar_Grad_i, /*!< \brief Gradient of turbulent variables at point i. */ + **TurbVar_Grad_j; /*!< \brief Gradient of turbulent variables at point j. */ + su2double + **TransVar_Grad_i, /*!< \brief Gradient of turbulent variables at point i. */ + **TransVar_Grad_j; /*!< \brief Gradient of turbulent variables at point j. */ + su2double + **TurbPsi_Grad_i, /*!< \brief Gradient of adjoint turbulent variables at point i. */ + **TurbPsi_Grad_j; /*!< \brief Gradient of adjoint turbulent variables at point j. */ + su2double + *AuxVar_Grad_i, /*!< \brief Gradient of an auxiliary variable at point i. */ + *AuxVar_Grad_j; /*!< \brief Gradient of an auxiliary variable at point i. */ + su2double + *Coord_i, /*!< \brief Cartesians coordinates of point i. */ + *Coord_j; /*!< \brief Cartesians coordinates of point j. */ + unsigned short + Neighbor_i, /*!< \brief Number of neighbors of the point i. */ + Neighbor_j; /*!< \brief Number of neighbors of the point j. */ + su2double + *Normal, /*!< \brief Normal vector, its norm is the area of the face. */ + *UnitNormal, /*!< \brief Unitary normal vector. */ + *UnitNormald; /*!< \brief Derivative of unitary normal vector. */ + su2double + TimeStep, /*!< \brief Time step useful in dual time method. */ + Area, /*!< \brief Area of the face i-j. */ + Volume; /*!< \brief Volume of the control volume around point i. */ + su2double vel2_inf; /*!< \brief value of the square of freestream speed. */ + su2double + *WindGust_i, /*!< \brief Wind gust at point i. */ + *WindGust_j; /*!< \brief Wind gust at point j. */ + su2double + *WindGustDer_i, /*!< \brief Wind gust derivatives at point i. */ + *WindGustDer_j; /*!< \brief Wind gust derivatives at point j. */ + su2double *Vorticity_i, *Vorticity_j; /*!< \brief Vorticity. */ + su2double StrainMag_i, StrainMag_j; /*!< \brief Strain rate magnitude. */ + su2double Dissipation_i, Dissipation_j; /*!< \brief Dissipation. */ + su2double Dissipation_ij; + + su2double *l, *m; + + su2double **MeanReynoldsStress; /*!< \brief Mean Reynolds stress tensor */ + su2double **MeanPerturbedRSM; /*!< \brief Perturbed Reynolds stress tensor */ + bool using_uq; /*!< \brief Flag for UQ methodology */ + su2double PerturbedStrainMag; /*!< \brief Strain magnitude calculated using perturbed stress tensor */ + unsigned short Eig_Val_Comp; /*!< \brief Component towards which perturbation is perfromed */ + su2double uq_delta_b; /*!< \brief Magnitude of perturbation */ + su2double uq_urlx; /*!< \brief Under-relaxation factor for numerical stability */ + bool uq_permute; /*!< \brief Flag for eigenvector permutation */ + + /* Supporting data structures for the eigenspace perturbation for UQ methodology */ + su2double **A_ij, **newA_ij, **Eig_Vec, **New_Eig_Vec, **Corners; + su2double *Eig_Val, *Barycentric_Coord, *New_Coord; + +public: + /*! + * \brief Return type used in some "ComputeResidual" overloads to give a + * const-view of the internally stored flux vector and Jacobians to the outside. + * \note The default template params make this an "all const" object, it cannot + * change after instantiation, nor can it be used to change the data. + */ + template + struct ResidualType { + const Vector_t residual; + const Matrix_t jacobian_i; + const Matrix_t jacobian_j; + + ResidualType() = delete; + + ResidualType(const Vector_t& res, const Matrix_t& jac_i, const Matrix_t& jac_j) : + residual(res), jacobian_i(jac_i), jacobian_j(jac_j) { } + + /*! + * \brief The object can be directly cast to the vector type, this + * allows discarding the Jacobians when they are not needed. + */ + operator Vector_t() { return residual; } + }; + + /*! + * \brief Constructor of the class. + */ + CNumerics(void); + + /*! + * \overload + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CNumerics(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + virtual ~CNumerics(void); + + /*! + * \brief Compute the determinant of a 3 by 3 matrix. + * \param[in] val_matrix 3 by 3 matrix. + * \return Determinant of the matrix + */ + inline static su2double Determinant_3x3(su2double A00, su2double A01, su2double A02, + su2double A10, su2double A11, su2double A12, + su2double A20, su2double A21, su2double A22) { + return A00*(A11*A22-A12*A21) - A01*(A10*A22-A12*A20) + A02*(A10*A21-A11*A20); + } + + /*! + * \brief Set the time step. + * \param[in] val_timestep - Value of the time step. + */ + inline void SetTimeStep(su2double val_timestep) { TimeStep = val_timestep;} + + /*! + * \brief Set the freestream velocity square. + * \param[in] SetVelocity2_Inf - Value of the square of the freestream velocity. + */ + inline void SetVelocity2_Inf(su2double val_velocity2) { vel2_inf = val_velocity2; } + + /*! + * \brief Set the value of the vorticity + * \param[in] val_vorticity - Value of the vorticity. + */ + void SetVorticity(su2double *val_vorticity_i, su2double *val_vorticity_j) { + Vorticity_i = val_vorticity_i; + Vorticity_j = val_vorticity_j; + } + + /*! + * \brief Set the value of the rate of strain magnitude. + * \param[in] val_StrainMag_i - Value of the magnitude of rate of strain at point i. + * \param[in] val_StrainMag_j - Value of the magnitude of rate of strain at point j. + */ + void SetStrainMag(su2double val_strainmag_i, su2double val_strainmag_j) { + StrainMag_i = val_strainmag_i; + StrainMag_j = val_strainmag_j; + } + + /*! + * \brief Set the value of the conservative variables. + * \param[in] val_u_i - Value of the conservative variable at point i. + * \param[in] val_u_j - Value of the conservative variable at point j. + */ + inline void SetConservative(su2double *val_u_i, su2double *val_u_j) { + U_i = val_u_i; + U_j = val_u_j; + } + + /*! + * \brief Set the value of the primitive variables. + * \param[in] val_v_i - Value of the primitive variable at point i. + * \param[in] val_v_j - Value of the primitive variable at point j. + */ + inline void SetPrimitive(su2double *val_v_i, su2double *val_v_j) { + V_i = val_v_i; + V_j = val_v_j; + } + + /*! + * \brief Set the value of the primitive variables. + * \param[in] val_v_i - Value of the primitive variable at point i. + * \param[in] val_v_j - Value of the primitive variable at point j. + */ + inline void SetSecondary(su2double *val_s_i, su2double *val_s_j) { + S_i = val_s_i; + S_j = val_s_j; + } + + /*! + * \brief Set the gradient of the conservative variables. + * \param[in] val_consvar_grad_i - Gradient of the conservative variable at point i. + * \param[in] val_consvar_grad_j - Gradient of the conservative variable at point j. + */ + inline void SetConsVarGradient(su2double **val_consvar_grad_i, + su2double **val_consvar_grad_j) { + ConsVar_Grad_i = val_consvar_grad_i; + ConsVar_Grad_j = val_consvar_grad_j; + } + + /*! + * \brief Set the gradient of the conservative variables. + * \param[in] val_consvar_grad - Gradient of the conservative variable which is a scalar. + */ + inline void SetConsVarGradient(su2double **val_consvar_grad) { ConsVar_Grad = val_consvar_grad; } + + /*! + * \brief Set the gradient of the primitive variables. + * \param[in] val_primvar_grad_i - Gradient of the primitive variable at point i. + * \param[in] val_primvar_grad_j - Gradient of the primitive variable at point j. + */ + void SetPrimVarGradient(su2double **val_primvar_grad_i, + su2double **val_primvar_grad_j) { + PrimVar_Grad_i = val_primvar_grad_i; + PrimVar_Grad_j = val_primvar_grad_j; + } + + /*! + * \brief Set the value of the adjoint variable. + * \param[in] val_psi_i - Value of the adjoint variable at point i. + * \param[in] val_psi_j - Value of the adjoint variable at point j. + */ + inline void SetAdjointVar(su2double *val_psi_i, su2double *val_psi_j) { + Psi_i = val_psi_i; + Psi_j = val_psi_j; + } + + /*! + * \brief Set the gradient of the adjoint variables. + * \param[in] val_psivar_grad_i - Gradient of the adjoint variable at point i. + * \param[in] val_psivar_grad_j - Gradient of the adjoint variable at point j. + */ + inline void SetAdjointVarGradient(su2double **val_psivar_grad_i, + su2double **val_psivar_grad_j) { + PsiVar_Grad_i = val_psivar_grad_i; + PsiVar_Grad_j = val_psivar_grad_j; + } + + /*! + * \brief Set the value of the turbulent variable. + * \param[in] val_turbvar_i - Value of the turbulent variable at point i. + * \param[in] val_turbvar_j - Value of the turbulent variable at point j. + */ + inline void SetTurbVar(su2double *val_turbvar_i, su2double *val_turbvar_j) { + TurbVar_i = val_turbvar_i; + TurbVar_j = val_turbvar_j; + } + + /*! + * \brief Set the value of the turbulent variable. + * \param[in] val_transvar_i - Value of the turbulent variable at point i. + * \param[in] val_transvar_j - Value of the turbulent variable at point j. + */ + inline void SetTransVar(su2double *val_transvar_i, su2double *val_transvar_j) { + TransVar_i = val_transvar_i; + TransVar_j = val_transvar_j; + } + + /*! + * \brief Set the gradient of the turbulent variables. + * \param[in] val_turbvar_grad_i - Gradient of the turbulent variable at point i. + * \param[in] val_turbvar_grad_j - Gradient of the turbulent variable at point j. + */ + inline void SetTurbVarGradient(su2double **val_turbvar_grad_i, + su2double **val_turbvar_grad_j) { + TurbVar_Grad_i = val_turbvar_grad_i; + TurbVar_Grad_j = val_turbvar_grad_j; + } + + /*! + * \brief Set the gradient of the turbulent variables. + * \param[in] val_turbvar_grad_i - Gradient of the turbulent variable at point i. + * \param[in] val_turbvar_grad_j - Gradient of the turbulent variable at point j. + */ + inline void SetTransVarGradient(su2double **val_transvar_grad_i, + su2double **val_transvar_grad_j) { + TransVar_Grad_i = val_transvar_grad_i; + TransVar_Grad_j = val_transvar_grad_j; + } + + /*! + * \brief Set the value of the adjoint turbulent variable. + * \param[in] val_turbpsivar_i - Value of the adjoint turbulent variable at point i. + * \param[in] val_turbpsivar_j - Value of the adjoint turbulent variable at point j. + */ + inline void SetTurbAdjointVar(su2double *val_turbpsivar_i, su2double *val_turbpsivar_j) { + TurbPsi_i = val_turbpsivar_i; + TurbPsi_j = val_turbpsivar_j; + } + + /*! + * \brief Set the gradient of the adjoint turbulent variables. + * \param[in] val_turbpsivar_grad_i - Gradient of the adjoint turbulent variable at point i. + * \param[in] val_turbpsivar_grad_j - Gradient of the adjoint turbulent variable at point j. + */ + inline void SetTurbAdjointGradient(su2double **val_turbpsivar_grad_i, + su2double **val_turbpsivar_grad_j) { + TurbPsi_Grad_i = val_turbpsivar_grad_i; + TurbPsi_Grad_j = val_turbpsivar_grad_j; + } + + /*! + * \brief Set the value of the first blending function. + * \param[in] val_F1_i - Value of the first Menter blending function at point i. + * \param[in] val_F1_j - Value of the first Menter blending function at point j. + */ + virtual void SetF1blending(su2double val_F1_i, su2double val_F1_j) {/* empty */}; + + /*! + * \brief Set the value of the second blending function. + * \param[in] val_F1_i - Value of the second Menter blending function at point i. + * \param[in] val_F1_j - Value of the second Menter blending function at point j. + */ + virtual void SetF2blending(su2double val_F1_i, su2double val_F1_j) {/* empty */}; + + /*! + * \brief Set the value of the cross diffusion for the SST model. + * \param[in] val_CDkw_i - Value of the cross diffusion at point i. + * \param[in] val_CDkw_j - Value of the cross diffusion at point j. + */ + virtual void SetCrossDiff(su2double val_CDkw_i, su2double val_CDkw_j) {/* empty */}; + + /*! + * \brief Set the gradient of the auxiliary variables. + * \param[in] val_auxvargrad_i - Gradient of the auxiliary variable at point i. + * \param[in] val_auxvargrad_j - Gradient of the auxiliary variable at point j. + */ + inline void SetAuxVarGrad(su2double *val_auxvargrad_i, su2double *val_auxvargrad_j) { + AuxVar_Grad_i = val_auxvargrad_i; + AuxVar_Grad_j = val_auxvargrad_j; + } + + /*! + * \brief Set the diffusion coefficient + * \param[in] val_diffusioncoeff_i - Value of the diffusion coefficients at i. + * \param[in] val_diffusioncoeff_j - Value of the diffusion coefficients at j + */ + inline void SetDiffusionCoeff(su2double* val_diffusioncoeff_i, + su2double* val_diffusioncoeff_j) { + Diffusion_Coeff_i = val_diffusioncoeff_i; + Diffusion_Coeff_j = val_diffusioncoeff_j; + } + + /*! + * \brief Set the laminar viscosity. + * \param[in] val_laminar_viscosity_i - Value of the laminar viscosity at point i. + * \param[in] val_laminar_viscosity_j - Value of the laminar viscosity at point j. + */ + inline void SetLaminarViscosity(su2double val_laminar_viscosity_i, + su2double val_laminar_viscosity_j) { + Laminar_Viscosity_i = val_laminar_viscosity_i; + Laminar_Viscosity_j = val_laminar_viscosity_j; + } + + /*! + * \brief Set the thermal conductivity (translational/rotational) + * \param[in] val_thermal_conductivity_i - Value of the thermal conductivity at point i. + * \param[in] val_thermal_conductivity_j - Value of the thermal conductivity at point j. + * \param[in] iSpecies - Value of the species. + */ + inline void SetThermalConductivity(su2double val_thermal_conductivity_i, + su2double val_thermal_conductivity_j) { + Thermal_Conductivity_i = val_thermal_conductivity_i; + Thermal_Conductivity_j = val_thermal_conductivity_j; + } + + /*! + * \brief Set the thermal diffusivity (translational/rotational) + * \param[in] val_thermal_diffusivity_i - Value of the thermal diffusivity at point i. + * \param[in] val_thermal_diffusivity_j - Value of the thermal diffusivity at point j. + * \param[in] iSpecies - Value of the species. + */ + inline void SetThermalDiffusivity(su2double val_thermal_diffusivity_i, + su2double val_thermal_diffusivity_j) { + Thermal_Diffusivity_i = val_thermal_diffusivity_i; + Thermal_Diffusivity_j = val_thermal_diffusivity_j; + } + + /*! + * \brief Set the eddy viscosity. + * \param[in] val_eddy_viscosity_i - Value of the eddy viscosity at point i. + * \param[in] val_eddy_viscosity_j - Value of the eddy viscosity at point j. + */ + inline void SetEddyViscosity(su2double val_eddy_viscosity_i, + su2double val_eddy_viscosity_j) { + Eddy_Viscosity_i = val_eddy_viscosity_i; + Eddy_Viscosity_j = val_eddy_viscosity_j; + } + + /*! + * \brief Set the turbulent kinetic energy. + * \param[in] val_turb_ke_i - Value of the turbulent kinetic energy at point i. + * \param[in] val_turb_ke_j - Value of the turbulent kinetic energy at point j. + */ + inline void SetTurbKineticEnergy(su2double val_turb_ke_i, su2double val_turb_ke_j) { + turb_ke_i = val_turb_ke_i; + turb_ke_j = val_turb_ke_j; + } + + /*! + * \brief Set the value of the distance from the nearest wall. + * \param[in] val_dist_i - Value of of the distance from point i to the nearest wall. + * \param[in] val_dist_j - Value of of the distance from point j to the nearest wall. + */ + void SetDistance(su2double val_dist_i, su2double val_dist_j) { + dist_i = val_dist_i; + dist_j = val_dist_j; + } + + /*! + * \brief Set coordinates of the points. + * \param[in] val_coord_i - Coordinates of the point i. + * \param[in] val_coord_j - Coordinates of the point j. + */ + inline void SetCoord(su2double *val_coord_i, su2double *val_coord_j) { + Coord_i = val_coord_i; + Coord_j = val_coord_j; + } + + /*! + * \brief Set the velocity of the computational grid. + * \param[in] val_gridvel_i - Grid velocity of the point i. + * \param[in] val_gridvel_j - Grid velocity of the point j. + */ + inline void SetGridVel(su2double *val_gridvel_i, su2double *val_gridvel_j) { + GridVel_i = val_gridvel_i; + GridVel_j = val_gridvel_j; + } + + /*! + * \brief Set the wind gust value. + * \param[in] val_windgust_i - Wind gust of the point i. + * \param[in] val_windgust_j - Wind gust of the point j. + */ + inline void SetWindGust(su2double *val_windgust_i, su2double *val_windgust_j) { + WindGust_i = val_windgust_i; + WindGust_j = val_windgust_j; + } + + /*! + * \brief Set the wind gust derivatives values. + * \param[in] val_windgust_i - Wind gust derivatives of the point i. + * \param[in] val_windgust_j - Wind gust derivatives of the point j. + */ + inline void SetWindGustDer(su2double *val_windgustder_i, su2double *val_windgustder_j) { + WindGustDer_i = val_windgustder_i; + WindGustDer_j = val_windgustder_j; + } + + /*! + * \brief Set the value of the pressure. + * \param[in] val_pressure_i - Value of the pressure at point i. + * \param[in] val_pressure_j - Value of the pressure at point j. + */ + void SetPressure(su2double val_pressure_i, su2double val_pressure_j) { + Pressure_i = val_pressure_i; + Pressure_j = val_pressure_j; + } + + /*! + * \brief Set the value of the density for the incompressible solver. + * \param[in] val_densityinc_i - Value of the pressure at point i. + * \param[in] val_densityinc_j - Value of the pressure at point j. + */ + void SetDensity(su2double val_densityinc_i, su2double val_densityinc_j) { + DensityInc_i = val_densityinc_i; + DensityInc_j = val_densityinc_j; + } + + /*! + * \brief Set the value of the beta for incompressible flows. + * \param[in] val_betainc2_i - Value of beta for incompressible flows at point i. + * \param[in] val_betainc2_j - Value of beta for incompressible flows at point j. + */ + inline void SetBetaInc2(su2double val_betainc2_i, su2double val_betainc2_j) { + BetaInc2_i = val_betainc2_i; + BetaInc2_j = val_betainc2_j; + } + + /*! + * \brief Set the value of the sound speed. + * \param[in] val_soundspeed_i - Value of the sound speed at point i. + * \param[in] val_soundspeed_j - Value of the sound speed at point j. + */ + inline void SetSoundSpeed(su2double val_soundspeed_i, su2double val_soundspeed_j) { + SoundSpeed_i = val_soundspeed_i; + SoundSpeed_j = val_soundspeed_j; + } + + /*! + * \brief Set the value of the temperature. + * \param[in] val_temp_i - Value of the temperature at point i. + * \param[in] val_temp_j - Value of the temperature at point j. + */ + inline void SetTemperature(su2double val_temp_i, su2double val_temp_j) { + Temp_i = val_temp_i; + Temp_j = val_temp_j; + } + + /*! + * \brief Set the value of the enthalpy. + * \param[in] val_enthalpy_i - Value of the enthalpy at point i. + * \param[in] val_enthalpy_j - Value of the enthalpy at point j. + */ + inline void SetEnthalpy(su2double val_enthalpy_i, su2double val_enthalpy_j) { + Enthalpy_i = val_enthalpy_i; + Enthalpy_j = val_enthalpy_j; + } + + /*! + * \brief Set the value of the spectral radius. + * \param[in] val_lambda_i - Value of the spectral radius at point i. + * \param[in] val_lambda_j - Value of the spectral radius at point j. + */ + inline void SetLambda(su2double val_lambda_i, su2double val_lambda_j) { + Lambda_i = val_lambda_i; + Lambda_j = val_lambda_j; + } + + /*! + * \brief Set the value of undivided laplacian. + * \param[in] val_und_lapl_i Undivided laplacian at point i. + * \param[in] val_und_lapl_j Undivided laplacian at point j. + */ + inline void SetUndivided_Laplacian(su2double *val_und_lapl_i, su2double *val_und_lapl_j) { + Und_Lapl_i = val_und_lapl_i; + Und_Lapl_j = val_und_lapl_j; + } + + /*! + * \brief Set the value of the pressure sensor. + * \param[in] val_sensor_i Pressure sensor at point i. + * \param[in] val_sensor_j Pressure sensor at point j. + */ + inline void SetSensor(su2double val_sensor_i, su2double val_sensor_j) { + Sensor_i = val_sensor_i; + Sensor_j = val_sensor_j; + } + + /*! + * \brief Set the number of neighbor to a point. + * \param[in] val_neighbor_i - Number of neighbor to point i. + * \param[in] val_neighbor_j - Number of neighbor to point j. + */ + inline void SetNeighbor(unsigned short val_neighbor_i, unsigned short val_neighbor_j) { + Neighbor_i = val_neighbor_i; + Neighbor_j = val_neighbor_j; + } + + /*! + * \brief Set the value of the normal vector to the face between two points. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + */ + inline void SetNormal(su2double *val_normal) { Normal = val_normal; } + + /*! + * \brief Set the value of the volume of the control volume. + * \param[in] val_volume Volume of the control volume. + */ + inline void SetVolume(su2double val_volume) { Volume = val_volume; } + + /*! + * \brief Sets the values of the roe dissipation. + * \param[in] diss_i - Dissipation value at node i + * \param[in] diss_j - Dissipation value at node j + */ + inline void SetDissipation(su2double diss_i, su2double diss_j) { + Dissipation_i = diss_i; + Dissipation_j = diss_j; + } + + /*! + * \brief Get the final Roe dissipation factor. + */ + inline su2double GetDissipation() const { return Dissipation_ij; } + + /*! + * \brief Get the inviscid fluxes. + * \param[in] val_density - Value of the density. + * \param[in] val_velocity - Value of the velocity. + * \param[in] val_pressure - Value of the pressure. + * \param[in] val_enthalpy - Value of the enthalpy. + */ + void GetInviscidFlux(su2double val_density, su2double *val_velocity, su2double val_pressure, su2double val_enthalpy); + + /*! + * \brief Compute the projected inviscid flux vector. + * \param[in] val_density - Pointer to the density. + * \param[in] val_velocity - Pointer to the velocity. + * \param[in] val_pressure - Pointer to the pressure. + * \param[in] val_enthalpy - Pointer to the enthalpy. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[out] val_Proj_Flux - Pointer to the projected flux. + */ + void GetInviscidProjFlux(su2double *val_density, su2double *val_velocity, + su2double *val_pressure, su2double *val_enthalpy, + su2double *val_normal, su2double *val_Proj_Flux); + + /*! + * \brief Compute the projected inviscid flux vector for incompresible simulations + * \param[in] val_density - Pointer to the density. + * \param[in] val_velocity - Pointer to the velocity. + * \param[in] val_pressure - Pointer to the pressure. + * \param[in] val_betainc2 - Value of the artificial compresibility factor. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[out] val_Proj_Flux - Pointer to the projected flux. + */ + void GetInviscidIncProjFlux(su2double *val_density, su2double *val_velocity, + su2double *val_pressure, su2double *val_betainc2, + su2double *val_enthalpy, + su2double *val_normal, su2double *val_Proj_Flux); + + /*! + * \brief Compute the projection of the inviscid Jacobian matrices. + * \param[in] val_velocity Pointer to the velocity. + * \param[in] val_energy Value of the energy. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[in] val_scale - Scale of the projection. + * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. + */ + void GetInviscidProjJac(su2double *val_velocity, su2double *val_energy, + su2double *val_normal, su2double val_scale, + su2double **val_Proj_Jac_tensor); + + /*! + * \brief Compute the projection of the inviscid Jacobian matrices (incompressible). + * \param[in] val_density - Value of the density. + * \param[in] val_velocity - Pointer to the velocity. + * \param[in] val_betainc2 - Value of the artificial compresibility factor. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[in] val_scale - Scale of the projection. + * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. + */ + void GetInviscidIncProjJac(su2double *val_density, su2double *val_velocity, + su2double *val_betainc2, su2double *val_normal, + su2double val_scale, + su2double **val_Proj_Jac_tensor); + + /*! + * \brief Compute the projection of the inviscid Jacobian matrices (overload for low speed preconditioner version). + * \param[in] val_density - Value of the density. + * \param[in] val_velocity - Pointer to the velocity. + * \param[in] val_betainc2 - Value of the artificial compresibility factor. + * \param[in] val_cp - Value of the specific heat at constant pressure. + * \param[in] val_temperature - Value of the temperature. + * \param[in] val_dRhodT - Value of the derivative of density w.r.t. temperature. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[in] val_scale - Scale of the projection. + * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. + */ + void GetInviscidIncProjJac(su2double *val_density, + su2double *val_velocity, + su2double *val_betainc2, + su2double *val_cp, + su2double *val_temperature, + su2double *val_dRhodT, + su2double *val_normal, + su2double val_scale, + su2double **val_Proj_Jac_Tensor); + + /*! + * \brief Compute the low speed preconditioning matrix. + * \param[in] val_density - Value of the density. + * \param[in] val_velocity - Pointer to the velocity. + * \param[in] val_betainc2 - Value of the artificial compresibility factor. + * \param[in] val_cp - Value of the specific heat at constant pressure. + * \param[in] val_temperature - Value of the temperature. + * \param[in] val_dRhodT - Value of the derivative of density w.r.t. temperature. + * \param[out] val_Precon - Pointer to the preconditioning matrix. + */ + void GetPreconditioner(su2double *val_density, + su2double *val_velocity, + su2double *val_betainc2, + su2double *val_cp, + su2double *val_temperature, + su2double *val_drhodt, + su2double **val_Precon); + + /*! + * \brief Compute the projection of the preconditioned inviscid Jacobian matrices. + * \param[in] val_density - Value of the density. + * \param[in] val_velocity - Pointer to the velocity. + * \param[in] val_betainc2 - Value of the artificial compresibility factor. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. + */ + void GetPreconditionedProjJac(su2double *val_density, + su2double *val_velocity, + su2double *val_betainc2, + su2double *val_normal, + su2double **val_Proj_Jac_Tensor); + + /*! + * \brief Compute the projection of the inviscid Jacobian matrices for general fluid model. + * \param[in] val_velocity Pointer to the velocity. + * \param[in] val_energy Value of the energy. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[in] val_scale - Scale of the projection. + * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. + */ + void GetInviscidProjJac(su2double *val_velocity, su2double *val_enthalphy, + su2double *val_chi, su2double *val_kappa, + su2double *val_normal, su2double val_scale, + su2double **val_Proj_Jac_tensor); + + /*! + * \brief Mapping between primitives variables P and conservatives variables C. + * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. + * \param[in] val_Mean_PrimVar - Mean Value of the secondary variables. + * \param[out] val_Jac_PC - Pointer to the Jacobian dPdC. + */ + void GetPrimitive2Conservative (su2double *val_Mean_PrimVar, + su2double *val_Mean_SecVar, + su2double **val_Jac_PC); + + /*! + * \overload + * \brief Computation of the matrix P for a generic fluid model + * \param[in] val_density - Value of the density. + * \param[in] val_velocity - Value of the velocity. + * \param[in] val_soundspeed - Value of the sound speed. + * \param[in] val_enthalpy - Value of the Enthalpy + * \param[in] val_chi - Value of the derivative of Pressure with respect to the Density. + * \param[in] val_kappa - Value of the derivative of Pressure with respect to the volume specific Static Energy. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[out] val_p_tensor - Pointer to the P matrix. + */ + void GetPMatrix(su2double *val_density, su2double *val_velocity, + su2double *val_soundspeed, su2double *val_enthalpy, + su2double *val_chi, su2double *val_kappa, + su2double *val_normal, su2double **val_p_tensor); + + /*! + * \brief Computation of the matrix P, this matrix diagonalize the conservative Jacobians in + * the form $P^{-1}(A.Normal)P=Lambda$. + * \param[in] val_density - Value of the density. + * \param[in] val_velocity - Value of the velocity. + * \param[in] val_soundspeed - Value of the sound speed. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[out] val_p_tensor - Pointer to the P matrix. + */ + void GetPMatrix(su2double *val_density, su2double *val_velocity, + su2double *val_soundspeed, su2double *val_normal, + su2double **val_p_tensor); + + /*! + * \brief Computation of the matrix Rinv*Pe. + * \param[in] Beta2 - A variable in used to define Pe matrix. + * \param[in] val_enthalpy - value of the enthalpy. + * \param[in] val_soundspeed - value of the sound speed. + * \param[in] val_density - value of the density. + * \param[in] val_velocity - value of the velocity. + * \param[out] val_invR_invPe - Pointer to the matrix of conversion from entropic to conserved variables. + */ + void GetinvRinvPe(su2double Beta2, su2double val_enthalpy, su2double val_soundspeed, + su2double val_density, su2double* val_velocity, + su2double** val_invR_invPe); + + /*! + * \brief Computation of the matrix R. + * \param[in] val_pressure - value of the pressure. + * \param[in] val_soundspeed - value of the sound speed. + * \param[in] val_density - value of the density. + * \param[in] val_velocity - value of the velocity. + * \param[out] val_invR_invPe - Pointer to the matrix of conversion from entropic to conserved variables. + */ + void GetRMatrix(su2double val_pressure, su2double val_soundspeed, + su2double val_density, su2double* val_velocity, + su2double** val_invR_invPe); + /*! + * \brief Computation of the matrix R. + * \param[in] val_soundspeed - value of the sound speed. + * \param[in] val_density - value of the density. + * \param[out] R_Matrix - Pointer to the matrix of conversion from entropic to conserved variables. + */ + void GetRMatrix(su2double val_soundspeed, su2double val_density, su2double **R_Matrix); + + /*! + * \brief Computation of the matrix R. + * \param[in] val_soundspeed - value of the sound speed. + * \param[in] val_density - value of the density. + * \param[out] L_Matrix - Pointer to the matrix of conversion from conserved to entropic variables. + */ + void GetLMatrix(su2double val_soundspeed, su2double val_density, su2double **L_Matrix); + + /*! + * \brief Computation of the flow Residual Jacoboan Matrix for Non Reflecting BC. + * \param[in] val_soundspeed - value of the sound speed. + * \param[in] val_density - value of the density. + * \param[out] R_c - Residual Jacoboan Matrix + * \param[out] R_c_inv- inverse of the Residual Jacoboan Matrix . + */ + void ComputeResJacobianGiles(CFluidModel *FluidModel, su2double pressure, su2double density, su2double *turboVel, + su2double alphaInBC, su2double gammaInBC, su2double **R_c, su2double **R_c_inv); + + /*! + * \brief Computate the inverse of a 3x3 matrix + * \param[in] matrix - the matrix to invert + * \param[out] invMatrix - inverse matrix. + */ + void InvMatrix3D(su2double **matrix, su2double **invMatrix); + + /*! + * \brief Computate the inverse of a 4x4 matrix + * \param[in] matrix - the matrix to invert + * \param[out] invMatrix - inverse matrix. + */ + void InvMatrix4D(su2double **matrix, su2double **invMatrix); + + /*! + * \brief Computation of the matrix R. + * \param[in] val_soundspeed - value of the sound speed. + * \param[in] val_density - value of the density. + * \param[in] prim_jump - pointer to the vector containing the primitive variable jump (drho, dV, dp). + * \param[out] char_jump - pointer to the vector containing the characteristic variable jump. + */ + void GetCharJump(su2double val_soundspeed, su2double val_density, su2double *prim_jump, su2double *char_jump); + + /*! + * \brief Computation of the matrix Td, this matrix diagonalize the preconditioned conservative Jacobians + * in the form $Tg |Lambda| Td = Pc{-1}|Pc (A.Normal)|$. + * \param[in] Beta2 - A variable in used to define absPeJacobian matrix. + * \param[in] r_hat - A variable in used to define absPeJacobian matrix. + * \param[in] s_hat - A variable in used to define absPeJacobian matrix. + * \param[in] t_hat - A variable in used to define absPeJacobian matrix. + * \param[in] rB2a2 - A variable in used to define absPeJacobian matrix. + * \param[in] val_Lambda - Eigenvalues of the Preconditioned Jacobian. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[out] val_absPeJac - Pointer to the Preconditioned Jacobian matrix. + */ + void GetPrecondJacobian(su2double Beta2, su2double r_hat, su2double s_hat, su2double t_hat, + su2double rB2a2, su2double* val_Lambda, su2double* val_normal, su2double** val_absPeJac); + + /*! + * \brief Computation of the matrix P^{-1}, this matrix diagonalize the conservative Jacobians + * in the form $P^{-1}(A.Normal)P=Lambda$. + * \param[in] val_density - Value of the density. + * \param[in] val_velocity - Value of the velocity. + * \param[in] val_soundspeed - Value of the sound speed. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[out] val_invp_tensor - Pointer to inverse of the P matrix. + */ + void GetPMatrix_inv(su2double **val_invp_tensor, su2double *val_density, + su2double *val_velocity, su2double *val_soundspeed, + su2double *val_chi, su2double *val_kappa, + su2double *val_normal); + + /*! + * \brief Computation of the matrix P^{-1}, this matrix diagonalize the conservative Jacobians + * in the form $P^{-1}(A.Normal)P=Lambda$. + * \param[in] val_density - Value of the density. + * \param[in] val_velocity - Value of the velocity. + * \param[in] val_soundspeed - Value of the sound speed. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[out] val_invp_tensor - Pointer to inverse of the P matrix. + */ + void GetPMatrix_inv(su2double *val_density, su2double *val_velocity, + su2double *val_soundspeed, su2double *val_normal, + su2double **val_invp_tensor); + + /*! + * \brief Compute viscous residual and jacobian. + */ + void GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j, su2double Density_i, su2double Density_j, + su2double ViscDens_i, su2double ViscDens_j, su2double *Velocity_i, su2double *Velocity_j, + su2double sq_vel_i, su2double sq_vel_j, + su2double XiDens_i, su2double XiDens_j, su2double **Mean_GradPhi, su2double *Mean_GradPsiE, + su2double dPhiE_dn, su2double *Normal, su2double *Edge_Vector, su2double dist_ij_2, su2double *val_residual_i, + su2double *val_residual_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, + su2double **val_Jacobian_jj, bool implicit); + + /*! + * \brief Computation of the projected inviscid lambda (eingenvalues). + * \param[in] val_velocity - Value of the velocity. + * \param[in] val_soundspeed - Value of the sound speed. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[in] val_Lambda_Vector - Pointer to Lambda matrix. + */ + void GetJacInviscidLambda_fabs(su2double *val_velocity, su2double val_soundspeed, + su2double *val_normal, su2double *val_Lambda_Vector); + + /*! + * \brief Compute the numerical residual. + * \param[out] val_residual - Pointer to the total residual. + * \param[in] config - Definition of the particular problem. + */ + inline virtual void ComputeResidual(su2double *val_residual, CConfig* config) { } + + /*! + * \overload + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + inline virtual void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, CConfig* config) { } + + /*! + * \overload For numerics classes that store the residual/flux and Jacobians internally. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + inline virtual ResidualType<> ComputeResidual(const CConfig* config) { return ResidualType<>(nullptr,nullptr,nullptr); } + + /*! + * \overload + * \param[out] val_residual_i - Pointer to the total residual at point i. + * \param[out] val_residual_j - Pointer to the total viscosity residual at point j. + * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. + * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. + * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. + * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. + * \param[in] config - Definition of the particular problem. + */ + inline virtual void ComputeResidual(su2double *val_residual_i, + su2double *val_residual_j, + su2double **val_Jacobian_ii, + su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, + su2double **val_Jacobian_jj, CConfig* config) { } + + /*! + * \overload + * \param[out] val_resconv_i - Pointer to the convective residual at point i. + * \param[out] val_resvisc_i - Pointer to the artificial viscosity residual at point i. + * \param[out] val_resconv_j - Pointer to the convective residual at point j. + * \param[out] val_resvisc_j - Pointer to the artificial viscosity residual at point j. + * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. + * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. + * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. + * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. + * \param[in] config - Definition of the particular problem. + */ + inline virtual void ComputeResidual(su2double *val_resconv_i, su2double *val_resvisc_i, + su2double *val_resconv_j, su2double *val_resvisc_j, + su2double **val_Jacobian_ii, + su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, + su2double **val_Jacobian_jj, CConfig* config) { } + + /*! + * \overload + * \param[in] config - Definition of the particular problem. + * \param[out] val_residual - residual of the source terms + * \param[out] val_Jacobian_i - Jacobian of the source terms + */ + inline virtual void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig* config) { } + + /*! + * \brief Residual for transition problems. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + * \param[out] gamma_sep + */ + inline virtual void ComputeResidual_TransLM(su2double *val_residual, + su2double **val_Jacobian_i, + su2double **val_Jacobian_j, CConfig* config, + su2double &gamma_sep) { } + + /*! + * \brief Set intermittency for numerics (used in SA with LM transition model) + */ + inline virtual void SetIntermittency(su2double intermittency_in) { } + + /*! + * \brief Residual for source term integration. + * \param[in] val_production - Value of the Production. + */ + inline virtual void SetProduction(su2double val_production) { } + + /*! + * \brief Residual for source term integration. + * \param[in] val_destruction - Value of the Destruction. + */ + inline virtual void SetDestruction(su2double val_destruction) { } + + /*! + * \brief Residual for source term integration. + * \param[in] val_crossproduction - Value of the CrossProduction. + */ + inline virtual void SetCrossProduction(su2double val_crossproduction) { } + + /*! + * \brief Residual for source term integration. + * \param[in] val_production - Value of the Production. + */ + inline virtual su2double GetProduction(void) const { return 0; } + + /*! + * \brief Residual for source term integration. + * \param[in] val_destruction - Value of the Destruction. + */ + inline virtual su2double GetDestruction(void) const { return 0; } + + /*! + * \brief Residual for source term integration. + * \param[in] val_crossproduction - Value of the CrossProduction. + */ + inline virtual su2double GetCrossProduction(void) const { return 0; } + + /*! + * \brief A virtual member. + */ + inline virtual su2double GetGammaBC(void) const { return 0.0; } + + /*! + * \brief A virtual member to compute the tangent matrix in structural problems + * \param[in] element_container - Element structure for the particular element integrated. + */ + inline virtual void Compute_Tangent_Matrix(CElement *element_container, const CConfig* config) { } + + /*! + * \brief A virtual member to compute the nodal stress term in non-linear structural problems + * \param[in] element_container - Definition of the particular element integrated. + */ + inline virtual void Compute_NodalStress_Term(CElement *element_container, const CConfig* config) { } + + /*! + * \brief Set the element-based local Young's modulus in mesh problems + * \param[in] iElem - Element index. + * \param[in] val_E - Value of elasticity modulus. + */ + inline virtual void SetMeshElasticProperties(unsigned long iElem, su2double val_E) { } + + /*! + * \brief A virtual member to set the value of the design variables + * \param[in] i_DV - Index of the design variable. + * \param[in] val_DV - Value of the design variable + */ + inline virtual void Set_DV_Val(unsigned short i_DV, su2double val_DV) { } + + /*! + * \brief A virtual member to retrieve the value of the design variables + * \param[in] i_DV - Index of the design variable. + */ + inline virtual su2double Get_DV_Val(unsigned short i_DV) const { return 0.0; } + + /*! + * \brief A virtual member to set the electric field + * \param[in] EField_DV - New electric field computed by adjoint methods. + */ + inline virtual void Set_ElectricField(unsigned short i_DV, su2double val_EField) { } + + /*! + * \brief A virtual member to set the material properties + * \param[in] iVal - Index of the region of concern + * \param[in] val_E - Value of the Young Modulus. + * \param[in] val_Nu - Value of the Poisson's ratio. + */ + inline virtual void SetMaterial_Properties(unsigned short iVal, su2double val_E, su2double val_Nu) { } + + /*! + * \brief A virtual member to set the material properties + * \param[in] iVal - Index of the region of concern + * \param[in] val_Rho - Value of the density (inertial effects). + * \param[in] val_Rho_DL - Value of the density (dead load effects). + */ + inline virtual void SetMaterial_Density(unsigned short iVal, su2double val_Rho, su2double val_Rho_DL) { } + + /*! + * \brief A virtual member to compute the mass matrix + * \param[in] element_container - Element structure for the particular element integrated. + */ + inline virtual void Compute_Mass_Matrix(CElement *element_container, const CConfig* config) { } + + /*! + * \brief A virtual member to compute the residual component due to dead loads + * \param[in] element_container - Element structure for the particular element integrated. + */ + inline virtual void Compute_Dead_Load(CElement *element_container, const CConfig* config) { } + + /*! + * \brief A virtual member to compute the averaged nodal stresses + * \param[in] element_container - Element structure for the particular element integrated. + */ + inline virtual void Compute_Averaged_NodalStress(CElement *element_container, const CConfig* config) { } + + /*! + * \brief Computes a basis of orthogonal vectors from a supplied vector + * \param[in] config - Normal vector + */ + void CreateBasis(su2double *val_Normal); + + /*! + * \brief Set the value of the Tauwall + * \param[in] val_tauwall_i - Tauwall at point i + * \param[in] val_tauwall_j - Tauwall at point j + */ + inline virtual void SetTauWall(su2double val_tauwall_i, su2double val_tauwall_j) { } + + /*! + * \brief - Calculate the central/upwind blending function for a face + * + * At its simplest level, this function will calculate the average + * value of the "Roe dissipation" or central/upwind blending function + * at a face. If Ducros shock sensors are used, then this method will + * also adjust the central/upwind blending to account for shocks. + * + * \param[in] Dissipation_i - Value of the blending function at point i + * \param[in] Dissipation_j - Value of the bledning function at point j + * \param[in] Sensor_i - Shock sensor at point i + * \param[in] Sensor_j - Shock sensor at point j + * \param[in] config - The configuration of the problem + * \return Dissipation_ij - Blending parameter at face + */ + su2double GetRoe_Dissipation(const su2double Dissipation_i, const su2double Dissipation_j, + const su2double Sensor_i, const su2double Sensor_j, const CConfig* config) const; + + /*! + * \brief Decomposes the symmetric matrix A_ij, into eigenvectors and eigenvalues + * \param[in] A_i: symmetric matrix to be decomposed + * \param[in] Eig_Vec: strores the eigenvectors + * \param[in] Eig_Val: stores the eigenvalues + * \param[in] n: order of matrix A_ij + */ + static void EigenDecomposition(su2double **A_ij, su2double **Eig_Vec, su2double *Eig_Val, unsigned short n); + + /*! + * \brief Recomposes the eigenvectors and eigenvalues into a matrix + * \param[in] A_ij: recomposed matrix + * \param[in] Eig_Vec: eigenvectors + * \param[in] Eig_Val: eigenvalues + * \param[in] n: order of matrix A_ij + */ + static void EigenRecomposition(su2double **A_ij, su2double **Eig_Vec, su2double *Eig_Val, unsigned short n); + + /*! + * \brief tred2 + * \param[in] V: matrix that needs to be decomposed + * \param[in] d: holds eigenvalues + * \param[in] e: supplemental data structure + * \param[in] n: order of matrix V + */ + static void tred2(su2double **V, su2double *d, su2double *e, unsigned short n); + + /*! + * \brief tql2 + * \param[in] V: matrix that will hold the eigenvectors + * \param[in] d: array that will hold the ordered eigenvalues + * \param[in] e: supplemental data structure + * \param[in] n: order of matrix V + */ + static void tql2(su2double **V, su2double *d, su2double *e, unsigned short n); + +}; + +/*! + * /brief Alias for a "do nothing" source term class + */ +using CSourceNothing = CNumerics; diff --git a/SU2_CFD/include/numerics/continuous_adjoint/adj_convection.hpp b/SU2_CFD/include/numerics/continuous_adjoint/adj_convection.hpp new file mode 100644 index 000000000000..b352031fff8a --- /dev/null +++ b/SU2_CFD/include/numerics/continuous_adjoint/adj_convection.hpp @@ -0,0 +1,254 @@ +/*! + * \file adj_convection.hpp + * \brief Delarations of numerics classes for continuous adjoint + * convective discretization. Implemented in adj_convection.cpp. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../CNumerics.hpp" + +/*! + * \class CCentLax_AdjFlow + * \brief Class for computing the Lax-Friedrich adjoint centered scheme. + * \ingroup ConvDiscr + * \author F. Palacios + */ +class CCentLax_AdjFlow : public CNumerics { +private: + su2double *Diff_Psi; + su2double *Velocity_i, *Velocity_j; + su2double *MeanPhi; + unsigned short iDim, jDim, iVar, jVar; + su2double Residual, ProjVelocity_i, ProjVelocity_j, ProjPhi, ProjPhi_Vel, sq_vel, phis1, phis2, + MeanPsiRho, MeanPsiE, Param_p, Param_Kappa_0, Local_Lambda_i, Local_Lambda_j, MeanLambda, + Phi_i, Phi_j, sc2, StretchingFactor, Epsilon_0; + bool implicit, grid_movement; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CCentLax_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CCentLax_AdjFlow(void); + + /*! + * \brief Compute the adjoint flow residual using a Lax method. + * \param[out] val_resconv_i - Pointer to the convective residual at point i. + * \param[out] val_resvisc_i - Pointer to the artificial viscosity residual at point i. + * \param[out] val_resconv_j - Pointer to the convective residual at point j. + * \param[out] val_resvisc_j - Pointer to the artificial viscosity residual at point j. + * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. + * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. + * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. + * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual (su2double *val_resconv_i, su2double *val_resvisc_i, + su2double *val_resconv_j, su2double *val_resvisc_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, + CConfig *config); +}; + +/*! + * \class CCentJST_AdjFlow + * \brief Class for and adjoint centered scheme - JST. + * \ingroup ConvDiscr + * \author F. Palacios + */ +class CCentJST_AdjFlow : public CNumerics { +private: + su2double *Diff_Psi, *Diff_Lapl; + su2double *Velocity_i, *Velocity_j; + su2double *MeanPhi; + unsigned short iDim, jDim, iVar, jVar; + su2double Residual, ProjVelocity_i, ProjVelocity_j, ProjPhi, ProjPhi_Vel, sq_vel, phis1, phis2; + su2double MeanPsiRho, MeanPsiE, Param_p, Param_Kappa_4, Param_Kappa_2, Local_Lambda_i, Local_Lambda_j, MeanLambda; + su2double Phi_i, Phi_j, sc4, StretchingFactor, Epsilon_4, Epsilon_2; + bool implicit, grid_movement; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CCentJST_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CCentJST_AdjFlow(void); + + /*! + * \brief Compute the adjoint flow residual using a JST method. + * \param[out] val_resconv_i - Pointer to the convective residual at point i. + * \param[out] val_resvisc_i - Pointer to the artificial viscosity residual at point i. + * \param[out] val_resconv_j - Pointer to the convective residual at point j. + * \param[out] val_resvisc_j - Pointer to the artificial viscosity residual at point j. + * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. + * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. + * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. + * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual (su2double *val_resconv_i, su2double *val_resvisc_i, + su2double *val_resconv_j, su2double *val_resvisc_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, + CConfig *config); +}; + +/*! + * \class CUpwRoe_AdjFlow + * \brief Class for solving an approximate Riemann solver of Roe + * for the adjoint flow equations. + * \ingroup ConvDiscr + * \author F. Palacios + */ +class CUpwRoe_AdjFlow : public CNumerics { +private: + su2double *Residual_Roe; + su2double area, Sx, Sy, Sz, rarea, nx, ny, nz, rho_l, u_l, v_l, w_l, h_l, rho_r, + u_r, v_r, w_r, h_r, psi1, psi2, psi3, psi4, psi5; + su2double h, u, v, w, c, psi1_l, psi2_l, psi3_l, psi4_l, psi5_l, + psi1_r, psi2_r, psi3_r, psi4_r, psi5_r, q_l, q_r, Q_l, Q_r, vn, + rrho_l, weight, rweight1, cc; + su2double l1psi, l2psi, absQ, absQp, absQm, q2, alpha, beta_u, beta_v, beta_w, Q, l1l2p, l1l2m, eta; + su2double RoeDensity, RoeSoundSpeed, *RoeVelocity, *Lambda, *Velocity_i, *Velocity_j, **ProjFlux_i, **ProjFlux_j, + Proj_ModJac_Tensor_ij, **Proj_ModJac_Tensor, Energy_i, Energy_j, **P_Tensor, **invP_Tensor; + unsigned short iDim, iVar, jVar, kVar; + bool implicit, grid_movement; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwRoe_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwRoe_AdjFlow(void); + + /*! + * \brief Compute the adjoint Roe's flux between two nodes i and j. + * \param[out] val_residual_i - Pointer to the total residual at point i. + * \param[out] val_residual_j - Pointer to the total residual at point j. + * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. + * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. + * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. + * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); +}; + +/*! + * \class CUpwLin_AdjTurb + * \brief Class for performing a linear upwind solver for the adjoint turbulence equations. + * \ingroup ConvDiscr + * \author A. Bueno. + */ +class CUpwLin_AdjTurb : public CNumerics { +private: + su2double *Velocity_i; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwLin_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwLin_AdjTurb(void); + + /*! + * \brief Compute the adjoint upwind flux between two nodes i and j. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual (su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); +}; + +/*! + * \class CUpwSca_AdjTurb + * \brief Class for doing a scalar upwind solver for the adjoint turbulence equations. + * \ingroup ConvDiscr + * \author A. Bueno. + */ +class CUpwSca_AdjTurb : public CNumerics { +private: + su2double *Velocity_i, *Velocity_j; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwSca_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwSca_AdjTurb(void); + + /*! + * \param[out] val_residual_i - Pointer to the total residual at point i. + * \param[out] val_residual_j - Pointer to the total viscosity residual at point j. + * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. + * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. + * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. + * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); +}; diff --git a/SU2_CFD/include/numerics/continuous_adjoint/adj_diffusion.hpp b/SU2_CFD/include/numerics/continuous_adjoint/adj_diffusion.hpp new file mode 100644 index 000000000000..e819365c8e98 --- /dev/null +++ b/SU2_CFD/include/numerics/continuous_adjoint/adj_diffusion.hpp @@ -0,0 +1,224 @@ +/*! + * \file adj_diffusion.hpp + * \brief Delarations of numerics classes for continuous adjoint + * diffusion discretization. Implemented in adj_diffusion.cpp. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../CNumerics.hpp" + +/*! + * \class CAvgGrad_AdjFlow + * \brief Class for computing the adjoint viscous terms. + * \ingroup ViscDiscr + * \author F. Palacios + */ +class CAvgGrad_AdjFlow : public CNumerics { +private: + su2double *Velocity_i; /*!< \brief Auxiliary vector for storing the velocity of point i. */ + su2double *Velocity_j; /*!< \brief Auxiliary vector for storing the velocity of point j. */ + su2double *Mean_Velocity; + su2double *Mean_GradPsiE; /*!< \brief Counter for dimensions of the problem. */ + su2double **Mean_GradPhi; /*!< \brief Counter for dimensions of the problem. */ + su2double *Edge_Vector; /*!< \brief Vector going from node i to node j. */ + bool implicit; /*!< \brief Implicit calculus. */ + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGrad_AdjFlow(void); + + /*! + * \brief Residual computation. + * \param[out] val_residual_i - Pointer to the total residual at point i. + * \param[out] val_residual_j - Pointer to the total residual at point j. + */ + void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); +}; + +/*! + * \class CAvgGradCorrected_AdjFlow + * \brief Class for computing the adjoint viscous terms, including correction. + * \ingroup ViscDiscr + * \author A. Bueno. + */ +class CAvgGradCorrected_AdjFlow : public CNumerics { +private: + su2double *Velocity_i; /*!< \brief Auxiliary vector for storing the velocity of point i. */ + su2double *Velocity_j; /*!< \brief Auxiliary vector for storing the velocity of point j. */ + su2double *Mean_Velocity; + su2double **Mean_GradPsiVar; /*!< \brief Counter for dimensions of the problem. */ + su2double *Edge_Vector; /*!< \brief Vector going from node i to node j. */ + su2double *Proj_Mean_GradPsiVar_Edge; /*!< \brief Projection of Mean_GradPsiVar onto Edge_Vector. */ + su2double *Mean_GradPsiE; /*!< \brief Counter for dimensions of the problem. */ + su2double **Mean_GradPhi; /*!< \brief Counter for dimensions of the problem. */ + bool implicit; /*!< \brief Boolean controlling Jacobian calculations. */ + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CAvgGradCorrected_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGradCorrected_AdjFlow(void); + + /*! + * \brief Compute the adjoint flow viscous residual in a non-conservative way using an average of gradients and derivative correction. + * \param[out] val_residual_i - Pointer to the viscous residual at point i. + * \param[out] val_residual_j - Pointer to the viscous residual at point j. + * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. + * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. + * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. + * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); +}; + +/*! + * \class CAvgGrad_AdjTurb + * \brief Class for adjoint turbulent using average of gradients with a correction. + * \ingroup ViscDiscr + * \author F. Palacios + */ +class CAvgGrad_AdjTurb : public CNumerics { +private: + su2double **Mean_GradTurbPsi; + su2double *Proj_Mean_GradTurbPsi_Kappa, *Proj_Mean_GradTurbPsi_Edge, *Proj_Mean_GradTurbPsi_Corrected; + su2double *Edge_Vector; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGrad_AdjTurb(void); + + /*! + * \brief Compute the adjoint turbulent residual using average of gradients and a derivative correction. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); + + /*! + * \overload + * \param[out] val_residual_i - Pointer to the total residual at point i. + * \param[out] val_residual_j - Pointer to the total viscosity residual at point j. + * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. + * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. + * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. + * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); +}; + +/*! + * \class CAvgGradCorrected_AdjTurb + * \brief Class for adjoint turbulent using average of gradients with a correction. + * \ingroup ViscDiscr + * \author A. Bueno. + */ +class CAvgGradCorrected_AdjTurb : public CNumerics { +private: + su2double **Mean_GradTurbPsi; + su2double *Proj_Mean_GradTurbPsi_Kappa, *Proj_Mean_GradTurbPsi_Edge, *Proj_Mean_GradTurbPsi_Corrected; + su2double *Edge_Vector; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CAvgGradCorrected_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGradCorrected_AdjTurb(void); + + /*! + * \brief Compute the adjoint turbulent residual using average of gradients and a derivative correction. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); + + /*! + * \overload + * \param[out] val_residual_i - Pointer to the total residual at point i. + * \param[out] val_residual_j - Pointer to the total viscosity residual at point j. + * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. + * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. + * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. + * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); +}; diff --git a/SU2_CFD/include/numerics/continuous_adjoint/adj_sources.hpp b/SU2_CFD/include/numerics/continuous_adjoint/adj_sources.hpp new file mode 100644 index 000000000000..ddafd2864007 --- /dev/null +++ b/SU2_CFD/include/numerics/continuous_adjoint/adj_sources.hpp @@ -0,0 +1,220 @@ +/*! + * \file adj_sources.hpp + * \brief Delarations of numerics classes for continuous adjoint + * source term integration. Implemented in adj_sources.cpp. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../CNumerics.hpp" + +/*! + * \class CSourceAxisymmetric_AdjFlow + * \brief Class for source term for solving axisymmetric problems. + * \ingroup SourceDiscr + * \author F. Palacios + */ +class CSourceAxisymmetric_AdjFlow : public CNumerics { +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceAxisymmetric_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CSourceAxisymmetric_AdjFlow(void); + + /*! + * \brief Residual of the rotational frame source term. + * \param[out] val_residual - Pointer to the total residual. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, CConfig *config); +}; + +class CSourceConservative_AdjFlow : public CNumerics { +private: + su2double *Velocity, *Residual_i, *Residual_j, *Mean_Residual; + su2double **Mean_PrimVar_Grad; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceConservative_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CSourceConservative_AdjFlow(void); + + /*! + * \brief Source term integration using a conservative scheme. + * \param[out] val_residual - Pointer to the total residual. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, CConfig *config); +}; + +/*! + * \class CSourceRotatingFrame_AdjFlow + * \brief Source term class for rotating frame adjoint. + * \ingroup SourceDiscr + * \author T. Economon. + */ +class CSourceRotatingFrame_AdjFlow : public CNumerics { +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceRotatingFrame_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CSourceRotatingFrame_AdjFlow(void); + + /*! + * \brief Residual of the adjoint rotating frame source term. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config); +}; + +/*! + * \class CSourceViscous_AdjFlow + * \brief Class for source term integration in adjoint problem. + * \ingroup SourceDiscr + * \author F. Palacios + */ +class CSourceViscous_AdjFlow : public CNumerics { +private: + su2double *Velocity, *GradDensity, *GradInvDensity, *dPoDensity2, *alpha, *beta, *Sigma_5_vec; + su2double **GradVel_o_Rho, **sigma, **Sigma_phi, **Sigma_5_Tensor, **Sigma; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceViscous_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CSourceViscous_AdjFlow(void); + + /*! + * \brief Source term integration of the flow adjoint equation. + * \param[out] val_residual - Pointer to the total residual. + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual (su2double *val_residual, CConfig *config); + +}; + +/*! + * \class CSourceConservative_AdjTurb + * \brief Class for source term integration in adjoint turbulent problem using a conservative scheme. + * \ingroup SourceDiscr + * \author A. Bueno. + */ +class CSourceConservative_AdjTurb : public CNumerics { +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceConservative_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CSourceConservative_AdjTurb(void); + + /*! + * \brief Source term integration using a conservative scheme. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); +}; + +/*! + * \class CSourcePieceWise_AdjTurb + * \brief Class for source term integration of the adjoint turbulent equation. + * \ingroup SourceDiscr + * \author A. Bueno. + */ +class CSourcePieceWise_AdjTurb : public CNumerics { +private: + su2double **tau, *Velocity; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CSourcePieceWise_AdjTurb(void); + + /*! + * \brief Source term integration of the adjoint turbulence equation. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); +}; diff --git a/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp b/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp index 5dde95b09999..015747b9fa86 100644 --- a/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp +++ b/SU2_CFD/include/numerics/elasticity/CFEAElasticity.hpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -27,8 +27,8 @@ #pragma once -#include "../../numerics_structure.hpp" - +#include "../CNumerics.hpp" +#include "../../../../Common/include/geometry/elements/CElement.hpp" /*! * \class CFEAElasticity @@ -91,7 +91,7 @@ class CFEAElasticity : public CNumerics { * \param[in] val_nVar - Number of variables of the problem. * \param[in] config - Definition of the particular problem. */ - CFEAElasticity(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + CFEAElasticity(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config); /*! * \brief Destructor of the class. @@ -153,28 +153,28 @@ class CFEAElasticity : public CNumerics { * \param[in,out] element_container - Element whose mass matrix is being built. * \param[in] config - Definition of the problem. */ - void Compute_Mass_Matrix(CElement *element_container, CConfig *config) final; + void Compute_Mass_Matrix(CElement *element_container, const CConfig *config) final; /*! * \brief Compute the nodal gravity loads for an element. * \param[in,out] element_container - The element for which the dead loads are computed. * \param[in] config - Definition of the problem. */ - void Compute_Dead_Load(CElement *element_container, CConfig *config) final; + void Compute_Dead_Load(CElement *element_container, const CConfig *config) final; /*! * \brief Build the tangent stiffness matrix of an element. * \param[in,out] element_container - Element whose tangent matrix is being built. * \param[in] config - Definition of the problem. */ - inline void Compute_Tangent_Matrix(CElement *element_container, CConfig *config) override { }; + inline void Compute_Tangent_Matrix(CElement *element_container, const CConfig *config) override { }; /*! * \brief Compute averaged nodal stresses (for post processing). * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - inline void Compute_Averaged_NodalStress(CElement *element_container, CConfig *config) override { }; + inline void Compute_Averaged_NodalStress(CElement *element_container, const CConfig *config) override { }; protected: /*! @@ -182,20 +182,20 @@ class CFEAElasticity : public CNumerics { * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - virtual void Compute_Constitutive_Matrix(CElement *element_container, CConfig *config) = 0; + virtual void Compute_Constitutive_Matrix(CElement *element_container, const CConfig *config) = 0; /*! * \brief Set element material properties. * \param[in] element_container - Element defining the properties. * \param[in] config - Definition of the problem. */ - virtual void SetElement_Properties(const CElement *element_container, CConfig *config); + virtual void SetElement_Properties(const CElement *element_container, const CConfig *config); /*! * \brief Read design variables from file. * \param[in] config - Definition of the problem. */ - void ReadDV(CConfig *config); + void ReadDV(const CConfig *config); /*! * \brief Update the Lame parameters (required in AD to account for all dependencies). diff --git a/SU2_CFD/include/numerics/elasticity/CFEALinearElasticity.hpp b/SU2_CFD/include/numerics/elasticity/CFEALinearElasticity.hpp index 6f5794d3381e..df0fd227a447 100644 --- a/SU2_CFD/include/numerics/elasticity/CFEALinearElasticity.hpp +++ b/SU2_CFD/include/numerics/elasticity/CFEALinearElasticity.hpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -53,7 +53,7 @@ class CFEALinearElasticity : public CFEAElasticity { * \param[in] val_nVar - Number of variables of the problem. * \param[in] config - Definition of the particular problem. */ - CFEALinearElasticity(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + CFEALinearElasticity(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config); /*! * \brief Destructor of the class. @@ -65,14 +65,14 @@ class CFEALinearElasticity : public CFEAElasticity { * \param[in,out] element_container - Element whose tangent matrix is being built. * \param[in] config - Definition of the problem. */ - void Compute_Tangent_Matrix(CElement *element_container, CConfig *config) final; + void Compute_Tangent_Matrix(CElement *element_container, const CConfig *config) final; /*! * \brief Compute averaged nodal stresses (for post processing). * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - void Compute_Averaged_NodalStress(CElement *element_container, CConfig *config) final; + void Compute_Averaged_NodalStress(CElement *element_container, const CConfig *config) final; private: /*! @@ -80,6 +80,62 @@ class CFEALinearElasticity : public CFEAElasticity { * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - void Compute_Constitutive_Matrix(CElement *element_container, CConfig *config) final; + void Compute_Constitutive_Matrix(CElement *element_container, const CConfig *config) final; + +}; + + +/*! + * \class CFEAMeshElasticity + * \brief Particular case of linear elasticity used for mesh deformation. + * \ingroup FEM_Discr + * \author R.Sanchez + * \version 7.0.1 "Blackbird" + */ +class CFEAMeshElasticity final : public CFEALinearElasticity { + + bool element_based; + bool stiffness_set; + +public: + /*! + * \brief Default constructor deleted as instantiation with no argument would not allocate fields. + */ + CFEAMeshElasticity() = delete; + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CFEAMeshElasticity(unsigned short val_nDim, unsigned short val_nVar, unsigned long val_nElem, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CFEAMeshElasticity(void) = default; + + /*! + * \brief Set the element-based local Young's modulus in mesh problems + * \param[in] iElem - Element index. + * \param[in] val_E - Value of elasticity modulus. + */ + inline void SetMeshElasticProperties(unsigned long iElem, su2double val_E) override { + if (element_based) E_i[iElem] = val_E; + } + +private: + /*! + * \brief Set element material properties. + * \param[in] element_container - Element defining the properties. + * \param[in] config - Definition of the problem. + */ + inline void SetElement_Properties(const CElement *element, const CConfig *config) override { + if (element_based) { + E = E_i[element->Get_iProp()]; + Compute_Lame_Parameters(); + } + } }; diff --git a/SU2_CFD/include/numerics/elasticity/CFEAMeshElasticity.hpp b/SU2_CFD/include/numerics/elasticity/CFEAMeshElasticity.hpp deleted file mode 100644 index e60caac7f9ff..000000000000 --- a/SU2_CFD/include/numerics/elasticity/CFEAMeshElasticity.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/*! - * \file CFEAMeshNumerics.hpp - * \brief Declaration and inlines of the class to compute - * the stiffness matrix of a linear, pseudo-elastic mesh problem. - * \author Ruben Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, 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 "CFEALinearElasticity.hpp" - - -class CFEAMeshElasticity final : public CFEALinearElasticity { - - bool element_based; - bool stiffness_set; - -public: - /*! - * \brief Default constructor deleted as instantiation with no argument would not allocate fields. - */ - CFEAMeshElasticity() = delete; - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CFEAMeshElasticity(unsigned short val_nDim, unsigned short val_nVar, unsigned long val_nElem, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CFEAMeshElasticity(void) = default; - - /*! - * \brief Set the element-based local Young's modulus in mesh problems - * \param[in] iElem - Element index. - * \param[in] val_E - Value of elasticity modulus. - */ - inline void SetMeshElasticProperties(unsigned long iElem, su2double val_E) override { - if (element_based) E_i[iElem] = val_E; - } - -private: - /*! - * \brief Set element material properties. - * \param[in] element_container - Element defining the properties. - * \param[in] config - Definition of the problem. - */ - inline void SetElement_Properties(const CElement *element, CConfig *config) override { - if (element_based) { - E = E_i[element->Get_iProp()]; - Compute_Lame_Parameters(); - } - } - -}; diff --git a/SU2_CFD/include/numerics/elasticity/CFEANonlinearElasticity.hpp b/SU2_CFD/include/numerics/elasticity/CFEANonlinearElasticity.hpp index 552f039b2099..f1698a1e9fb5 100644 --- a/SU2_CFD/include/numerics/elasticity/CFEANonlinearElasticity.hpp +++ b/SU2_CFD/include/numerics/elasticity/CFEANonlinearElasticity.hpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -92,7 +92,7 @@ class CFEANonlinearElasticity : public CFEAElasticity { * \param[in] val_nVar - Number of variables of the problem. * \param[in] config - Definition of the particular problem. */ - CFEANonlinearElasticity(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + CFEANonlinearElasticity(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config); /*! * \brief Destructor of the class. @@ -113,21 +113,21 @@ class CFEANonlinearElasticity : public CFEAElasticity { * \param[in,out] element_container - Element whose tangent matrix is being built. * \param[in] config - Definition of the problem. */ - void Compute_Tangent_Matrix(CElement *element_container, CConfig *config) final; + void Compute_Tangent_Matrix(CElement *element_container, const CConfig *config) final; /*! * \brief Compute the nodal stress terms for an element. * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - void Compute_NodalStress_Term(CElement *element_container, CConfig *config) final; + void Compute_NodalStress_Term(CElement *element_container, const CConfig *config) final; /*! * \brief Compute averaged nodal stresses (for post processing). * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - void Compute_Averaged_NodalStress(CElement *element_container, CConfig *config) final; + void Compute_Averaged_NodalStress(CElement *element_container, const CConfig *config) final; protected: /*! @@ -135,28 +135,28 @@ class CFEANonlinearElasticity : public CFEAElasticity { * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - virtual void Compute_Plane_Stress_Term(CElement *element_container, CConfig *config) = 0; + virtual void Compute_Plane_Stress_Term(CElement *element_container, const CConfig *config) = 0; /*! * \brief Compute the stress tensor. * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - virtual void Compute_Stress_Tensor(CElement *element_container, CConfig *config) = 0; + virtual void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) = 0; /*! * \brief Update an element with Maxwell's stress. * \param[in,out] element_container - The finite element. * \param[in] config - Definition of the problem. */ - void Add_MaxwellStress(CElement *element_container, CConfig *config); + void Add_MaxwellStress(CElement *element_container, const CConfig *config); /*! * \brief Set element electric properties. * \param[in] element_container - Element defining the properties. * \param[in] config - Definition of the problem. */ - void SetElectric_Properties(const CElement *element_container, CConfig *config); + void SetElectric_Properties(const CElement *element_container, const CConfig *config); /*! * \brief TODO: Describe what this does. diff --git a/SU2_CFD/include/numerics/elasticity/CFEM_DielectricElastomer.hpp b/SU2_CFD/include/numerics/elasticity/CFEM_DielectricElastomer.hpp deleted file mode 100644 index 9e9308ebe97d..000000000000 --- a/SU2_CFD/include/numerics/elasticity/CFEM_DielectricElastomer.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/*! - * \file CFEM_DielectricElastomer.hpp - * \brief Class for computing the constitutive and stress tensors for a dielectric elastomer. - * \author Ruben Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, 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 "CFEANonlinearElasticity.hpp" - - -/*! - * \class CFEM_DielectricElastomer - * \brief Class for computing the constitutive and stress tensors for a dielectric elastomer. - * \ingroup FEM_Discr - * \author R.Sanchez - * \version 7.0.1 "Blackbird" - */ -class CFEM_DielectricElastomer final : public CFEANonlinearElasticity { - -public: - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CFEM_DielectricElastomer(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CFEM_DielectricElastomer(void) = default; - -private: - /*! - * \brief Compute the plane stress term. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - inline void Compute_Plane_Stress_Term(CElement *element_container, CConfig *config) override { }; - - /*! - * \brief Compute the constitutive matrix. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Constitutive_Matrix(CElement *element_container, CConfig *config) override; - - /*! - * \brief Compute the stress tensor. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Stress_Tensor(CElement *element_container, CConfig *config) override; - -}; diff --git a/SU2_CFD/include/numerics/elasticity/CFEM_IdealDE.hpp b/SU2_CFD/include/numerics/elasticity/CFEM_IdealDE.hpp deleted file mode 100644 index 7d040cac41dc..000000000000 --- a/SU2_CFD/include/numerics/elasticity/CFEM_IdealDE.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/*! - * \file CFEM_IdealDE.hpp - * \brief Class for computing the constitutive and stress tensors for a nearly-incompressible ideal DE. - * \author Ruben Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, 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 "CFEANonlinearElasticity.hpp" - -/*! - * \class CFEM_IdealDE - * \brief Class for computing the constitutive and stress tensors for a nearly-incompressible ideal DE. - * \ingroup FEM_Discr - * \author R.Sanchez - * \version 7.0.1 "Blackbird" - */ -class CFEM_IdealDE final : public CFEANonlinearElasticity { - - su2double trbbar, Eg, Eg23, Ek, Pr; /*!< \brief Variables of the model calculation. */ - -public: - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CFEM_IdealDE(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CFEM_IdealDE(void) = default; - -private: - /*! - * \brief Compute the plane stress term. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Plane_Stress_Term(CElement *element_container, CConfig *config) override; - - /*! - * \brief Compute the constitutive matrix. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Constitutive_Matrix(CElement *element_container, CConfig *config) override; - - /*! - * \brief Compute the stress tensor. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Stress_Tensor(CElement *element_container, CConfig *config) override; - -}; diff --git a/SU2_CFD/include/numerics/elasticity/CFEM_Knowles_NearInc.hpp b/SU2_CFD/include/numerics/elasticity/CFEM_Knowles_NearInc.hpp deleted file mode 100644 index ac991d586074..000000000000 --- a/SU2_CFD/include/numerics/elasticity/CFEM_Knowles_NearInc.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/*! - * \file CFEM_Knowles_NearInc.hpp - * \brief Class for computing the constitutive and stress tensors - * for the Knowles nearly-incompressible material. - * \author Ruben Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, 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 "CFEANonlinearElasticity.hpp" - - -/*! - * \class CFEM_NeoHookean_Comp - * \brief Constitutive and stress tensors for a Knowles stored-energy function, nearly incompressible. - * \ingroup FEM_Discr - * \author R.Sanchez - * \version 7.0.1 "Blackbird" - */ -class CFEM_Knowles_NearInc final : public CFEANonlinearElasticity { - - su2double trbbar, term1, term2, Ek, Pr; /*!< \brief Variables of the model calculation. */ - su2double Bk, Nk; /*!< \brief Parameters b and n of the model. */ - -public: - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CFEM_Knowles_NearInc(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CFEM_Knowles_NearInc(void) = default; - -private: - /*! - * \brief Compute the plane stress term. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Plane_Stress_Term(CElement *element_container, CConfig *config) override; - - /*! - * \brief Compute the constitutive matrix. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Constitutive_Matrix(CElement *element_container, CConfig *config) override; - - /*! - * \brief Compute the stress tensor. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Stress_Tensor(CElement *element_container, CConfig *config) override; - -}; diff --git a/SU2_CFD/include/numerics/elasticity/CFEM_NeoHookean_Comp.hpp b/SU2_CFD/include/numerics/elasticity/CFEM_NeoHookean_Comp.hpp deleted file mode 100644 index 548abf84ae68..000000000000 --- a/SU2_CFD/include/numerics/elasticity/CFEM_NeoHookean_Comp.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/*! - * \file CFEM_NeoHookean_Comp.hpp - * \brief Compressible Neo-Hookean FE numerics class. - * \author Ruben Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, 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 "CFEANonlinearElasticity.hpp" - - -/*! - * \class CFEM_NeoHookean_Comp - * \brief Class for computing the constitutive and stress tensors for a neo-Hookean material model, compressible. - * \ingroup FEM_Discr - * \author R.Sanchez - * \version 7.0.1 "Blackbird" - */ -class CFEM_NeoHookean_Comp final : public CFEANonlinearElasticity { - -public: - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CFEM_NeoHookean_Comp(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CFEM_NeoHookean_Comp(void) = default; - -private: - /*! - * \brief Compute the plane stress term. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Plane_Stress_Term(CElement *element_container, CConfig *config) override; - - /*! - * \brief Compute the constitutive matrix. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Constitutive_Matrix(CElement *element_container, CConfig *config) override; - - /*! - * \brief Compute the stress tensor. - * \param[in,out] element_container - The finite element. - * \param[in] config - Definition of the problem. - */ - void Compute_Stress_Tensor(CElement *element_container, CConfig *config) override; - -}; - diff --git a/SU2_CFD/include/numerics/elasticity/nonlinear_models.hpp b/SU2_CFD/include/numerics/elasticity/nonlinear_models.hpp new file mode 100644 index 000000000000..e51c9b50bb11 --- /dev/null +++ b/SU2_CFD/include/numerics/elasticity/nonlinear_models.hpp @@ -0,0 +1,227 @@ +/*! + * \file nonlinear_models.hpp + * \brief Declarations of nonlinear constitutive models. + * \author Ruben Sanchez + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "CFEANonlinearElasticity.hpp" + + +/*! + * \class CFEM_NeoHookean_Comp + * \brief Class for computing the constitutive and stress tensors for a neo-Hookean material model, compressible. + * \ingroup FEM_Discr + * \author R.Sanchez + * \version 7.0.1 "Blackbird" + */ +class CFEM_NeoHookean_Comp final : public CFEANonlinearElasticity { + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CFEM_NeoHookean_Comp(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CFEM_NeoHookean_Comp(void) = default; + +private: + /*! + * \brief Compute the plane stress term. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Plane_Stress_Term(CElement *element_container, const CConfig *config) override; + + /*! + * \brief Compute the constitutive matrix. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Constitutive_Matrix(CElement *element_container, const CConfig *config) override; + + /*! + * \brief Compute the stress tensor. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) override; + +}; + + +/*! + * \class CFEM_NeoHookean_Comp + * \brief Constitutive and stress tensors for a Knowles stored-energy function, nearly incompressible. + * \ingroup FEM_Discr + * \author R.Sanchez + * \version 7.0.1 "Blackbird" + */ +class CFEM_Knowles_NearInc final : public CFEANonlinearElasticity { + + su2double trbbar, term1, term2, Ek, Pr; /*!< \brief Variables of the model calculation. */ + su2double Bk, Nk; /*!< \brief Parameters b and n of the model. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CFEM_Knowles_NearInc(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CFEM_Knowles_NearInc(void) = default; + +private: + /*! + * \brief Compute the plane stress term. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Plane_Stress_Term(CElement *element_container, const CConfig *config) override; + + /*! + * \brief Compute the constitutive matrix. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Constitutive_Matrix(CElement *element_container, const CConfig *config) override; + + /*! + * \brief Compute the stress tensor. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) override; + +}; + + +/*! + * \class CFEM_DielectricElastomer + * \brief Class for computing the constitutive and stress tensors for a dielectric elastomer. + * \ingroup FEM_Discr + * \author R.Sanchez + * \version 7.0.1 "Blackbird" + */ +class CFEM_DielectricElastomer final : public CFEANonlinearElasticity { + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CFEM_DielectricElastomer(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CFEM_DielectricElastomer(void) = default; + +private: + /*! + * \brief Compute the plane stress term. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + inline void Compute_Plane_Stress_Term(CElement *element_container, const CConfig *config) override { }; + + /*! + * \brief Compute the constitutive matrix. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Constitutive_Matrix(CElement *element_container, const CConfig *config) override; + + /*! + * \brief Compute the stress tensor. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) override; + +}; + + +/*! + * \class CFEM_IdealDE + * \brief Class for computing the constitutive and stress tensors for a nearly-incompressible ideal DE. + * \ingroup FEM_Discr + * \author R.Sanchez + * \version 7.0.1 "Blackbird" + */ +class CFEM_IdealDE final : public CFEANonlinearElasticity { + + su2double trbbar, Eg, Eg23, Ek, Pr; /*!< \brief Variables of the model calculation. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CFEM_IdealDE(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CFEM_IdealDE(void) = default; + +private: + /*! + * \brief Compute the plane stress term. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Plane_Stress_Term(CElement *element_container, const CConfig *config) override; + + /*! + * \brief Compute the constitutive matrix. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Constitutive_Matrix(CElement *element_container, const CConfig *config) override; + + /*! + * \brief Compute the stress tensor. + * \param[in,out] element_container - The finite element. + * \param[in] config - Definition of the problem. + */ + void Compute_Stress_Tensor(CElement *element_container, const CConfig *config) override; + +}; diff --git a/SU2_CFD/include/numerics/flow/convection/ausm_slau.hpp b/SU2_CFD/include/numerics/flow/convection/ausm_slau.hpp new file mode 100644 index 000000000000..3139fea00425 --- /dev/null +++ b/SU2_CFD/include/numerics/flow/convection/ausm_slau.hpp @@ -0,0 +1,262 @@ +/*! + * \file ausm_slau.hpp + * \brief Declaration of numerics classes for the AUSM family of schemes, + * including SLAU. The implementation is in ausm.cpp. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../../CNumerics.hpp" + +/*! + * \class CUpwAUSMPLUS_SLAU_Base_Flow + * \brief Base class for AUSM+up(2) and SLAU(2) convective schemes. + * \ingroup ConvDiscr + * \author Amit Sachdeva, P. Gomes + */ +class CUpwAUSMPLUS_SLAU_Base_Flow : public CNumerics { +protected: + bool implicit; + bool UseAccurateJacobian; + bool HasAnalyticalDerivatives; + su2double FinDiffStep; + + su2double MassFlux, DissFlux, Pressure; + su2double Velocity_i[MAXNDIM] = {0.0}, Velocity_j[MAXNDIM] = {0.0}; + su2double *psi_i = nullptr, *psi_j = nullptr; + su2double dmdot_dVi[6], dmdot_dVj[6], dpres_dVi[6], dpres_dVj[6]; + + /*--- Roe variables (for approximate Jacobian) ---*/ + su2double *Lambda = nullptr, *Epsilon = nullptr, RoeVelocity[MAXNDIM] = {0.0}; + su2double **P_Tensor = nullptr, **invP_Tensor = nullptr; + + su2double* Flux = nullptr; /*!< \brief The flux accross the face. */ + su2double** Jacobian_i = nullptr; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j = nullptr; /*!< \brief The Jacobian w.r.t. point j after computation. */ + + /*! + * \brief Compute the mass flux and pressure based on Primitives_i/j, derived classes must implement this method. + * \note See the body of the (empty) default implementation for instructions on how to implement the method. + * \param[in] config - Definition of the particular problem. + * \param[out] mdot - The mass flux. + * \param[out] pressure - The pressure at the control volume face. + */ + virtual void ComputeMassAndPressureFluxes(const CConfig* config, su2double &mdot, su2double &pressure) = 0; + +private: + /*! + * \brief Compute the flux Jacobians of the Roe scheme to use as an approximation. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + */ + void ApproximateJacobian(su2double **val_Jacobian_i, su2double **val_Jacobian_j); + + /*! + * \brief Compute the flux Jacobians using a mix of finite differences and manual differentiation. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + */ + void AccurateJacobian(const CConfig* config, su2double **val_Jacobian_i, su2double **val_Jacobian_j); + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwAUSMPLUS_SLAU_Base_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwAUSMPLUS_SLAU_Base_Flow(void); + + /*! + * \brief Compute the AUSM+ and SLAU family of schemes. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) final; + +}; + +/*! + * \class CUpwAUSMPLUSUP_Flow + * \brief Class for solving an approximate Riemann AUSM+ -up. + * \ingroup ConvDiscr + * \author Amit Sachdeva, P. Gomes + */ +class CUpwAUSMPLUSUP_Flow final : public CUpwAUSMPLUS_SLAU_Base_Flow { +private: + su2double Kp, Ku, sigma; + + /*! + * \brief Mass flux and pressure for the AUSM+up scheme. + * \param[in] config - Definition of the particular problem. + * \param[out] mdot - The mass flux. + * \param[out] pressure - The pressure at the control volume face. + */ + void ComputeMassAndPressureFluxes(const CConfig* config, su2double &mdot, su2double &pressure) override; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwAUSMPLUSUP_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +}; + +/*! + * \class CUpwAUSMPLUSUP2_Flow + * \brief Class for solving an approximate Riemann AUSM+ -up. + * \ingroup ConvDiscr + * \author Amit Sachdeva, P. Gomes + */ +class CUpwAUSMPLUSUP2_Flow final : public CUpwAUSMPLUS_SLAU_Base_Flow { +private: + su2double Kp, sigma; + + /*! + * \brief Mass flux and pressure for the AUSM+up2 scheme. + * \param[in] config - Definition of the particular problem. + * \param[out] mdot - The mass flux. + * \param[out] pressure - The pressure at the control volume face. + */ + void ComputeMassAndPressureFluxes(const CConfig* config, su2double &mdot, su2double &pressure) override; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwAUSMPLUSUP2_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +}; + +/*! + * \class CUpwSLAU_Flow + * \brief Class for solving the Low-Dissipation AUSM. + * \ingroup ConvDiscr + * \author E. Molina, P. Gomes + */ +class CUpwSLAU_Flow : public CUpwAUSMPLUS_SLAU_Base_Flow { +protected: + bool slau_low_diss; + bool slau2; + + /*! + * \brief Mass flux and pressure for the SLAU and SLAU2 schemes. + * \param[in] config - Definition of the particular problem. + * \param[out] mdot - The mass flux. + * \param[out] pressure - The pressure at the control volume face. + */ + void ComputeMassAndPressureFluxes(const CConfig* config, su2double &mdot, su2double &pressure) final; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwSLAU_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config, bool val_low_dissipation); + +}; + +/*! + * \class CUpwSLAU2_Flow + * \brief Class for solving the Simple Low-Dissipation AUSM 2. + * \ingroup ConvDiscr + * \author E. Molina, P. Gomes + */ +class CUpwSLAU2_Flow final : public CUpwSLAU_Flow { +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwSLAU2_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config, bool val_low_dissipation); + +}; + +/*! + * \class CUpwAUSM_Flow + * \brief Class for solving an approximate Riemann AUSM. + * \ingroup ConvDiscr + * \author F. Palacios + */ +class CUpwAUSM_Flow final : public CNumerics { +private: + bool implicit; + su2double *Diff_U; + su2double Velocity_i[MAXNDIM], Velocity_j[MAXNDIM], RoeVelocity[MAXNDIM]; + su2double *ProjFlux_i, *ProjFlux_j; + su2double *delta_wave, delta_vel[MAXNDIM]; + su2double *Lambda, *Epsilon; + su2double **P_Tensor, **invP_Tensor; + su2double sq_vel, Proj_ModJac_Tensor_ij, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, + Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, R, RoeDensity, RoeEnthalpy, RoeSoundSpeed, + ProjVelocity, ProjVelocity_i, ProjVelocity_j; + unsigned short iDim, iVar, jVar, kVar; + su2double mL, mR, mLP, mRM, mF, pLP, pRM, pF, Phi; + + su2double* Flux; /*!< \brief The flux accross the face. */ + su2double** Jacobian_i; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j; /*!< \brief The Jacobian w.r.t. point j after computation. */ +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwAUSM_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwAUSM_Flow(void); + + /*! + * \brief Compute the Roe's flux between two nodes i and j. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; diff --git a/SU2_CFD/include/numerics/flow/convection/centered.hpp b/SU2_CFD/include/numerics/flow/convection/centered.hpp new file mode 100644 index 000000000000..18a682aa23aa --- /dev/null +++ b/SU2_CFD/include/numerics/flow/convection/centered.hpp @@ -0,0 +1,339 @@ +/*! + * \file centered.hpp + * \brief Delaration of numerics classes for centered schemes, + * the implementation is in centered.cpp. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../../CNumerics.hpp" + +/*! + * \class CCentBase_Flow + * \brief Intermediate class to define centered schemes. + * \ingroup ConvDiscr + * \author F. Palacios + */ +class CCentBase_Flow : public CNumerics { + +protected: + unsigned short iDim, iVar, jVar; /*!< \brief Iteration on dimension and variables. */ + bool dynamic_grid; /*!< \brief Consider grid movement. */ + bool implicit; /*!< \brief Implicit calculation (compute Jacobians). */ + su2double fix_factor; /*!< \brief Fix factor for dissipation Jacobians (more diagonal dominance). */ + + su2double Velocity_i[MAXNDIM] = {0.0}; /*!< \brief Velocity at node i. */ + su2double Velocity_j[MAXNDIM] = {0.0}; /*!< \brief Velocity at node j. */ + su2double MeanVelocity[MAXNDIM] = {0.0}; /*!< \brief Mean velocity. */ + su2double ProjVelocity_i, ProjVelocity_j; /*!< \brief Velocities in the face normal direction. */ + su2double sq_vel_i, sq_vel_j; /*!< \brief Squared norm of the velocity vectors. */ + su2double Energy_i, Energy_j, MeanEnergy; /*!< \brief Energy at nodes i and j and mean. */ + su2double MeanDensity, MeanPressure, MeanEnthalpy; /*!< \brief Mean density, pressure, and enthalpy. */ + su2double *ProjFlux = nullptr; /*!< \brief "The" flux. */ + + su2double *Diff_U = nullptr, *Diff_Lapl = nullptr; /*!< \brief Differences of conservatives and undiv. Laplacians. */ + su2double Local_Lambda_i, Local_Lambda_j, MeanLambda; /*!< \brief Local eingenvalues. */ + su2double Param_p, Phi_i, Phi_j, StretchingFactor; /*!< \brief Streching parameters. */ + su2double cte_0, cte_1; /*!< \brief Constants for the scalar dissipation Jacobian. */ + + su2double ProjGridVel; /*!< \brief Projected grid velocity. */ + + su2double** Jacobian_i = nullptr; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j = nullptr; /*!< \brief The Jacobian w.r.t. point j after computation. */ + + /*! + * \brief Hook method for derived classes to define preaccumulated variables, optional to implement. + * \return true if any variable was set as preacc. input, in which case the residual will be output. + */ + virtual bool SetPreaccInVars(void) {return false;} + + /*! + * \brief Derived classes must implement this method, called in ComputeResidual after inviscid part. + * \param[in,out] val_residual - Pointer to the convective flux contribution to the residual. + * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + */ + virtual void DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) = 0; + + /*! + * \brief Add the contribution of a scalar dissipation term to the Jacobians. + * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i. + * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j. + */ + void ScalarDissipationJacobian(su2double **val_Jacobian_i, su2double **val_Jacobian_j); + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CCentBase_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + virtual ~CCentBase_Flow(void); + + /*! + * \brief Compute the flow residual using a centered method with artificial dissipation. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) final; + +}; + +/*! + * \class CCentLax_Flow + * \brief Class for computing the Lax-Friedrich centered scheme. + * \ingroup ConvDiscr + * \author F. Palacios + */ +class CCentLax_Flow final : public CCentBase_Flow { +private: + su2double Param_Kappa_0; /*!< \brief Artificial dissipation parameter. */ + su2double sc0; /*!< \brief Streching parameter. */ + su2double Epsilon_0; /*!< \brief Artificial dissipation coefficient. */ + + /*! + * \brief Lax-Friedrich first order dissipation term. + * \param[in,out] val_residual - Pointer to the convective flux contribution to the residual. + * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + */ + void DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) override; + + /*! + * \brief Set input variables for AD preaccumulation. + * \return true, as we will define inputs. + */ + bool SetPreaccInVars(void) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CCentLax_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +}; + +/*! + * \class CCentJST_KE_Flow + * \brief Class for centered scheme - JST_KE (no 4th dissipation order term). + * \ingroup ConvDiscr + * \author F. Palacios + */ +class CCentJST_KE_Flow final : public CCentBase_Flow { + +private: + su2double Param_Kappa_2; /*!< \brief Artificial dissipation parameter. */ + su2double sc2; /*!< \brief Streching parameter. */ + su2double Epsilon_2; /*!< \brief Artificial dissipation coefficient. */ + + /*! + * \brief JST_KE second order dissipation term. + * \param[in,out] val_residual - Pointer to the convective flux contribution to the residual. + * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + */ + void DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) override; + + /*! + * \brief Set input variables for AD preaccumulation. + * \return true, as we will define inputs. + */ + bool SetPreaccInVars(void); + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CCentJST_KE_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +}; + +/*! + * \class CCentJST_Flow + * \brief Class for centered scheme - JST. + * \ingroup ConvDiscr + * \author F. Palacios + */ +class CCentJST_Flow final : public CCentBase_Flow { + +private: + su2double Param_Kappa_2, Param_Kappa_4; /*!< \brief Artificial dissipation parameters. */ + su2double sc2, sc4; /*!< \brief Streching parameters. */ + su2double Epsilon_2, Epsilon_4; /*!< \brief Artificial dissipation coefficients. */ + + /*! + * \brief JST second and forth order dissipation terms. + * \param[in,out] val_residual - Pointer to the convective flux contribution to the residual. + * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + */ + void DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) override; + + /*! + * \brief Set input variables for AD preaccumulation. + * \return true, as we will define inputs. + */ + bool SetPreaccInVars(void) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CCentJST_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +}; + +/*! + * \class CCentLaxInc_Flow + * \brief Class for computing the Lax-Friedrich centered scheme (modified with incompressible preconditioning). + * \ingroup ConvDiscr + * \author F. Palacios, T. Economon + */ +class CCentLaxInc_Flow final : public CNumerics { +private: + unsigned short iDim, iVar, jVar; /*!< \brief Iteration on dimension and variables. */ + su2double *Diff_V, /*!< \brief Difference of primitive variables. */ + *Velocity_i, *Velocity_j, /*!< \brief Velocity at node 0 and 1. */ + *MeanVelocity, ProjVelocity_i, + ProjVelocity_j, /*!< \brief Mean and projected velocities. */ + *ProjFlux, /*!< \brief Projected inviscid flux tensor. */ + sq_vel_i, sq_vel_j, /*!< \brief Modulus of the velocity and the normal vector. */ + Temperature_i, Temperature_j, /*!< \brief Temperature at node 0 and 1. */ + MeanDensity, MeanPressure, + MeanBetaInc2, MeanEnthalpy, + MeanCp, MeanTemperature, /*!< \brief Mean values of primitive variables. */ + MeandRhodT, /*!< \brief Derivative of density w.r.t. temperature (variable density flows). */ + Param_p, Param_Kappa_0, /*!< \brief Artificial dissipation parameters. */ + Local_Lambda_i, Local_Lambda_j, + MeanLambda, /*!< \brief Local eingenvalues. */ + Phi_i, Phi_j, sc0, + StretchingFactor, /*!< \brief Streching parameters. */ + Epsilon_0; /*!< \brief Artificial dissipation values. */ + su2double **Precon; + bool implicit, /*!< \brief Implicit calculation. */ + dynamic_grid, /*!< \brief Modification for grid movement. */ + variable_density, /*!< \brief Variable density incompressible flows. */ + energy; /*!< \brief computation with the energy equation. */ + + su2double** Jacobian_i = nullptr; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j = nullptr; /*!< \brief The Jacobian w.r.t. point j after computation. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CCentLaxInc_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CCentLaxInc_Flow(void); + + /*! + * \brief Compute the flow residual using a Lax method. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CCentJSTInc_Flow + * \brief Class for centered scheme - modified JST with incompressible preconditioning. + * \ingroup ConvDiscr + * \author F. Palacios, T. Economon + */ +class CCentJSTInc_Flow final : public CNumerics { + +private: + unsigned short iDim, iVar, jVar; /*!< \brief Iteration on dimension and variables. */ + su2double *Diff_V, *Diff_Lapl, /*!< \brief Diference of primitive variables and undivided laplacians. */ + *Velocity_i, *Velocity_j, /*!< \brief Velocity at node 0 and 1. */ + *MeanVelocity, ProjVelocity_i, + ProjVelocity_j, /*!< \brief Mean and projected velocities. */ + sq_vel_i, sq_vel_j, /*!< \brief Modulus of the velocity and the normal vector. */ + Temperature_i, Temperature_j, /*!< \brief Temperature at node 0 and 1. */ + MeanDensity, MeanPressure, + MeanBetaInc2, MeanEnthalpy, + MeanCp, MeanTemperature, /*!< \brief Mean values of primitive variables. */ + MeandRhodT, /*!< \brief Derivative of density w.r.t. temperature (variable density flows). */ + Param_p, Param_Kappa_2, + Param_Kappa_4, /*!< \brief Artificial dissipation parameters. */ + Local_Lambda_i, Local_Lambda_j, + MeanLambda, /*!< \brief Local eingenvalues. */ + Phi_i, Phi_j, sc2, sc4, + StretchingFactor, /*!< \brief Streching parameters. */ + *ProjFlux, /*!< \brief Projected inviscid flux tensor. */ + Epsilon_2, Epsilon_4; /*!< \brief Artificial dissipation values. */ + su2double **Precon; + bool implicit, /*!< \brief Implicit calculation. */ + dynamic_grid, /*!< \brief Modification for grid movement. */ + variable_density, /*!< \brief Variable density incompressible flows. */ + energy; /*!< \brief computation with the energy equation. */ + + su2double** Jacobian_i = nullptr; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j = nullptr; /*!< \brief The Jacobian w.r.t. point j after computation. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CCentJSTInc_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CCentJSTInc_Flow(void); + + /*! + * \brief Compute the flow residual using a JST method. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; diff --git a/SU2_CFD/include/numerics/flow/convection/cusp.hpp b/SU2_CFD/include/numerics/flow/convection/cusp.hpp new file mode 100644 index 000000000000..e62f9c453075 --- /dev/null +++ b/SU2_CFD/include/numerics/flow/convection/cusp.hpp @@ -0,0 +1,69 @@ +/*! + * \file cusp.hpp + * \brief Declaration of the CUSP numerics class. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../../CNumerics.hpp" + +/*! + * \class CUpwCUSP_Flow + * \brief Class for centered scheme - CUSP. + * \ingroup ConvDiscr + * \author F. Palacios + */ +class CUpwCUSP_Flow final : public CNumerics { + +private: + su2double Velocity_i[MAXNDIM], Velocity_j[MAXNDIM], *ProjFlux_i, *ProjFlux_j; + bool implicit; + + su2double* Flux; /*!< \brief The flux accross the face. */ + su2double** Jacobian_i; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j; /*!< \brief The Jacobian w.r.t. point j after computation. */ +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwCUSP_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwCUSP_Flow(void); + + /*! + * \brief Compute the flow residual using a JST method. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; diff --git a/SU2_CFD/include/numerics/flow/convection/fds.hpp b/SU2_CFD/include/numerics/flow/convection/fds.hpp new file mode 100644 index 000000000000..6747ffd5028e --- /dev/null +++ b/SU2_CFD/include/numerics/flow/convection/fds.hpp @@ -0,0 +1,83 @@ +/*! + * \file fds.hpp + * \brief Declarations of classes for Flux-Difference-Spliting schemes, + * the implementations are in fds.cpp + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../../CNumerics.hpp" + +/*! + * \class CUpwFDSInc_Flow + * \brief Class for solving a Flux Difference Splitting (FDS) upwind method for the incompressible flow equations. + * \ingroup ConvDiscr + * \author F. Palacios, T. Economon + */ +class CUpwFDSInc_Flow final : public CNumerics { +private: + bool implicit, /*!< \brief Implicit calculation. */ + dynamic_grid, /*!< \brief Modification for grid movement. */ + variable_density, /*!< \brief Variable density incompressible flows. */ + energy; /*!< \brief computation with the energy equation. */ + su2double *Diff_V; + su2double *Velocity_i, *Velocity_j, *MeanVelocity; + su2double *ProjFlux_i, *ProjFlux_j; + su2double *Lambda, *Epsilon; + su2double **Precon, **invPrecon_A; + su2double Proj_ModJac_Tensor_ij, Pressure_i, + Pressure_j, ProjVelocity, + MeandRhodT, dRhodT_i, dRhodT_j, /*!< \brief Derivative of density w.r.t. temperature (variable density flows). */ + Temperature_i, Temperature_j, /*!< \brief Temperature at node 0 and 1. */ + MeanDensity, MeanPressure, MeanSoundSpeed, MeanBetaInc2, MeanEnthalpy, MeanCp, MeanTemperature; /*!< \brief Mean values of primitive variables. */ + unsigned short iDim, iVar, jVar, kVar; + + su2double* Flux = nullptr; /*!< \brief The flux / residual across the edge. */ + su2double** Jacobian_i = nullptr; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j = nullptr; /*!< \brief The Jacobian w.r.t. point j after computation. */ + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwFDSInc_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwFDSInc_Flow(void); + + /*! + * \brief Compute the upwind flux between two nodes i and j. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; diff --git a/SU2_CFD/include/numerics/flow/convection/fvs.hpp b/SU2_CFD/include/numerics/flow/convection/fvs.hpp new file mode 100644 index 000000000000..9eedb36749c9 --- /dev/null +++ b/SU2_CFD/include/numerics/flow/convection/fvs.hpp @@ -0,0 +1,76 @@ +/*! + * \file fvs.hpp + * \brief Delarations of classes for Flux-Vector-Spliting schemes, + * the implementations are in fvs.cpp. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../../CNumerics.hpp" + +/*! + * \class CUpwMSW_Flow + * \brief Class for solving a flux-vector splitting method by Steger & Warming, modified version. + * \ingroup ConvDiscr + * \author S. Copeland + */ +class CUpwMSW_Flow final : public CNumerics { +private: + bool implicit; + su2double *Diff_U; + su2double *u_i, *u_j, *ust_i, *ust_j; + su2double *Fc_i, *Fc_j; + su2double *Lambda_i, *Lambda_j; + su2double rhos_i, rhos_j; + su2double *Ust_i, *Ust_j, *Vst_i, *Vst_j, *Velst_i, *Velst_j; + su2double **P_Tensor, **invP_Tensor; + unsigned short nPrimVar, nVar, nDim; + + su2double** Jacobian_i; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j; /*!< \brief The Jacobian w.r.t. point j after computation. */ + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwMSW_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwMSW_Flow(void); + + /*! + * \brief Compute the Roe's flux between two nodes i and j. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; diff --git a/SU2_CFD/include/numerics/flow/convection/hllc.hpp b/SU2_CFD/include/numerics/flow/convection/hllc.hpp new file mode 100644 index 000000000000..b148bcde5224 --- /dev/null +++ b/SU2_CFD/include/numerics/flow/convection/hllc.hpp @@ -0,0 +1,140 @@ +/*! + * \file hllc.hpp + * \brief Declaration of HLLC numerics classes, implemented in hllc.cpp. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../../CNumerics.hpp" + +/*! + * \class CUpwHLLC_Flow + * \brief Class for solving an approximate Riemann HLLC. + * \ingroup ConvDiscr + * \author G. Gori, Politecnico di Milano + * \version 7.0.1 "Blackbird" + */ +class CUpwHLLC_Flow final : public CNumerics { +private: + bool implicit, dynamic_grid; + unsigned short iDim, jDim, iVar, jVar; + + su2double *IntermediateState; + su2double *Velocity_i, *Velocity_j, *RoeVelocity; + + su2double sq_vel_i, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, ProjVelocity_i; + su2double sq_vel_j, Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, ProjVelocity_j; + + su2double sq_velRoe, RoeDensity, RoeEnthalpy, RoeSoundSpeed, RoeProjVelocity, ProjInterfaceVel; + + su2double sL, sR, sM, pStar, EStar, rhoSL, rhoSR, Rrho, kappa; + + su2double Omega, RHO, OmegaSM; + su2double *dSm_dU, *dPI_dU, *drhoStar_dU, *dpStar_dU, *dEStar_dU; + + su2double* Flux; /*!< \brief The flux accross the face. */ + su2double** Jacobian_i; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j; /*!< \brief The Jacobian w.r.t. point j after computation. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwHLLC_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwHLLC_Flow(void); + + /*! + * \brief Compute the Roe's flux between two nodes i and j. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CUpwGeneralHLLC_Flow + * \brief Class for solving an approximate Riemann HLLC. + * \ingroup ConvDiscr + * \author G. Gori, Politecnico di Milano + * \version 7.0.1 "Blackbird" + */ +class CUpwGeneralHLLC_Flow final : public CNumerics { +private: + bool implicit, dynamic_grid; + unsigned short iDim, jDim, iVar, jVar; + + su2double *IntermediateState; + su2double *Velocity_i, *Velocity_j, *RoeVelocity; + + su2double sq_vel_i, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, ProjVelocity_i, StaticEnthalpy_i, StaticEnergy_i; + su2double sq_vel_j, Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, ProjVelocity_j, StaticEnthalpy_j, StaticEnergy_j; + + su2double sq_velRoe, RoeDensity, RoeEnthalpy, RoeSoundSpeed, RoeProjVelocity, ProjInterfaceVel; + su2double Kappa_i, Kappa_j, Chi_i, Chi_j, RoeKappa, RoeChi, RoeKappaStaticEnthalpy; + + su2double sL, sR, sM, pStar, EStar, rhoSL, rhoSR, Rrho, kappa; + + su2double Omega, RHO, OmegaSM; + su2double *dSm_dU, *dPI_dU, *drhoStar_dU, *dpStar_dU, *dEStar_dU; + + su2double* Flux; /*!< \brief The flux accross the face. */ + su2double** Jacobian_i; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j; /*!< \brief The Jacobian w.r.t. point j after computation. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwGeneralHLLC_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwGeneralHLLC_Flow(void); + + /*! + * \brief Compute the Roe's flux between two nodes i and j. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + + /*! + * \brief Compute the Average quantities for a general fluid flux between two nodes i and j. + * Using the approach of Vinokur and Montagne' + */ + void VinokurMontagne(); +}; diff --git a/SU2_CFD/include/numerics/flow/convection/roe.hpp b/SU2_CFD/include/numerics/flow/convection/roe.hpp new file mode 100644 index 000000000000..9fbb697b4f41 --- /dev/null +++ b/SU2_CFD/include/numerics/flow/convection/roe.hpp @@ -0,0 +1,284 @@ +/*! + * \file roe.hpp + * \brief Delarations of numerics classes for Roe-type schemes, + * implemented in roe.cpp. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../../CNumerics.hpp" + +/*! + * \class CUpwRoeBase_Flow + * \brief Intermediate base class for Roe schemes on ideal gas. + * \ingroup ConvDiscr + * \author A. Bueno, F. Palacios, P. Gomes + */ +class CUpwRoeBase_Flow : public CNumerics { +protected: + bool implicit, dynamic_grid, roe_low_dissipation; + su2double Velocity_i[MAXNDIM] = {0.0}, Velocity_j[MAXNDIM] = {0.0}, RoeVelocity[MAXNDIM] = {0.0}; + su2double *Diff_U = nullptr, *Lambda = nullptr; + su2double *ProjFlux_i = nullptr, *Conservatives_i = nullptr; + su2double *ProjFlux_j = nullptr, *Conservatives_j = nullptr; + su2double **P_Tensor = nullptr, **invP_Tensor = nullptr; + su2double RoeDensity, RoeEnthalpy, RoeSoundSpeed, ProjVelocity, RoeSoundSpeed2, kappa; + + su2double* Flux = nullptr; /*!< \brief The flux accross the face. */ + su2double** Jacobian_i = nullptr; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j = nullptr; /*!< \brief The Jacobian w.r.t. point j after computation. */ + + /*! + * \brief Derived classes must specialize this method to add the specifics of the scheme they implement (e.g. low-Mach precond.). + * \param[out] val_residual - Convective flux. + * \param[out] val_Jacobian_i - Flux Jacobian wrt node i conservatives (implicit computation). + * \param[out] val_Jacobian_j - Flux Jacobian wrt node j conservatives (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + virtual void FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, const CConfig* config) = 0; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + * \param[in] val_low_dissipation - Use a low dissipation formulation. + */ + CUpwRoeBase_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config, bool val_low_dissipation); + + /*! + * \brief Destructor of the class. + */ + virtual ~CUpwRoeBase_Flow(void); + + /*! + * \brief Compute the flux from node i to node j, part common to most Roe schemes. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) final; + +}; + +/*! + * \class CUpwRoe_Flow + * \brief Class for solving an approximate Riemann solver of Roe for the flow equations. + * \ingroup ConvDiscr + * \author A. Bueno, F. Palacios, P. Gomes + */ +class CUpwRoe_Flow final : public CUpwRoeBase_Flow { +private: + /*! + * \brief Add standard Roe dissipation to the flux. + * \param[out] val_residual - Convective flux. + * \param[out] val_Jacobian_i - Flux Jacobian wrt node i conservatives (implicit computation). + * \param[out] val_Jacobian_j - Flux Jacobian wrt node j conservatives (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, const CConfig* config) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + * \param[in] val_low_dissipation - Use a low dissipation formulation. + */ + CUpwRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config, bool val_low_dissipation); + +}; + +/*! + * \class CUpwL2Roe_Flow + * \brief Class for solving an approximate Riemann solver of L2Roe for the flow equations. + * \ingroup ConvDiscr + * \author E. Molina, A. Bueno, F. Palacios, P. Gomes + * \version 7.0.1 "Blackbird" + */ +class CUpwL2Roe_Flow final : public CUpwRoeBase_Flow { +private: + /*! + * \brief Add L^2 Roe dissipation to the flux (low-Mach scheme). + * \param[out] val_residual - Convective flux. + * \param[out] val_Jacobian_i - Flux Jacobian wrt node i conservatives (implicit computation). + * \param[out] val_Jacobian_j - Flux Jacobian wrt node j conservatives (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, const CConfig* config) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwL2Roe_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +}; + +/*! + * \class CUpwLMRoe_Flow + * \brief Class for solving an approximate Riemann solver of LMRoe for the flow equations. + * \ingroup ConvDiscr + * \author E. Molina, A. Bueno, F. Palacios, P. Gomes + * \version 7.0.1 "Blackbird" + */ +class CUpwLMRoe_Flow final : public CUpwRoeBase_Flow { +private: + /*! + * \brief Add LMRoe dissipation to the flux (low-Mach scheme). + * \param[out] val_residual - Convective flux. + * \param[out] val_Jacobian_i - Flux Jacobian wrt node i conservatives (implicit computation). + * \param[out] val_Jacobian_j - Flux Jacobian wrt node j conservatives (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, const CConfig* config) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwLMRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +}; + +/*! + * \class CUpwTurkel_Flow + * \brief Class for solving an approximate Riemann solver of Roe with Turkel Preconditioning for the flow equations. + * \ingroup ConvDiscr + * \author A. K. Lonkar + */ +class CUpwTurkel_Flow final : public CNumerics { +private: + bool implicit, dynamic_grid; + su2double *Diff_U; + su2double *Velocity_i, *Velocity_j, *RoeVelocity; + su2double *ProjFlux_i, *ProjFlux_j; + su2double *Lambda, *Epsilon; + su2double **absPeJac, **invRinvPe, **R_Tensor, **Matrix, **Art_Visc; + su2double sq_vel, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, + Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, R, RoePressure, RoeDensity, RoeEnthalpy, RoeSoundSpeed, + ProjVelocity, ProjVelocity_i, ProjVelocity_j; + unsigned short iDim, iVar, jVar, kVar; + su2double Beta, Beta_min, Beta_max; + su2double r_hat, s_hat, t_hat, rhoB2a2, sqr_one_m_Betasqr_Lam1; + su2double Beta2, one_m_Betasqr, one_p_Betasqr, sqr_two_Beta_c_Area; + su2double local_Mach; + + su2double* Flux = nullptr; /*!< \brief The flux accross the face. */ + su2double** Jacobian_i = nullptr; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j = nullptr; /*!< \brief The Jacobian w.r.t. point j after computation. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwTurkel_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwTurkel_Flow(void); + + /*! + * \brief Compute the Roe's flux between two nodes i and j. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CUpwGeneralRoe_Flow + * \brief Class for solving an approximate Riemann solver of Roe for the flow equations for a general fluid model. + * \ingroup ConvDiscr + * \author S.Vitale, G.Gori, M.Pini + */ +class CUpwGeneralRoe_Flow final : public CNumerics { +private: + + bool implicit, dynamic_grid; + + su2double *Diff_U; + su2double *Velocity_i, *Velocity_j, *RoeVelocity; + su2double *ProjFlux_i, *ProjFlux_j; + su2double *delta_wave, *delta_vel; + su2double *Lambda, *Epsilon, MaxLambda, Delta; + su2double **P_Tensor, **invP_Tensor; + su2double sq_vel, Proj_ModJac_Tensor_ij, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, + + Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, R, RoeDensity, RoeEnthalpy, RoeSoundSpeed, RoeSoundSpeed2, + ProjVelocity, ProjVelocity_i, ProjVelocity_j, proj_delta_vel, delta_p, delta_rho, kappa; + unsigned short iDim, iVar, jVar, kVar; + + su2double StaticEnthalpy_i, StaticEnergy_i, StaticEnthalpy_j, StaticEnergy_j, Kappa_i, Kappa_j, Chi_i, Chi_j, Velocity2_i, Velocity2_j; + su2double RoeKappa, RoeChi; + + su2double* Flux = nullptr; /*!< \brief The flux accross the face. */ + su2double** Jacobian_i = nullptr; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j = nullptr; /*!< \brief The Jacobian w.r.t. point j after computation. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwGeneralRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwGeneralRoe_Flow(void); + + /*! + * \brief Compute the Roe's flux between two nodes i and j. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + + /*! + * \brief Compute the Average for a general fluid flux between two nodes i and j. + * Using the approach of Vinokur and Montagne' + */ + void ComputeRoeAverage(); + +}; diff --git a/SU2_CFD/include/numerics/flow/flow_diffusion.hpp b/SU2_CFD/include/numerics/flow/flow_diffusion.hpp new file mode 100644 index 000000000000..e50eb3a59d58 --- /dev/null +++ b/SU2_CFD/include/numerics/flow/flow_diffusion.hpp @@ -0,0 +1,440 @@ +/*! + * \file flow_diffusion.hpp + * \brief Delarations of numerics classes for viscous flux computation. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../CNumerics.hpp" + +/*! + * \class CAvgGrad_Base + * \brief A base class for computing viscous terms using an average of gradients. + * \details This is the base class for the numerics classes that compute the + * viscous fluxes for the flow solvers (i.e. compressible or incompressible + * Navier Stokes). The actual numerics classes derive from this class. + * This class is used to share functions and variables that are common to all + * of the flow viscous numerics. For example, the turbulent stress tensor + * is computed identically for all three derived classes. + * \ingroup ViscDiscr + * \author C. Pederson, A. Bueno, F. Palacios, T. Economon + */ +class CAvgGrad_Base : public CNumerics { +protected: + const unsigned short nPrimVar; /*!< \brief The size of the primitive variable array used in the numerics class. */ + const bool correct_gradient; /*!< \brief Apply a correction to the gradient term */ + bool implicit = false; /*!< \brief Implicit calculus. */ + su2double + heat_flux_vector[MAXNDIM] = {0.0}, /*!< \brief Flux of total energy due to molecular and turbulent diffusion */ + *heat_flux_jac_i = nullptr, /*!< \brief Jacobian of the molecular + turbulent heat flux vector, projected onto the normal vector. */ + **tau_jacobian_i = nullptr; /*!< \brief Jacobian of the viscous + turbulent stress tensor, projected onto the normal vector. */ + su2double *Mean_PrimVar = nullptr; /*!< \brief Mean primitive variables. */ + const su2double + *PrimVar_i = nullptr, + *PrimVar_j = nullptr; /*!< \brief Primitives variables at point i and j. */ + su2double **Mean_GradPrimVar = nullptr, /*!< \brief Mean value of the gradient. */ + Mean_Laminar_Viscosity, /*!< \brief Mean value of the viscosity. */ + Mean_Eddy_Viscosity, /*!< \brief Mean value of the eddy viscosity. */ + Mean_turb_ke, /*!< \brief Mean value of the turbulent kinetic energy. */ + Mean_TauWall, /*!< \brief Mean wall shear stress (wall functions). */ + TauWall_i, TauWall_j, /*!< \brief Wall shear stress at point i and j (wall functions). */ + dist_ij_2, /*!< \brief Length of the edge and face, squared */ + Edge_Vector[MAXNDIM] = {0.0}, /*!< \brief Vector from point i to point j. */ + *Proj_Mean_GradPrimVar_Edge = nullptr; /*!< \brief Inner product of the Mean gradient and the edge vector. */ + + su2double** Jacobian_i = nullptr; /*!< \brief The Jacobian w.r.t. point i after computation. */ + su2double** Jacobian_j = nullptr; /*!< \brief The Jacobian w.r.t. point j after computation. */ + + /*! + * \brief Add a correction using a Quadratic Constitutive Relation + * + * This function requires that the stress tensor already be + * computed using \ref GetStressTensor + * + * See: Spalart, P. R., "Strategies for Turbulence Modelling and + * Simulation," International Journal of Heat and Fluid Flow, Vol. 21, + * 2000, pp. 252-263 + * + * \param[in] val_gradprimvar + */ + void AddQCR(const su2double* const *val_gradprimvar); + + /*! + * \brief Scale the stress tensor using a predefined wall stress. + * + * This function requires that the stress tensor already be + * computed using \ref GetStressTensor + * + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[in] val_tau_wall - The wall stress + */ + void AddTauWall(const su2double *val_normal, + su2double val_tau_wall); + + /** + * \brief Calculate the Jacobian of the viscous + turbulent stress tensor + * + * This function is intended only for the compressible flow solver. + * This Jacobian is projected onto the normal vector, so it is of dimension + * [nDim][nVar] + * + * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. + * \param[in] val_laminar_viscosity - Value of the laminar viscosity. + * \param[in] val_eddy_viscosity - Value of the eddy viscosity. + * \param[in] val_dist_ij - Distance between the points. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + */ + void SetTauJacobian(const su2double* val_Mean_PrimVar, + su2double val_laminar_viscosity, + su2double val_eddy_viscosity, + su2double val_dist_ij, + const su2double *val_normal); + + + /** + * \brief Calculate the Jacobian of the viscous and turbulent stress tensor + * + * This function is intended only for the incompressible flow solver. + * This Jacobian is projected onto the normal vector, so it is of dimension + * [nDim][nVar] + * + * \param[in] val_laminar_viscosity - Value of the laminar viscosity. + * \param[in] val_eddy_viscosity - Value of the eddy viscosity. + * \param[in] val_dist_ij - Distance between the points. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + */ + void SetIncTauJacobian(su2double val_laminar_viscosity, + su2double val_eddy_viscosity, + su2double val_dist_ij, + const su2double *val_normal); + + /*! + * \brief Compute the projection of the viscous fluxes into a direction. + * + * The heat flux vector and the stress tensor must be calculated before + * calling this function. + * + * \param[in] val_primvar - Primitive variables. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + */ + void GetViscousProjFlux(const su2double *val_primvar, + const su2double *val_normal); + + /*! + * \brief TSL-Approximation of Viscous NS Jacobians. + * + * The Jacobians of the heat flux vector and the stress tensor must be + * calculated before calling this function. + * + * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. + * \param[in] val_dS - Area of the face between two nodes. + * \param[in] val_Proj_Visc_Flux - Pointer to the projected viscous flux. + * \param[out] val_Proj_Jac_Tensor_i - Pointer to the projected viscous Jacobian at point i. + * \param[out] val_Proj_Jac_Tensor_j - Pointer to the projected viscous Jacobian at point j. + */ + void GetViscousProjJacs(const su2double *val_Mean_PrimVar, + su2double val_dS, + const su2double *val_Proj_Visc_Flux, + su2double **val_Proj_Jac_Tensor_i, + su2double **val_Proj_Jac_Tensor_j); + + /*! + * \brief Apply a correction to the gradient to reduce the truncation error + * + * \param[in] val_PrimVar_i - Primitive variables at point i + * \param[in] val_PrimVar_j - Primitive variables at point j + * \param[in] val_edge_vector - The vector between points i and j + * \param[in] val_dist_ij_2 - The distance between points i and j, squared + * \param[in] val_nPrimVar - The number of primitive variables + */ + void CorrectGradient(su2double** GradPrimVar, + const su2double* val_PrimVar_i, + const su2double* val_PrimVar_j, + const su2double* val_edge_vector, + su2double val_dist_ij_2, + const unsigned short val_nPrimVar); + + /*! + * \brief Initialize the Reynolds Stress Matrix + * \param[in] turb_ke turbulent kinetic energy of node + */ + void SetReynoldsStressMatrix(su2double turb_ke); + + /*! + * \brief Perturb the Reynolds stress tensor based on parameters + * \param[in] turb_ke: turbulent kinetic energy of the noce + * \param[in] Eig_Val_Comp: Defines type of eigenspace perturbation + * \param[in] beta_delta: Defines the amount of eigenvalue perturbation + */ + void SetPerturbedRSM(su2double turb_ke, const CConfig* config); + + /*! + * \brief Get the mean rate of strain matrix based on velocity gradients + * \param[in] S_ij + */ + void GetMeanRateOfStrainMatrix(su2double **S_ij) const; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] val_nPrimVar - Number of primitive variables to use. + * \param[in] val_correct_grad - Apply a correction to the gradient + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_Base(unsigned short val_nDim, unsigned short val_nVar, + unsigned short val_nPrimVar, + bool val_correct_grad, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGrad_Base(); + + /*! + * \brief Set the value of the wall shear stress at point i and j (wall functions). + * \param[in] val_tauwall_i - Value of the wall shear stress at point i. + * \param[in] val_tauwall_j - Value of the wall shear stress at point j. + */ + inline void SetTauWall(su2double val_tauwall_i, su2double val_tauwall_j) override { + TauWall_i = val_tauwall_i; + TauWall_j = val_tauwall_j; + } + + /*! + * \brief Calculate the viscous + turbulent stress tensor + * \param[in] val_primvar - Primitive variables. + * \param[in] val_gradprimvar - Gradient of the primitive variables. + * \param[in] val_turb_ke - Turbulent kinetic energy + * \param[in] val_laminar_viscosity - Laminar viscosity. + * \param[in] val_eddy_viscosity - Eddy viscosity. + */ + void SetStressTensor(const su2double *val_primvar, + const su2double* const *val_gradprimvar, + su2double val_turb_ke, + su2double val_laminar_viscosity, + su2double val_eddy_viscosity); + + /*! + * \brief Get a component of the viscous stress tensor. + * + * \param[in] iDim - The first index + * \param[in] jDim - The second index + * \return The component of the viscous stress tensor at iDim, jDim + */ + inline su2double GetStressTensor(unsigned short iDim, unsigned short jDim) const { return tau[iDim][jDim];} + + /*! + * \brief Get a component of the heat flux vector. + * \param[in] iDim - The index of the component + * \return The component of the heat flux vector at iDim + */ + inline su2double GetHeatFluxVector(unsigned short iDim) const { return heat_flux_vector[iDim]; } + +}; + +/*! + * \class CAvgGrad_Flow + * \brief Class for computing viscous term using the average of gradients. + * \ingroup ViscDiscr + * \author A. Bueno, and F. Palacios + */ +class CAvgGrad_Flow final : public CAvgGrad_Base { +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] val_correct_grad - Apply a correction to the gradient + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_Flow(unsigned short val_nDim, unsigned short val_nVar, + bool val_correct_grad, const CConfig* config); + + /*! + * \brief Compute the viscous flow residual using an average of gradients. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + + /*! + * \brief Compute the heat flux due to molecular and turbulent diffusivity + * \param[in] val_gradprimvar - Gradient of the primitive variables. + * \param[in] val_laminar_viscosity - Laminar viscosity. + * \param[in] val_eddy_viscosity - Eddy viscosity. + */ + void SetHeatFluxVector(const su2double* const *val_gradprimvar, + su2double val_laminar_viscosity, + su2double val_eddy_viscosity); + + /*! + * \brief Compute the Jacobian of the heat flux vector + * + * This Jacobian is projected onto the normal vector, so it is of + * dimension nVar. + * + * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. + * \param[in] val_gradprimvar - Mean value of the gradient of the primitive variables. + * \param[in] val_laminar_viscosity - Value of the laminar viscosity. + * \param[in] val_eddy_viscosity - Value of the eddy viscosity. + * \param[in] val_dist_ij - Distance between the points. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + */ + void SetHeatFluxJacobian(const su2double *val_Mean_PrimVar, + su2double val_laminar_viscosity, + su2double val_eddy_viscosity, + su2double val_dist_ij, + const su2double *val_normal); +}; + +/*! + * \class CAvgGradInc_Flow + * \brief Class for computing viscous term using an average of gradients. + * \ingroup ViscDiscr + * \author A. Bueno, F. Palacios, T. Economon + */ +class CAvgGradInc_Flow final : public CAvgGrad_Base { +private: + su2double Mean_Thermal_Conductivity; /*!< \brief Mean value of the effective thermal conductivity. */ + bool energy; /*!< \brief computation with the energy equation. */ + + /*! + * \brief Compute the projection of the viscous fluxes into a direction + * + * The viscous + turbulent stress tensor must be calculated before calling + * this function. + * + * \param[in] val_gradprimvar - Gradient of the primitive variables. + * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. + * \param[in] val_thermal_conductivity - Thermal conductivity. + */ + void GetViscousIncProjFlux(const su2double* const *val_gradprimvar, + const su2double *val_normal, + su2double val_thermal_conductivity); + + /*! + * \brief Compute the projection of the viscous Jacobian matrices. + * + * The Jacobian of the stress tensor must be calculated before calling + * this function. + * + * \param[in] val_dS - Area of the face between two nodes. + * \param[out] val_Proj_Jac_Tensor_i - Pointer to the projected viscous Jacobian at point i. + * \param[out] val_Proj_Jac_Tensor_j - Pointer to the projected viscous Jacobian at point j. + */ + void GetViscousIncProjJacs(su2double val_dS, + su2double **val_Proj_Jac_Tensor_i, + su2double **val_Proj_Jac_Tensor_j); + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] val_correct_grad - Apply a correction to the gradient + * \param[in] config - Definition of the particular problem. + */ + CAvgGradInc_Flow(unsigned short val_nDim, unsigned short val_nVar, + bool val_correct_grad, const CConfig* config); + + /*! + * \brief Compute the viscous flow residual using an average of gradients. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + + +/*! + * \class CGeneralAvgGrad_Flow + * \brief Class for computing viscous term using the average of gradients. + * \ingroup ViscDiscr + * \author M.Pini, S. Vitale + */ +class CGeneralAvgGrad_Flow final : public CAvgGrad_Base { +private: + su2double Mean_SecVar[2], /*!< \brief Mean secondary variables. */ + Mean_Thermal_Conductivity, /*!< \brief Mean value of the thermal conductivity. */ + Mean_Cp; /*!< \brief Mean value of the Cp. */ + + /*! + * \brief Compute the heat flux due to molecular and turbulent diffusivity + * \param[in] val_gradprimvar - Gradient of the primitive variables. + * \param[in] val_laminar_viscosity - Laminar viscosity. + * \param[in] val_eddy_viscosity - Eddy viscosity. + * \param[in] val_thermal_conductivity - Thermal Conductivity. + * \param[in] val_heat_capacity_cp - Heat Capacity at constant pressure. + */ + void SetHeatFluxVector(const su2double* const *val_gradprimvar, + su2double val_laminar_viscosity, + su2double val_eddy_viscosity, + su2double val_thermal_conductivity, + su2double val_heat_capacity_cp); + + /*! + * \brief Compute the Jacobian of the heat flux vector + * + * This Jacobian is projected onto the normal vector, so it is of + * dimension nVar. + * + * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. + * \param[in] val_Mean_SecVar - Mean value of the secondary variables. + * \param[in] val_eddy_viscosity - Value of the eddy viscosity. + * \param[in] val_thermal_conductivity - Value of the thermal conductivity. + * \param[in] val_heat_capacity_cp - Value of the specific heat at constant pressure. + * \param[in] val_dist_ij - Distance between the points. + */ + void SetHeatFluxJacobian(const su2double *val_Mean_PrimVar, + const su2double *val_Mean_SecVar, + su2double val_eddy_viscosity, + su2double val_thermal_conductivity, + su2double val_heat_capacity_cp, + su2double val_dist_ij); + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] val_correct_grad - Apply a correction to the gradient + * \param[in] config - Definition of the particular problem. + */ + CGeneralAvgGrad_Flow(unsigned short val_nDim, unsigned short val_nVar, bool val_correct_grad, const CConfig* config); + + /*! + * \brief Compute the viscous flow residual using an average of gradients. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; diff --git a/SU2_CFD/include/numerics/flow/flow_sources.hpp b/SU2_CFD/include/numerics/flow/flow_sources.hpp new file mode 100644 index 000000000000..1872a9c60325 --- /dev/null +++ b/SU2_CFD/include/numerics/flow/flow_sources.hpp @@ -0,0 +1,295 @@ +/*! + * \file flow_sources.hpp + * \brief Delarations of numerics classes for source-term integration. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../CNumerics.hpp" + +/*! + * \class CSourceBase_Flow + * \brief Intermediate source term class to allocate the internally + * stored residual and Jacobian. Not for stand alone use, + * just a helper to build more complicated classes. + * \ingroup SourceDiscr + */ +class CSourceBase_Flow : public CNumerics { +protected: + su2double* residual = nullptr; + su2double** jacobian = nullptr; + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceBase_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +public: + /*! + * \brief Destructor of the class. + */ + virtual ~CSourceBase_Flow(); + +}; + +/*! + * \class CSourceAxisymmetric_Flow + * \brief Class for source term for solving axisymmetric problems. + * \ingroup SourceDiscr + * \author F. Palacios + */ +class CSourceAxisymmetric_Flow final : public CSourceBase_Flow { +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceAxisymmetric_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual of the rotational frame source term. + * \param[in] config - Definition of the particular problem. + * \return Lightweight const-view of residual and Jacobian. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourceIncAxisymmetric_Flow + * \brief Class for source term for solving incompressible axisymmetric problems. + * \ingroup SourceDiscr + * \author T. Economon + */ +class CSourceIncAxisymmetric_Flow final : public CSourceBase_Flow { + bool implicit, /*!< \brief Implicit calculation. */ + viscous, /*!< \brief Viscous incompressible flows. */ + energy; /*!< \brief computation with the energy equation. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceIncAxisymmetric_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual of the rotational frame source term. + * \param[in] config - Definition of the particular problem. + * \return Lightweight const-view of residual and Jacobian. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourceBodyForce + * \brief Class for the source term integration of a body force. + * \ingroup SourceDiscr + * \author T. Economon + */ +class CSourceBodyForce final : public CSourceBase_Flow { + su2double Body_Force_Vector[3]; + +public: + /*! + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceBodyForce(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Source term integration for a body force. + * \param[in] config - Definition of the particular problem. + * \return Lightweight const-view of residual and Jacobian. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourceIncBodyForce + * \brief Class for the source term integration of a body force in the incompressible solver. + * \ingroup SourceDiscr + * \author T. Economon + * \version 7.0.1 "Blackbird" + */ +class CSourceIncBodyForce final : public CSourceBase_Flow { + su2double Body_Force_Vector[3]; + +public: + /*! + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceIncBodyForce(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Source term integration for a body force. + * \param[in] config - Definition of the particular problem. + * \return Lightweight const-view of residual and Jacobian. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourceBoussinesq + * \brief Class for the source term integration of the Boussinesq approximation for incompressible flow. + * \ingroup SourceDiscr + * \author T. Economon + * \version 7.0.1 "Blackbird" + */ +class CSourceBoussinesq final : public CSourceBase_Flow { + su2double Gravity_Vector[3]; + +public: + /*! + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceBoussinesq(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Source term integration for the Boussinesq approximation. + * \param[in] config - Definition of the particular problem. + * \return Lightweight const-view of residual and Jacobian. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourceGravity + * \brief Class for the source term integration of the gravity force. + * \ingroup SourceDiscr + * \author F. Palacios + */ +class CSourceGravity final : public CSourceBase_Flow { +public: + /*! + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceGravity(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Source term integration for the poissonal potential. + * \param[in] config - Definition of the particular problem. + * \return Lightweight const-view of residual and Jacobian. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourceRotatingFrame_Flow + * \brief Class for a rotating frame source term. + * \ingroup SourceDiscr + * \author F. Palacios, T. Economon. + */ +class CSourceRotatingFrame_Flow final : public CSourceBase_Flow { +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceRotatingFrame_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual of the rotational frame source term. + * \param[in] config - Definition of the particular problem. + * \return Lightweight const-view of residual and Jacobian. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourceIncRotatingFrame_Flow + * \brief Class for a rotating frame source term. + * \ingroup SourceDiscr + */ +class CSourceIncRotatingFrame_Flow final : public CSourceBase_Flow { + +private: + su2double Omega[3]; /*!< \brief Angular velocity */ + bool implicit; /*!< \brief Implicit calculation. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceIncRotatingFrame_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual of the rotational frame source term. + * \param[in] config - Definition of the particular problem. + * \return Lightweight const-view of residual and Jacobian. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourceWindGust + * \brief Class for a source term due to a wind gust. + * \ingroup SourceDiscr + * \author S. Padrón + */ +class CSourceWindGust final : public CSourceBase_Flow { +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceWindGust(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual of the wind gust source term. + * \param[in] config - Definition of the particular problem. + * \return Lightweight const-view of residual and Jacobian. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; diff --git a/SU2_CFD/include/numerics/heat.hpp b/SU2_CFD/include/numerics/heat.hpp new file mode 100644 index 000000000000..88bf8ed3641f --- /dev/null +++ b/SU2_CFD/include/numerics/heat.hpp @@ -0,0 +1,196 @@ +/*! + * \file heat.hpp + * \brief Delarations of numerics classes for heat transfer problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "CNumerics.hpp" + +/*! + * \class CCentSca_Heat + * \brief Class for scalar centered scheme. + * \ingroup ConvDiscr + * \author O. Burghardt + * \version 7.0.1 "Blackbird" + */ +class CCentSca_Heat : public CNumerics { + +private: + unsigned short iDim; /*!< \brief Iteration on dimension and variables. */ + su2double *Diff_Lapl, /*!< \brief Diference of conservative variables and undivided laplacians. */ + *MeanVelocity, ProjVelocity, + ProjVelocity_i, ProjVelocity_j, /*!< \brief Mean and projected velocities. */ + Param_Kappa_4, /*!< \brief Artificial dissipation parameters. */ + Local_Lambda_i, Local_Lambda_j, + MeanLambda, /*!< \brief Local eingenvalues. */ + cte_0, cte_1; /*!< \brief Artificial dissipation values. */ + bool implicit, /*!< \brief Implicit calculation. */ + dynamic_grid; /*!< \brief Modification for grid movement. */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CCentSca_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CCentSca_Heat(void); + + /*! + * \brief Compute the flow residual using a JST method. + * \param[out] val_resconv - Pointer to the convective residual. + * \param[out] val_resvisc - Pointer to the artificial viscosity residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, + CConfig *config); +}; + +/*! + * \class CUpwSca_Heat + * \brief Class for doing a scalar upwind solver for the heat convection equation. + * \ingroup ConvDiscr + * \author O. Burghardt. + * \version 7.0.1 "Blackbird" + */ +class CUpwSca_Heat : public CNumerics { +private: + su2double *Velocity_i, *Velocity_j; + bool implicit, dynamic_grid; + su2double q_ij, a0, a1; + unsigned short iDim; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwSca_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwSca_Heat(void); + + /*! + * \brief Compute the scalar upwind flux between two nodes i and j. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); +}; + +/*! + * \class CAvgGrad_Heat + * \brief Class for computing viscous term using average of gradients without correction (heat equation). + * \ingroup ViscDiscr + * \author O. Burghardt. + * \version 7.0.1 "Blackbird" + */ +class CAvgGrad_Heat : public CNumerics { +private: + su2double **Mean_GradHeatVar; + su2double *Proj_Mean_GradHeatVar_Normal, *Proj_Mean_GradHeatVar_Corrected; + su2double *Edge_Vector; + bool implicit; + su2double dist_ij_2, proj_vector_ij, Thermal_Diffusivity_Mean; + unsigned short iVar, iDim; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGrad_Heat(void); + + /*! + * \brief Compute the viscous heat residual using an average of gradients with correction. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config); +}; + +/*! + * \class CAvgGradCorrected_Heat + * \brief Class for computing viscous term using average of gradients with correction (heat equation). + * \ingroup ViscDiscr + * \author O. Burghardt. + * \version 7.0.1 "Blackbird" + */ +class CAvgGradCorrected_Heat : public CNumerics { +private: + su2double **Mean_GradHeatVar; + su2double *Proj_Mean_GradHeatVar_Kappa, *Proj_Mean_GradHeatVar_Edge, *Proj_Mean_GradHeatVar_Corrected; + su2double *Edge_Vector; + bool implicit; + su2double dist_ij_2, proj_vector_ij, Thermal_Diffusivity_Mean; + unsigned short iVar, iDim; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CAvgGradCorrected_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGradCorrected_Heat(void); + + /*! + * \brief Compute the viscous heat residual using an average of gradients with correction. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config); +}; diff --git a/SU2_CFD/include/numerics/template.hpp b/SU2_CFD/include/numerics/template.hpp new file mode 100644 index 000000000000..c9bdd3659cd3 --- /dev/null +++ b/SU2_CFD/include/numerics/template.hpp @@ -0,0 +1,138 @@ +/*! + * \file template.hpp + * \brief Declarations of template (empty) numerics classes, these give + * an idea of the methods that need to be defined to implement + * new schemes in SU2, in practice you should look for a similar + * scheme and try to re-use functionality (not by copy-paste). + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "CNumerics.hpp" + +/*! + * \class CConvectiveTemplate + * \brief Class for setting up new method for spatial discretization of convective terms in flow equations. + * \ingroup ConvDiscr + * \author A. Lonkar + */ +class CConvective_Template : public CNumerics { +private: + + /* define private variables here */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CConvective_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CConvective_Template(void); + + /*! + * \brief Compute the Roe's flux between two nodes i and j. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); +}; + +/*! + * \class CViscous_Template + * \brief Class for computing viscous term using average of gradients. + * \ingroup ViscDiscr + * \author F. Palacios + */ +class CViscous_Template : public CNumerics { +private: + + /* define private variables here */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimension of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CViscous_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CViscous_Template(void); + + /*! + * \brief Compute the viscous flow residual using an average of gradients. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); +}; + +/*! + * \class CSource_Template + * \brief Dummy class. + * \ingroup SourceDiscr + * \author A. Lonkar. + */ +class CSource_Template : public CNumerics { +private: + + /* define private variables here */ + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Name of the input config file + * + */ + CSource_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Residual for source term integration. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CSource_Template(void); +}; diff --git a/SU2_CFD/include/numerics/transition.hpp b/SU2_CFD/include/numerics/transition.hpp new file mode 100644 index 000000000000..2806fdd07c63 --- /dev/null +++ b/SU2_CFD/include/numerics/transition.hpp @@ -0,0 +1,252 @@ +/*! + * \file transition.hpp + * \brief Delarations of numerics classes for transition problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "CNumerics.hpp" + +/*! + * \class CUpwLin_TransLM + * \brief Class for performing a linear upwind solver for the Spalart-Allmaras turbulence model equations with transition + * \ingroup ConvDiscr + * \author A. Aranake + */ +class CUpwLin_TransLM : public CNumerics { +private: + su2double *Velocity_i; + su2double *Velocity_j; + bool implicit, incompressible; + su2double Density_i, Density_j, q_ij, a0, a1; + unsigned short iDim; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwLin_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwLin_TransLM(void); + + /*! + * \brief Compute the upwind flux between two nodes i and j. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual (su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); +}; + +/*! + * \class CUpwSca_TransLM + * \brief Class for doing a scalar upwind solver for the Spalart-Allmaras turbulence model equations with transition. + * \ingroup ConvDiscr + * \author A. Aranake. + */ +class CUpwSca_TransLM : public CNumerics { +private: + su2double *Velocity_i, *Velocity_j; + bool implicit; + su2double q_ij, a0, a1; + unsigned short iDim; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwSca_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwSca_TransLM(void); + + /*! + * \brief Compute the scalar upwind flux between two nodes i and j. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); +}; + +/*! + * \class CAvgGrad_TransLM + * \brief Class for computing viscous term using average of gradients (Spalart-Allmaras Turbulence model). + * \ingroup ViscDiscr + * \author A. Bueno. + */ +class CAvgGrad_TransLM : public CNumerics { +private: + su2double **Mean_GradTransVar; + su2double *Proj_Mean_GradTransVar_Kappa, *Proj_Mean_GradTransVar_Edge; + su2double *Edge_Vector; + bool implicit, incompressible; + su2double sigma; + //su2double dist_ij_2; + //su2double proj_vector_ij; + //unsigned short iVar, iDim; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGrad_TransLM(void); + + /*! + * \brief Compute the viscous turbulence terms residual using an average of gradients. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config); +}; + +/*! + * \class CAvgGradCorrected_TransLM + * \brief Class for computing viscous term using average of gradients with correction (Spalart-Allmaras turbulence model). + * \ingroup ViscDiscr + * \author A. Bueno. + */ +class CAvgGradCorrected_TransLM : public CNumerics { +private: + su2double **Mean_GradTurbVar; + su2double *Proj_Mean_GradTurbVar_Kappa, *Proj_Mean_GradTurbVar_Edge, *Proj_Mean_GradTurbVar_Corrected; + su2double *Edge_Vector; + bool implicit, incompressible; + su2double sigma; + +public: + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CAvgGradCorrected_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGradCorrected_TransLM(void); + + /*! + * \brief Compute the viscous turbulent residual using an average of gradients with correction. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config); +}; + +/*! + * \class CSourcePieceWise_TransLM + * \brief Class for integrating the source terms of the Spalart-Allmaras turbulence model equation. + * \ingroup SourceDiscr + * \author A. Bueno. + */ +class CSourcePieceWise_TransLM : public CNumerics { +private: + + /*-- SA model constants --*/ + su2double cv1_3; + su2double k2; + su2double cb1; + su2double cw2; + su2double cw3_6; + su2double sigma; + su2double cb2; + su2double cw1; + + /*-- gamma-theta model constants --*/ + su2double c_e1; + su2double c_a1; + su2double c_e2; + su2double c_a2; + su2double sigmaf; + su2double s1; + su2double c_theta; + su2double sigmat; + + /*-- Correlation constants --*/ + su2double flen_global; + su2double alpha_global; + su2double Vorticity; + + bool implicit; + +public: + bool debugme; // For debugging only, remove this. -AA + + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); + + /*! + * \brief Destructor of the class. + */ + ~CSourcePieceWise_TransLM(void); + + /*! + * \brief Residual for source term integration. + * \param[out] val_residual - Pointer to the total residual. + * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). + * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). + * \param[in] config - Definition of the particular problem. + */ + void ComputeResidual_TransLM(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config, su2double &gamma_sep); + + void CSourcePieceWise_TransLM__ComputeResidual_TransLM_d(su2double *TransVar_i, su2double *TransVar_id, su2double *val_residual, su2double *val_residuald, CConfig *config); +}; diff --git a/SU2_CFD/include/numerics/turbulent/turb_convection.hpp b/SU2_CFD/include/numerics/turbulent/turb_convection.hpp new file mode 100644 index 000000000000..a63f16f890ad --- /dev/null +++ b/SU2_CFD/include/numerics/turbulent/turb_convection.hpp @@ -0,0 +1,152 @@ +/*! + * \file turb_convection.hpp + * \brief Delarations of numerics classes for discretization of + * convective fluxes in turbulence problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../CNumerics.hpp" + +/*! + * \class CUpwScalar + * \brief Template class for scalar upwind fluxes between nodes i and j. + * \details This class serves as a template for the scalar upwinding residual + * classes. The general structure of a scalar upwinding calculation is the + * same for many different models, which leads to a lot of repeated code. + * By using the template design pattern, these sections of repeated code are + * moved to this shared base class, and the specifics of each model + * are implemented by derived classes. In order to add a new residual + * calculation for a convection residual, extend this class and implement + * the pure virtual functions with model-specific behavior. + * \ingroup ConvDiscr + * \author C. Pederson, A. Bueno., and A. Campos. + */ +class CUpwScalar : public CNumerics { +protected: + su2double + q_ij = 0.0, /*!< \brief Projected velocity at the face. */ + a0 = 0.0, /*!< \brief The maximum of the face-normal velocity and 0 */ + a1 = 0.0, /*!< \brief The minimum of the face-normal velocity and 0 */ + *Flux = nullptr, /*!< \brief Final result, diffusive flux/residual. */ + **Jacobian_i = nullptr, /*!< \brief Flux Jacobian w.r.t. node i. */ + **Jacobian_j = nullptr; /*!< \brief Flux Jacobian w.r.t. node j. */ + + const bool implicit = false, incompressible = false, dynamic_grid = false; + + /*! + * \brief A pure virtual function; Adds any extra variables to AD + */ + virtual void ExtraADPreaccIn() = 0; + + /*! + * \brief Model-specific steps in the ComputeResidual method, derived classes + * compute the Flux and its Jacobians via this method. + * \param[in] config - Definition of the particular problem. + */ + virtual void FinishResidualCalc(const CConfig* config) = 0; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwScalar(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CUpwScalar(void); + + /*! + * \brief Compute the scalar upwind flux between two nodes i and j. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config); + +}; + +/*! + * \class CUpwSca_TurbSA + * \brief Class for doing a scalar upwind solver for the Spalar-Allmaras turbulence model equations. + * \ingroup ConvDiscr + * \author A. Bueno. + */ +class CUpwSca_TurbSA final : public CUpwScalar { +private: + /*! + * \brief Adds any extra variables to AD + */ + void ExtraADPreaccIn() override; + + /*! + * \brief SA specific steps in the ComputeResidual method + * \param[in] config - Definition of the particular problem. + */ + void FinishResidualCalc(const CConfig* config) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwSca_TurbSA(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +}; + +/*! + * \class CUpwSca_TurbSST + * \brief Class for doing a scalar upwind solver for the Menter SST turbulence model equations. + * \ingroup ConvDiscr + * \author A. Campos. + */ +class CUpwSca_TurbSST final : public CUpwScalar { +private: + /*! + * \brief Adds any extra variables to AD + */ + void ExtraADPreaccIn() override; + + /*! + * \brief SST specific steps in the ComputeResidual method + * \param[in] config - Definition of the particular problem. + */ + void FinishResidualCalc(const CConfig* config) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CUpwSca_TurbSST(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + +}; diff --git a/SU2_CFD/include/numerics/turbulent/turb_diffusion.hpp b/SU2_CFD/include/numerics/turbulent/turb_diffusion.hpp new file mode 100644 index 000000000000..00b1738b4763 --- /dev/null +++ b/SU2_CFD/include/numerics/turbulent/turb_diffusion.hpp @@ -0,0 +1,212 @@ +/*! + * \file turb_diffusion.hpp + * \brief Declarations of numerics classes for discretization of + * viscous fluxes in turbulence problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../CNumerics.hpp" + +/*! + * \class CAvgGrad_Scalar + * \brief Template class for computing viscous residual of scalar values + * \details This class serves as a template for the scalar viscous residual + * classes. The general structure of a viscous residual calculation is the + * same for many different models, which leads to a lot of repeated code. + * By using the template design pattern, these sections of repeated code are + * moved to a shared base class, and the specifics of each model + * are implemented by derived classes. In order to add a new residual + * calculation for a viscous residual, extend this class and implement + * the pure virtual functions with model-specific behavior. + * \ingroup ViscDiscr + * \author C. Pederson, A. Bueno, and F. Palacios + */ +class CAvgGrad_Scalar : public CNumerics { +protected: + su2double + Edge_Vector[MAXNDIM] = {0.0}, /*!< \brief Vector from node i to node j. */ + *Proj_Mean_GradTurbVar_Normal = nullptr, /*!< \brief Mean_gradTurbVar DOT normal. */ + *Proj_Mean_GradTurbVar_Edge = nullptr, /*!< \brief Mean_gradTurbVar DOT Edge_Vector. */ + *Proj_Mean_GradTurbVar = nullptr, /*!< \brief Mean_gradTurbVar DOT normal, corrected if required. */ + dist_ij_2 = 0.0, /*!< \brief |Edge_Vector|^2 */ + proj_vector_ij = 0.0, /*!< \brief (Edge_Vector DOT normal)/|Edge_Vector|^2 */ + *Flux = nullptr, /*!< \brief Final result, diffusive flux/residual. */ + **Jacobian_i = nullptr, /*!< \brief Flux Jacobian w.r.t. node i. */ + **Jacobian_j = nullptr; /*!< \brief Flux Jacobian w.r.t. node j. */ + + const bool correct_gradient = false, implicit = false, incompressible = false; + + /*! + * \brief A pure virtual function; Adds any extra variables to AD + */ + virtual void ExtraADPreaccIn() = 0; + + /*! + * \brief Model-specific steps in the ComputeResidual method, derived classes + * should compute the Flux and Jacobians (i/j) inside this method. + * \param[in] config - Definition of the particular problem. + */ + virtual void FinishResidualCalc(const CConfig* config) = 0; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] correct_gradient - Whether to correct gradient for skewness. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_Scalar(unsigned short val_nDim, unsigned short val_nVar, + bool correct_gradient, const CConfig* config); + + /*! + * \brief Destructor of the class. + */ + ~CAvgGrad_Scalar(void); + + /*! + * \brief Compute the viscous residual using an average of gradients without correction. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config); + +}; + +/*! + * \class CAvgGrad_TurbSA + * \brief Class for computing viscous term using average of gradients (Spalart-Allmaras Turbulence model). + * \ingroup ViscDiscr + * \author A. Bueno. + */ +class CAvgGrad_TurbSA final : public CAvgGrad_Scalar { +private: + const su2double sigma = 2.0/3.0; + + /*! + * \brief Adds any extra variables to AD + */ + void ExtraADPreaccIn(void) override; + + /*! + * \brief SA specific steps in the ComputeResidual method + * \param[in] config - Definition of the particular problem. + */ + void FinishResidualCalc(const CConfig* config) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] correct_grad - Whether to correct gradient for skewness. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_TurbSA(unsigned short val_nDim, unsigned short val_nVar, + bool correct_grad, const CConfig* config); +}; + +/*! + * \class CAvgGrad_TurbSA_Neg + * \brief Class for computing viscous term using average of gradients (Spalart-Allmaras Turbulence model). + * \ingroup ViscDiscr + * \author F. Palacios + */ +class CAvgGrad_TurbSA_Neg final : public CAvgGrad_Scalar { +private: + const su2double sigma = 2.0/3.0; + const su2double cn1 = 16.0; + + /*! + * \brief Adds any extra variables to AD + */ + void ExtraADPreaccIn(void) override; + + /*! + * \brief SA specific steps in the ComputeResidual method + * \param[in] config - Definition of the particular problem. + */ + void FinishResidualCalc(const CConfig* config) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] correct_grad - Whether to correct gradient for skewness. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_TurbSA_Neg(unsigned short val_nDim, unsigned short val_nVar, + bool correct_grad, const CConfig* config); +}; + +/*! + * \class CAvgGrad_TurbSST + * \brief Class for computing viscous term using average of gradient with correction (Menter SST turbulence model). + * \ingroup ViscDiscr + * \author A. Bueno. + */ +class CAvgGrad_TurbSST final : public CAvgGrad_Scalar { +private: + const su2double + sigma_k1 = 0.0, /*!< \brief Constants for the viscous terms, k-w (1), k-eps (2)*/ + sigma_k2 = 0.0, + sigma_om1 = 0.0, + sigma_om2 = 0.0; + + su2double F1_i, F1_j; /*!< \brief Menter's first blending function */ + + /*! + * \brief Adds any extra variables to AD + */ + void ExtraADPreaccIn(void) override; + + /*! + * \brief SST specific steps in the ComputeResidual method + * \param[in] config - Definition of the particular problem. + */ + void FinishResidualCalc(const CConfig* config) override; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] constants - Constants of the model. + * \param[in] correct_grad - Whether to correct gradient for skewness. + * \param[in] config - Definition of the particular problem. + */ + CAvgGrad_TurbSST(unsigned short val_nDim, unsigned short val_nVar, + const su2double* constants, bool correct_grad, const CConfig* config); + + /*! + * \brief Sets value of first blending function. + */ + void SetF1blending(su2double val_F1_i, su2double val_F1_j) { + F1_i = val_F1_i; F1_j = val_F1_j; + } + +}; diff --git a/SU2_CFD/include/numerics/turbulent/turb_sources.hpp b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp new file mode 100644 index 000000000000..9ec52d2f2ce5 --- /dev/null +++ b/SU2_CFD/include/numerics/turbulent/turb_sources.hpp @@ -0,0 +1,394 @@ +/*! + * \file turb_sources.hpp + * \brief Delarations of numerics classes for integration of source + * terms in turbulence problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, 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 "../CNumerics.hpp" + +/*! + * \class CSourcePieceWise_TurbSA + * \brief Class for integrating the source terms of the Spalart-Allmaras turbulence model equation. + * \ingroup SourceDiscr + * \author A. Bueno. + */ +class CSourceBase_TurbSA : public CNumerics { +protected: + su2double cv1_3; + su2double k2; + su2double cb1; + su2double cw2; + su2double ct3; + su2double ct4; + su2double cw3_6; + su2double cb2_sigma; + su2double sigma; + su2double cb2; + su2double cw1; + + su2double gamma_BC; + su2double intermittency; + su2double Production, Destruction, CrossProduction; + + su2double Residual, *Jacobian_i; +private: + su2double Jacobian_Buffer; /// Static storage for the Jacobian (which needs to be pointer for return type). + +protected: + const bool incompressible = false, rotating_frame = false; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourceBase_TurbSA(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual for source term integration. + * \param[in] intermittency_in - Value of the intermittency. + */ + inline void SetIntermittency(su2double intermittency_in) final { intermittency = intermittency_in; } + + /*! + * \brief Residual for source term integration. + * \param[in] val_production - Value of the Production. + */ + inline void SetProduction(su2double val_production) final { Production = val_production; } + + /*! + * \brief Residual for source term integration. + * \param[in] val_destruction - Value of the Destruction. + */ + inline void SetDestruction(su2double val_destruction) final { Destruction = val_destruction; } + + /*! + * \brief Residual for source term integration. + * \param[in] val_crossproduction - Value of the CrossProduction. + */ + inline void SetCrossProduction(su2double val_crossproduction) final { CrossProduction = val_crossproduction; } + + /*! + * \brief ______________. + */ + inline su2double GetProduction(void) const final { return Production; } + + /*! + * \brief Get the intermittency for the BC trans. model. + * \return Value of the intermittency. + */ + inline su2double GetGammaBC(void) const final { return gamma_BC; } + + /*! + * \brief ______________. + */ + inline su2double GetDestruction(void) const final { return Destruction; } + + /*! + * \brief ______________. + */ + inline su2double GetCrossProduction(void) const final { return CrossProduction; } +}; + + +/*! + * \class CSourcePieceWise_TurbSA + * \brief Class for integrating the source terms of the Spalart-Allmaras turbulence model equation. + * \ingroup SourceDiscr + * \author A. Bueno. + */ +class CSourcePieceWise_TurbSA final : public CSourceBase_TurbSA { +private: + su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; + su2double r, g, g_6, glim, fw; + su2double norm2_Grad; + su2double dfv1, dfv2, dShat; + su2double dr, dg, dfw; + unsigned short iDim; + bool transition; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_TurbSA(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual for source term integration. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourcePieceWise_TurbSA_COMP + * \brief Class for integrating the source terms of the Spalart-Allmaras CC modification turbulence model equation. + * \ingroup SourceDiscr + * \author E.Molina, A. Bueno. + * \version 7.0.1 "Blackbird" + */ +class CSourcePieceWise_TurbSA_COMP final : public CSourceBase_TurbSA { +private: + su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; + su2double r, g, g_6, glim, fw; + su2double norm2_Grad; + su2double dfv1, dfv2, dShat; + su2double dr, dg, dfw; + su2double aux_cc, CompCorrection, c5; + unsigned short iDim, jDim; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_TurbSA_COMP(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual for source term integration. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourcePieceWise_TurbSA_E + * \brief Class for integrating the source terms of the Spalart-Allmaras Edwards modification turbulence model equation. + * \ingroup SourceDiscr + * \author E.Molina, A. Bueno. + * \version 7.0.1 "Blackbird" + */ +class CSourcePieceWise_TurbSA_E final : public CSourceBase_TurbSA { +private: + su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; + su2double r, g, g_6, glim, fw; + su2double norm2_Grad; + su2double dfv1, dfv2, dShat; + su2double dr, dg, dfw; + su2double Sbar; + unsigned short iDim, jDim; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_TurbSA_E(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual for source term integration. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; +}; + +/*! + * \class CSourcePieceWise_TurbSA_E_COMP + * \brief Class for integrating the source terms of the Spalart-Allmaras Edwards modification with CC turbulence model equation. + * \ingroup SourceDiscr + * \author E.Molina, A. Bueno. + * \version 7.0.1 "Blackbird" + */ +class CSourcePieceWise_TurbSA_E_COMP : public CSourceBase_TurbSA { +private: + su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; + su2double r, g, g_6, glim, fw; + su2double norm2_Grad; + su2double dfv1, dfv2, dShat; + su2double dr, dg, dfw; + su2double Sbar; + su2double aux_cc, CompCorrection, c5; + unsigned short iDim, jDim; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_TurbSA_E_COMP(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual for source term integration. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; +}; + +/*! + * \class CSourcePieceWise_TurbSA_Neg + * \brief Class for integrating the source terms of the Spalart-Allmaras turbulence model equation. + * \ingroup SourceDiscr + * \author F. Palacios + */ +class CSourcePieceWise_TurbSA_Neg : public CSourceBase_TurbSA { +private: + su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; + su2double r, g, g_6, glim, fw; + su2double norm2_Grad; + su2double dfv1, dfv2, dShat; + su2double dr, dg, dfw; + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_TurbSA_Neg(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config); + + /*! + * \brief Residual for source term integration. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; + +/*! + * \class CSourcePieceWise_TurbSST + * \brief Class for integrating the source terms of the Menter SST turbulence model equations. + * \ingroup SourceDiscr + * \author A. Campos. + */ +class CSourcePieceWise_TurbSST final : public CNumerics { +private: + su2double F1_i, + F1_j, + F2_i, + F2_j; + + su2double alfa_1, + alfa_2, + beta_1, + beta_2, + sigma_omega_1, + sigma_omega_2, + beta_star, + a1; + + su2double CDkw_i, CDkw_j; + + su2double kAmb, omegaAmb; + + su2double Residual[2], + *Jacobian_i[2] = {nullptr}, + Jacobian_Buffer[4] = {0.0}; /// Static storage for the Jacobian (which needs to be pointer for return type). + + bool incompressible; + bool sustaining_terms; + + /*! + * \brief Initialize the Reynolds Stress Matrix + * \param[in] turb_ke turbulent kinetic energy of node + */ + void SetReynoldsStressMatrix(su2double turb_ke); + + /*! + * \brief Perturb the Reynolds stress tensor based on parameters + * \param[in] turb_ke: turbulent kinetic energy of the noce + * \param[in] config: config file + */ + void SetPerturbedRSM(su2double turb_ke, const CConfig* config); + /*! + * \brief A virtual member. Get strain magnitude based on perturbed reynolds stress matrix + * \param[in] turb_ke: turbulent kinetic energy of the node + */ + void SetPerturbedStrainMag(su2double turb_ke); + + /*! + * \brief Get the mean rate of strain matrix based on velocity gradients + * \param[in] S_ij + */ + void GetMeanRateOfStrainMatrix(su2double **S_ij); + +public: + /*! + * \brief Constructor of the class. + * \param[in] val_nDim - Number of dimensions of the problem. + * \param[in] val_nVar - Number of variables of the problem. + * \param[in] config - Definition of the particular problem. + */ + CSourcePieceWise_TurbSST(unsigned short val_nDim, unsigned short val_nVar, const su2double* constants, + su2double val_kine_Inf, su2double val_omega_Inf, const CConfig* config); + + /*! + * \brief Set the value of the first blending function. + * \param[in] val_F1_i - Value of the first blending function at point i. + * \param[in] val_F1_j - Value of the first blending function at point j. + */ + inline void SetF1blending(su2double val_F1_i, su2double val_F1_j) override { + F1_i = val_F1_i; + F1_j = val_F1_j; + } + + /*! + * \brief Set the value of the second blending function. + * \param[in] val_F2_i - Value of the second blending function at point i. + * \param[in] val_F2_j - Value of the second blending function at point j. + */ + inline void SetF2blending(su2double val_F2_i, su2double val_F2_j) override { + F2_i = val_F2_i; + F2_j = val_F2_j; + } + + /*! + * \brief Set the value of the cross diffusion for the SST model. + * \param[in] val_CDkw_i - Value of the cross diffusion at point i. + * \param[in] val_CDkw_j - Value of the cross diffusion at point j. + */ + inline void SetCrossDiff(su2double val_CDkw_i, su2double val_CDkw_j) override { + CDkw_i = val_CDkw_i; + CDkw_j = val_CDkw_j; + } + + /*! + * \brief Residual for source term integration. + * \param[in] config - Definition of the particular problem. + * \return A lightweight const-view (read-only) of the residual/flux and Jacobians. + */ + ResidualType<> ComputeResidual(const CConfig* config) override; + +}; diff --git a/SU2_CFD/include/numerics_structure.hpp b/SU2_CFD/include/numerics_structure.hpp deleted file mode 100644 index 3895babb54f1..000000000000 --- a/SU2_CFD/include/numerics_structure.hpp +++ /dev/null @@ -1,5381 +0,0 @@ -/*! - * \file numerics_structure.hpp - * \brief Headers of the main subroutines for the dumerical definition of the problem. - * The subroutines and functions are in the numerics_structure.cpp, - * numerics_convective.cpp, numerics_viscous.cpp, and - * numerics_source.cpp files. - * \author F. Palacios, T. Economon - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, 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/mpi_structure.hpp" - -#include -#include -#include -#include - -#include "../../Common/include/CConfig.hpp" -#include "../../Common/include/geometry/elements/CElement.hpp" -#include "fluid_model.hpp" - -using namespace std; - -/*! - * \class CNumerics - * \brief Class for defining the numerical methods. - * \author F. Palacios, T. Economon - */ -class CNumerics { -protected: - unsigned short nDim, nVar; /*!< \brief Number of dimensions and variables. */ - su2double Gamma; /*!< \brief Fluid's Gamma constant (ratio of specific heats). */ - su2double Gamma_Minus_One; /*!< \brief Fluids's Gamma - 1.0 . */ - su2double Minf; /*!< \brief Free stream Mach number . */ - su2double Gas_Constant; /*!< \brief Gas constant. */ - su2double *Vector; /*!< \brief Auxiliary vector. */ - su2double *Enthalpy_formation; /*!< \brief Enthalpy of formation. */ - su2double Prandtl_Lam; /*!< \brief Laminar Prandtl's number. */ - su2double Prandtl_Turb; /*!< \brief Turbulent Prandtl's number. */ - -public: - - su2double - **Flux_Tensor, /*!< \brief Flux tensor (used for viscous and inviscid purposes. */ - *Proj_Flux_Tensor; /*!< \brief Flux tensor projected in a direction. */ - - su2double - **tau, /*!< \brief Viscous stress tensor. */ - **delta, /*!< \brief Identity matrix. */ - **delta3; /*!< \brief 3 row Identity matrix. */ - su2double - *Diffusion_Coeff_i, /*!< \brief Species diffusion coefficients at point i. */ - *Diffusion_Coeff_j; /*!< \brief Species diffusion coefficients at point j. */ - su2double - Laminar_Viscosity_i, /*!< \brief Laminar viscosity at point i. */ - Laminar_Viscosity_j, /*!< \brief Laminar viscosity at point j. */ - Laminar_Viscosity_id, /*!< \brief Variation of laminar viscosity at point i. */ - Laminar_Viscosity_jd; /*!< \brief Variation of laminar viscosity at point j. */ - su2double - Thermal_Conductivity_i, /*!< \brief Thermal conductivity at point i. */ - Thermal_Conductivity_j, /*!< \brief Thermal conductivity at point j. */ - Thermal_Conductivity_ve_i, /*!< \brief Thermal conductivity at point i. */ - Thermal_Conductivity_ve_j, /*!< \brief Thermal conductivity at point j. */ - Thermal_Diffusivity_i, /*!< \brief Thermal diffusivity at point i. */ - Thermal_Diffusivity_j; /*!< \brief Thermal diffusivity at point j. */ - su2double - Cp_i, /*!< \brief Cp at point i. */ - Cp_j; /*!< \brief Cp at point j. */ - su2double *Theta_v; /*!< \brief Characteristic vibrational temperature */ - su2double - Eddy_Viscosity_i, /*!< \brief Eddy viscosity at point i. */ - Eddy_Viscosity_j; /*!< \brief Eddy viscosity at point j. */ - su2double - turb_ke_i, /*!< \brief Turbulent kinetic energy at point i. */ - turb_ke_j; /*!< \brief Turbulent kinetic energy at point j. */ - su2double - Pressure_i, /*!< \brief Pressure at point i. */ - Pressure_j; /*!< \brief Pressure at point j. */ - su2double - GravityForce_i, /*!< \brief Gravity force at point i. */ - GravityForce_j; /*!< \brief Gravity force at point j. */ - su2double - Density_i, /*!< \brief Density at point i. */ - Density_j; /*!< \brief Density at point j. */ - su2double - DensityInc_i, /*!< \brief Incompressible density at point i. */ - DensityInc_j; /*!< \brief Incompressible density at point j. */ - su2double - BetaInc2_i, /*!< \brief Beta incompressible at point i. */ - BetaInc2_j; /*!< \brief Beta incompressible at point j. */ - su2double - Lambda_i, /*!< \brief Spectral radius at point i. */ - Lambda_j; /*!< \brief Spectral radius at point j. */ - su2double - LambdaComb_i, /*!< \brief Spectral radius at point i. */ - LambdaComb_j; /*!< \brief Spectral radius at point j. */ - su2double - SoundSpeed_i, /*!< \brief Sound speed at point i. */ - SoundSpeed_j; /*!< \brief Sound speed at point j. */ - su2double - Enthalpy_i, /*!< \brief Enthalpy at point i. */ - Enthalpy_j; /*!< \brief Enthalpy at point j. */ - su2double - dist_i, /*!< \brief Distance of point i to the nearest wall. */ - dist_j; /*!< \brief Distance of point j to the nearest wall. */ - su2double - Temp_i, /*!< \brief Temperature at point i. */ - Temp_j; /*!< \brief Temperature at point j. */ - su2double - *Temp_tr_i, /*!< \brief Temperature transl-rot at point i. */ - *Temp_tr_j; /*!< \brief Temperature transl-rot at point j. */ - su2double - *Temp_vib_i, /*!< \brief Temperature vibrational at point i. */ - *Temp_vib_j; /*!< \brief Temperature vibrational at point j. */ - su2double - *Und_Lapl_i, /*!< \brief Undivided laplacians at point i. */ - *Und_Lapl_j; /*!< \brief Undivided laplacians at point j. */ - su2double - Sensor_i, /*!< \brief Pressure sensor at point i. */ - Sensor_j; /*!< \brief Pressure sensor at point j. */ - su2double - *GridVel_i, /*!< \brief Grid velocity at point i. */ - *GridVel_j; /*!< \brief Grid velocity at point j. */ - su2double - *U_i, /*!< \brief Vector of conservative variables at point i. */ - *U_id, /*!< \brief Vector of derivative of conservative variables at point i. */ - *UZeroOrder_i, /*!< \brief Vector of conservative variables at point i without reconstruction. */ - *U_j, /*!< \brief Vector of conservative variables at point j. */ - *UZeroOrder_j, /*!< \brief Vector of conservative variables at point j without reconstruction. */ - *U_jd, /*!< \brief Vector of derivative of conservative variables at point j. */ - *U_0, /*!< \brief Vector of conservative variables at node 0. */ - *U_1, /*!< \brief Vector of conservative variables at node 1. */ - *U_2, /*!< \brief Vector of conservative variables at node 2. */ - *U_3; /*!< \brief Vector of conservative variables at node 3. */ - su2double - *V_i, /*!< \brief Vector of primitive variables at point i. */ - *V_j; /*!< \brief Vector of primitive variables at point j. */ - su2double - *S_i, /*!< \brief Vector of secondary variables at point i. */ - *S_j; /*!< \brief Vector of secondary variables at point j. */ - su2double - *Psi_i, /*!< \brief Vector of adjoint variables at point i. */ - *Psi_j; /*!< \brief Vector of adjoint variables at point j. */ - su2double - *DeltaU_i, /*!< \brief Vector of linearized variables at point i. */ - *DeltaU_j; /*!< \brief Vector of linearized variables at point j. */ - su2double - *TurbVar_i, /*!< \brief Vector of turbulent variables at point i. */ - *TurbVar_id, /*!< \brief Vector of derivative of turbulent variables at point i. */ - *TurbVar_j, /*!< \brief Vector of turbulent variables at point j. */ - *TurbVar_jd; /*!< \brief Vector of derivative of turbulent variables at point j. */ - su2double - *TransVar_i, /*!< \brief Vector of turbulent variables at point i. */ - *TransVar_j; /*!< \brief Vector of turbulent variables at point j. */ - su2double - *TurbPsi_i, /*!< \brief Vector of adjoint turbulent variables at point i. */ - *TurbPsi_j; /*!< \brief Vector of adjoint turbulent variables at point j. */ - su2double - **ConsVar_Grad_i, /*!< \brief Gradient of conservative variables at point i. */ - **ConsVar_Grad_j, /*!< \brief Gradient of conservative variables at point j. */ - **ConsVar_Grad_0, /*!< \brief Gradient of conservative variables at point 0. */ - **ConsVar_Grad_1, /*!< \brief Gradient of conservative variables at point 1. */ - **ConsVar_Grad_2, /*!< \brief Gradient of conservative variables at point 2. */ - **ConsVar_Grad_3, /*!< \brief Gradient of conservative variables at point 3. */ - **ConsVar_Grad; /*!< \brief Gradient of conservative variables which is a scalar. */ - su2double - **PrimVar_Grad_i, /*!< \brief Gradient of primitive variables at point i. */ - **PrimVar_Grad_j; /*!< \brief Gradient of primitive variables at point j. */ - su2double - **PsiVar_Grad_i, /*!< \brief Gradient of adjoint variables at point i. */ - **PsiVar_Grad_j; /*!< \brief Gradient of adjoint variables at point j. */ - su2double - **TurbVar_Grad_i, /*!< \brief Gradient of turbulent variables at point i. */ - **TurbVar_Grad_j; /*!< \brief Gradient of turbulent variables at point j. */ - su2double - **TransVar_Grad_i, /*!< \brief Gradient of turbulent variables at point i. */ - **TransVar_Grad_j; /*!< \brief Gradient of turbulent variables at point j. */ - su2double - **TurbPsi_Grad_i, /*!< \brief Gradient of adjoint turbulent variables at point i. */ - **TurbPsi_Grad_j; /*!< \brief Gradient of adjoint turbulent variables at point j. */ - su2double - *AuxVar_Grad_i, /*!< \brief Gradient of an auxiliary variable at point i. */ - *AuxVar_Grad_j; /*!< \brief Gradient of an auxiliary variable at point i. */ - su2double - *Coord_i, /*!< \brief Cartesians coordinates of point i. */ - *Coord_j, /*!< \brief Cartesians coordinates of point j. */ - *Coord_0, /*!< \brief Cartesians coordinates of point 0 (Galerkin method, triangle). */ - *Coord_1, /*!< \brief Cartesians coordinates of point 1 (Galerkin method, tetrahedra). */ - *Coord_2, /*!< \brief Cartesians coordinates of point 2 (Galerkin method, triangle). */ - *Coord_3; /*!< \brief Cartesians coordinates of point 3 (Galerkin method, tetrahedra). */ - unsigned short - Neighbor_i, /*!< \brief Number of neighbors of the point i. */ - Neighbor_j; /*!< \brief Number of neighbors of the point j. */ - su2double - *Normal, /*!< \brief Normal vector, it norm is the area of the face. */ - *UnitNormal, /*!< \brief Unitary normal vector. */ - *UnitNormald; /*!< \brief derivatve of unitary normal vector. */ - su2double - TimeStep, /*!< \brief Time step useful in dual time method. */ - Area, /*!< \brief Area of the face i-j. */ - Volume; /*!< \brief Volume of the control volume around point i. */ - su2double - Volume_n, /*!< \brief Volume of the control volume at time n. */ - Volume_nM1, /*!< \brief Volume of the control volume at time n-1. */ - Volume_nP1; /*!< \brief Volume of the control volume at time n+1. */ - su2double - *U_n, /*!< \brief Vector of conservative variables at time n. */ - *U_nM1, /*!< \brief Vector of conservative variables at time n-1. */ - *U_nP1; /*!< \brief Vector of conservative variables at time n+1. */ - su2double vel2_inf; /*!< \brief value of the square of freestream speed. */ - su2double - *WindGust_i, /*!< \brief Wind gust at point i. */ - *WindGust_j; /*!< \brief Wind gust at point j. */ - su2double - *WindGustDer_i, /*!< \brief Wind gust derivatives at point i. */ - *WindGustDer_j; /*!< \brief Wind gust derivatives at point j. */ - su2double *Vorticity_i, *Vorticity_j; /*!< \brief Vorticity. */ - su2double StrainMag_i, StrainMag_j; /*!< \brief Strain rate magnitude. */ - su2double Dissipation_i, Dissipation_j; /*!< \brief Dissipation. */ - su2double Dissipation_ij; - - su2double *l, *m; - - su2double **MeanReynoldsStress; /*!< \brief Mean Reynolds stress tensor */ - su2double **MeanPerturbedRSM; /*!< \brief Perturbed Reynolds stress tensor */ - bool using_uq; /*!< \brief Flag for UQ methodology */ - su2double PerturbedStrainMag; /*!< \brief Strain magnitude calculated using perturbed stress tensor */ - unsigned short Eig_Val_Comp; /*!< \brief Component towards which perturbation is perfromed */ - su2double uq_delta_b; /*!< \brief Magnitude of perturbation */ - su2double uq_urlx; /*!< \brief Under-relaxation factor for numerical stability */ - bool uq_permute; /*!< \brief Flag for eigenvector permutation */ - - /* Supporting data structures for the eigenspace perturbation for UQ methodology */ - su2double **A_ij, **newA_ij, **Eig_Vec, **New_Eig_Vec, **Corners; - su2double *Eig_Val, *Barycentric_Coord, *New_Coord; - - /*! - * \brief Constructor of the class. - */ - CNumerics(void); - - /*! - * \overload - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CNumerics(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - virtual ~CNumerics(void); - - /*! - * \brief Compute the determinant of a 3 by 3 matrix. - * \param[in] val_matrix 3 by 3 matrix. - * \result Determinant of the matrix - */ - su2double Determinant_3x3(su2double A00, su2double A01, su2double A02, - su2double A10, su2double A11, su2double A12, - su2double A20, su2double A21, su2double A22); - - /*! - * \brief Set the solution at different times. - * \param[in] val_u_nM1 Conservative solution at time n-1. - * \param[in] val_u_n Conservative solution at time n. - * \param[in] val_u_nP1 Conservative solution at time n+1. - */ - void SetPastSol(su2double *val_u_nM1, su2double *val_u_n, su2double *val_u_nP1); - - /*! - * \brief Set the control volume at different times. - * \param[in] val_volume_nM1 - Control volume at time n-1. - * \param[in] val_volume_n - Control volume at time n. - * \param[in] val_volume_nP1 - Control volume at time n+1. - */ - void SetPastVolume(su2double val_volume_nM1, su2double val_volume_n, su2double val_volume_nP1); - - /*! - * \brief Set the time step. - * \param[in] val_timestep - Value of the time step. - */ - void SetTimeStep(su2double val_timestep); - - /*! - * \brief Set the freestream velocity square. - * \param[in] SetVelocity2_Inf - Value of the square of the freestream velocity. - */ - void SetVelocity2_Inf(su2double val_velocity2); - - /*! - * \brief Set the value of the vorticity - * \param[in] val_vorticity - Value of the vorticity. - */ - void SetVorticity(su2double *val_vorticity_i, su2double *val_vorticity_j); - - /*! - * \brief Set the value of the rate of strain magnitude. - * \param[in] val_StrainMag_i - Value of the magnitude of rate of strain at point i. - * \param[in] val_StrainMag_j - Value of the magnitude of rate of strain at point j. - */ - void SetStrainMag(su2double val_strainmag_i, su2double val_strainmag_j); - - /*! - * \brief Set the value of the conservative variables. - * \param[in] val_u_i - Value of the conservative variable at point i. - * \param[in] val_u_j - Value of the conservative variable at point j. - */ - void SetConservative(su2double *val_u_i, su2double *val_u_j); - - /*! - * \brief Set the value of the conservative variables withour reconstruction. - * \param[in] val_u_i - Value of the conservative variable at point i. - * \param[in] val_u_j - Value of the conservative variable at point j. - */ - void SetConservative_ZeroOrder(su2double *val_u_i, su2double *val_u_j); - - /*! - * \brief Set the value of the primitive variables. - * \param[in] val_v_i - Value of the primitive variable at point i. - * \param[in] val_v_j - Value of the primitive variable at point j. - */ - void SetPrimitive(su2double *val_v_i, su2double *val_v_j); - - /*! - * \brief Set the value of the primitive variables. - * \param[in] val_v_i - Value of the primitive variable at point i. - * \param[in] val_v_j - Value of the primitive variable at point j. - */ - void SetSecondary(su2double *val_s_i, su2double *val_s_j); - - /*! - * \brief Set the value of the conservative variables. - * \param[in] val_u_0 - Value of the conservative variable at point 0. - * \param[in] val_u_1 - Value of the conservative variable at point 1. - * \param[in] val_u_2 - Value of the conservative variable at point 2. - */ - void SetConservative(su2double *val_u_0, su2double *val_u_1, su2double *val_u_2); - - /*! - * \brief Set the value of the conservative variables. - * \param[in] val_u_0 - Value of the conservative variable at point 0. - * \param[in] val_u_1 - Value of the conservative variable at point 1. - * \param[in] val_u_2 - Value of the conservative variable at point 2. - * \param[in] val_u_3 - Value of the conservative variable at point 3. - */ - void SetConservative(su2double *val_u_0, su2double *val_u_1, su2double *val_u_2, su2double *val_u_3); - - /*! - * \brief Set the gradient of the conservative variables. - * \param[in] val_consvar_grad_i - Gradient of the conservative variable at point i. - * \param[in] val_consvar_grad_j - Gradient of the conservative variable at point j. - */ - void SetConsVarGradient(su2double **val_consvar_grad_i, su2double **val_consvar_grad_j); - - /*! - * \brief Set the gradient of the conservative variables. - * \param[in] val_consvar_grad_0 - Gradient of the conservative variable at point 0. - * \param[in] val_consvar_grad_1 - Gradient of the conservative variable at point 1. - * \param[in] val_consvar_grad_2 - Gradient of the conservative variable at point 2. - */ - void SetConsVarGradient(su2double **val_consvar_grad_0, - su2double **val_consvar_grad_1, - su2double **val_consvar_grad_2); - - /*! - * \brief Set the gradient of the conservative variables. - * \param[in] val_consvar_grad_0 - Gradient of the conservative variable at point 0. - * \param[in] val_consvar_grad_1 - Gradient of the conservative variable at point 1. - * \param[in] val_consvar_grad_2 - Gradient of the conservative variable at point 2. - * \param[in] val_consvar_grad_3 - Gradient of the conservative variable at point 3. - */ - void SetConsVarGradient(su2double **val_consvar_grad_0, - su2double **val_consvar_grad_1, - su2double **val_consvar_grad_2, - su2double **val_consvar_grad_3); - - /*! - * \brief Set the gradient of the conservative variables. - * \param[in] val_consvar_grad - Gradient of the conservative variable which is a scalar. - */ - void SetConsVarGradient(su2double **val_consvar_grad); - - /*! - * \brief Set the gradient of the primitive variables. - * \param[in] val_primvar_grad_i - Gradient of the primitive variable at point i. - * \param[in] val_primvar_grad_j - Gradient of the primitive variable at point j. - */ - void SetPrimVarGradient(su2double **val_primvar_grad_i, - su2double **val_primvar_grad_j); - - /*! - * \brief Set the value of the adjoint variable. - * \param[in] val_psi_i - Value of the adjoint variable at point i. - * \param[in] val_psi_j - Value of the adjoint variable at point j. - */ - void SetAdjointVar(su2double *val_psi_i, su2double *val_psi_j); - - /*! - * \brief Set the gradient of the adjoint variables. - * \param[in] val_psivar_grad_i - Gradient of the adjoint variable at point i. - * \param[in] val_psivar_grad_j - Gradient of the adjoint variable at point j. - */ - void SetAdjointVarGradient(su2double **val_psivar_grad_i, su2double **val_psivar_grad_j); - - /*! - * \brief Set the value of the turbulent variable. - * \param[in] val_turbvar_i - Value of the turbulent variable at point i. - * \param[in] val_turbvar_j - Value of the turbulent variable at point j. - */ - void SetTurbVar(su2double *val_turbvar_i, su2double *val_turbvar_j); - - /*! - * \brief Set the value of the turbulent variable. - * \param[in] val_transvar_i - Value of the turbulent variable at point i. - * \param[in] val_transvar_j - Value of the turbulent variable at point j. - */ - void SetTransVar(su2double *val_transvar_i, su2double *val_transvar_j); - - /*! - * \brief Set the gradient of the turbulent variables. - * \param[in] val_turbvar_grad_i - Gradient of the turbulent variable at point i. - * \param[in] val_turbvar_grad_j - Gradient of the turbulent variable at point j. - */ - void SetTurbVarGradient(su2double **val_turbvar_grad_i, su2double **val_turbvar_grad_j); - - /*! - * \brief Set the gradient of the turbulent variables. - * \param[in] val_turbvar_grad_i - Gradient of the turbulent variable at point i. - * \param[in] val_turbvar_grad_j - Gradient of the turbulent variable at point j. - */ - void SetTransVarGradient(su2double **val_transvar_grad_i, su2double **val_transvar_grad_j); - - /*! - * \brief Set the value of the adjoint turbulent variable. - * \param[in] val_turbpsivar_i - Value of the adjoint turbulent variable at point i. - * \param[in] val_turbpsivar_j - Value of the adjoint turbulent variable at point j. - */ - void SetTurbAdjointVar(su2double *val_turbpsivar_i, su2double *val_turbpsivar_j); - - /*! - * \brief Set the gradient of the adjoint turbulent variables. - * \param[in] val_turbpsivar_grad_i - Gradient of the adjoint turbulent variable at point i. - * \param[in] val_turbpsivar_grad_j - Gradient of the adjoint turbulent variable at point j. - */ - void SetTurbAdjointGradient (su2double **val_turbpsivar_grad_i, su2double **val_turbpsivar_grad_j); - - /*! - * \brief Set the value of the first blending function. - * \param[in] val_F1_i - Value of the first Menter blending function at point i. - * \param[in] val_F1_j - Value of the first Menter blending function at point j. - */ - virtual void SetF1blending(su2double val_F1_i, su2double val_F1_j) {/* empty */}; - - /*! - * \brief Set the value of the second blending function. - * \param[in] val_F1_i - Value of the second Menter blending function at point i. - * \param[in] val_F1_j - Value of the second Menter blending function at point j. - */ - virtual void SetF2blending(su2double val_F1_i, su2double val_F1_j) {/* empty */}; - - /*! - * \brief Set the value of the cross diffusion for the SST model. - * \param[in] val_CDkw_i - Value of the cross diffusion at point i. - * \param[in] val_CDkw_j - Value of the cross diffusion at point j. - */ - virtual void SetCrossDiff(su2double val_CDkw_i, su2double val_CDkw_j) {/* empty */}; - - /*! - * \brief Set the gradient of the auxiliary variables. - * \param[in] val_auxvargrad_i - Gradient of the auxiliary variable at point i. - * \param[in] val_auxvargrad_j - Gradient of the auxiliary variable at point j. - */ - void SetAuxVarGrad(su2double *val_auxvargrad_i, su2double *val_auxvargrad_j); - - /*! - * \brief Set the diffusion coefficient - * \param[in] val_diffusioncoeff_i - Value of the diffusion coefficients at i. - * \param[in] val_diffusioncoeff_j - Value of the diffusion coefficients at j - */ - void SetDiffusionCoeff(su2double* val_diffusioncoeff_i, - su2double* val_diffusioncoeff_j); - - /*! - * \brief Set the laminar viscosity. - * \param[in] val_laminar_viscosity_i - Value of the laminar viscosity at point i. - * \param[in] val_laminar_viscosity_j - Value of the laminar viscosity at point j. - */ - void SetLaminarViscosity(su2double val_laminar_viscosity_i, - su2double val_laminar_viscosity_j); - - /*! - * \brief Set the thermal conductivity (translational/rotational) - * \param[in] val_thermal_conductivity_i - Value of the thermal conductivity at point i. - * \param[in] val_thermal_conductivity_j - Value of the thermal conductivity at point j. - * \param[in] iSpecies - Value of the species. - */ - void SetThermalConductivity(su2double val_thermal_conductivity_i, - su2double val_thermal_conductivity_j); - - /*! - * \brief Set the thermal conductivity (translational/rotational) - * \param[in] val_thermal_conductivity_i - Value of the thermal conductivity at point i. - * \param[in] val_thermal_conductivity_j - Value of the thermal conductivity at point j. - * \param[in] iSpecies - Value of the species. - */ - void SetThermalConductivity_ve(su2double val_thermal_conductivity_ve_i, - su2double val_thermal_conductivity_ve_j); - - /*! - * \brief Set the thermal diffusivity (translational/rotational) - * \param[in] val_thermal_diffusivity_i - Value of the thermal diffusivity at point i. - * \param[in] val_thermal_diffusivity_j - Value of the thermal diffusivity at point j. - * \param[in] iSpecies - Value of the species. - */ - void SetThermalDiffusivity(su2double val_thermal_diffusivity_i, - su2double val_thermal_diffusivity_j); - /*! - * \brief Set the eddy viscosity. - * \param[in] val_eddy_viscosity_i - Value of the eddy viscosity at point i. - * \param[in] val_eddy_viscosity_j - Value of the eddy viscosity at point j. - */ - void SetEddyViscosity(su2double val_eddy_viscosity_i, - su2double val_eddy_viscosity_j); - - /*! - * \brief Set the turbulent kinetic energy. - * \param[in] val_turb_ke_i - Value of the turbulent kinetic energy at point i. - * \param[in] val_turb_ke_j - Value of the turbulent kinetic energy at point j. - */ - void SetTurbKineticEnergy(su2double val_turb_ke_i, su2double val_turb_ke_j); - - /*! - * \brief Set the value of the distance from the nearest wall. - * \param[in] val_dist_i - Value of of the distance from point i to the nearest wall. - * \param[in] val_dist_j - Value of of the distance from point j to the nearest wall. - */ - void SetDistance(su2double val_dist_i, su2double val_dist_j); - - /*! - * \brief Set coordinates of the points. - * \param[in] val_coord_i - Coordinates of the point i. - * \param[in] val_coord_j - Coordinates of the point j. - */ - void SetCoord(su2double *val_coord_i, su2double *val_coord_j); - - /*! - * \overload - * \param[in] val_coord_0 - Coordinates of the point 0. - * \param[in] val_coord_1 - Coordinates of the point 1. - * \param[in] val_coord_2 - Coordinates of the point 2. - */ - void SetCoord(su2double *val_coord_0, su2double *val_coord_1, su2double *val_coord_2); - - /*! - * \overload - * \param[in] val_coord_0 - Coordinates of the point 0. - * \param[in] val_coord_1 - Coordinates of the point 1. - * \param[in] val_coord_2 - Coordinates of the point 2. - * \param[in] val_coord_3 - Coordinates of the point 3. - */ - void SetCoord(su2double *val_coord_0, su2double *val_coord_1, su2double *val_coord_2, - su2double *val_coord_3); - - /*! - * \brief Set the velocity of the computational grid. - * \param[in] val_gridvel_i - Grid velocity of the point i. - * \param[in] val_gridvel_j - Grid velocity of the point j. - */ - void SetGridVel(su2double *val_gridvel_i, su2double *val_gridvel_j); - - /*! - * \brief Set the wind gust value. - * \param[in] val_windgust_i - Wind gust of the point i. - * \param[in] val_windgust_j - Wind gust of the point j. - */ - void SetWindGust(su2double *val_windgust_i, su2double *val_windgust_j); - - /*! - * \brief Set the wind gust derivatives values. - * \param[in] val_windgust_i - Wind gust derivatives of the point i. - * \param[in] val_windgust_j - Wind gust derivatives of the point j. - */ - void SetWindGustDer(su2double *val_windgustder_i, su2double *val_windgustder_j); - - /*! - * \brief Set the value of the pressure. - * \param[in] val_pressure_i - Value of the pressure at point i. - * \param[in] val_pressure_j - Value of the pressure at point j. - */ - void SetPressure(su2double val_pressure_i, su2double val_pressure_j); - - /*! - * \brief Set the value of the density for the incompressible solver. - * \param[in] val_densityinc_i - Value of the pressure at point i. - * \param[in] val_densityinc_j - Value of the pressure at point j. - */ - void SetDensity(su2double val_densityinc_i, su2double val_densityinc_j); - - /*! - * \brief Set the value of the beta for incompressible flows. - * \param[in] val_betainc2_i - Value of beta for incompressible flows at point i. - * \param[in] val_betainc2_j - Value of beta for incompressible flows at point j. - */ - void SetBetaInc2(su2double val_betainc2_i, su2double val_betainc2_j); - - /*! - * \brief Set the value of the sound speed. - * \param[in] val_soundspeed_i - Value of the sound speed at point i. - * \param[in] val_soundspeed_j - Value of the sound speed at point j. - */ - void SetSoundSpeed(su2double val_soundspeed_i, su2double val_soundspeed_j); - - /*! - * \brief Set the value of the temperature. - * \param[in] val_temp_i - Value of the temperature at point i. - * \param[in] val_temp_j - Value of the temperature at point j. - */ - void SetTemperature(su2double val_temp_i, su2double val_temp_j); - - /*! - * \brief Set the value of the enthalpy. - * \param[in] val_enthalpy_i - Value of the enthalpy at point i. - * \param[in] val_enthalpy_j - Value of the enthalpy at point j. - */ - void SetEnthalpy(su2double val_enthalpy_i, su2double val_enthalpy_j); - - /*! - * \brief Set the value of the spectral radius. - * \param[in] val_lambda_i - Value of the spectral radius at point i. - * \param[in] val_lambda_j - Value of the spectral radius at point j. - */ - void SetLambda(su2double val_lambda_i, su2double val_lambda_j); - - /*! - * \brief Set the value of undivided laplacian. - * \param[in] val_und_lapl_i Undivided laplacian at point i. - * \param[in] val_und_lapl_j Undivided laplacian at point j. - */ - void SetUndivided_Laplacian(su2double *val_und_lapl_i, su2double *val_und_lapl_j); - - /*! - * \brief Set the value of the pressure sensor. - * \param[in] val_sensor_i Pressure sensor at point i. - * \param[in] val_sensor_j Pressure sensor at point j. - */ - void SetSensor(su2double val_sensor_i, su2double val_sensor_j); - - /*! - * \brief Set the number of neighbor to a point. - * \param[in] val_neighbor_i - Number of neighbor to point i. - * \param[in] val_neighbor_j - Number of neighbor to point j. - */ - void SetNeighbor(unsigned short val_neighbor_i, unsigned short val_neighbor_j); - - /*! - * \brief Set the value of the normal vector to the face between two points. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - */ - void SetNormal(su2double *val_normal); - - /*! - * \brief Set the value of the volume of the control volume. - * \param[in] val_volume Volume of the control volume. - */ - void SetVolume(su2double val_volume); - - /*! - * \brief Retrieves the value of the species density in the primitive variable vector. - * \param[in] iRho_s - */ - void SetRhosIndex(unsigned short val_Index); - - /*! - * \brief Retrieves the value of the species density in the primitive variable vector. - * \param[in] iRho_s - */ - void SetRhoIndex(unsigned short val_Index); - - /*! - * \brief Retrieves the value of the species density in the primitive variable vector. - * \param[in] iRho_s - */ - void SetPIndex(unsigned short val_Index); - - /*! - * \brief Retrieves the value of the species density in the primitive variable vector. - * \param[in] iRho_s - */ - void SetTIndex(unsigned short val_Index); - - /*! - * \brief Retrieves the value of the species density in the primitive variable vector. - * \param[in] iRho_s - */ - void SetTveIndex(unsigned short val_Index); - - /*! - * \brief Retrieves the value of the velocity index in the primitive variable vector. - * \param[in] i(rho*u) - */ - void SetVelIndex(unsigned short val_Index); - - /*! - * \brief Retrieves the value of the species density in the primitive variable vector. - * \param[in] iRho_s - */ - void SetHIndex(unsigned short val_Index); - - /*! - * \brief Retrieves the value of the species density in the primitive variable vector. - * \param[in] iRho_s - */ - void SetAIndex(unsigned short val_Index); - - /*! - * \brief Retrieves the value of the species density in the primitive variable vector. - * \param[in] iRho_s - */ - void SetRhoCvtrIndex(unsigned short val_Index); - - /*! - * \brief Retrieves the value of the species density in the primitive variable vector. - * \param[in] iRho_s - */ - void SetRhoCvveIndex(unsigned short val_Index); - - /*! - * \brief Sets the value of the derivative of pressure w.r.t. species density. - * \param[in] iRho_s - */ - void SetdPdU(su2double *val_dPdU_i, su2double *val_dPdU_j); - - /*! - * \brief Sets the value of the derivative of temperature w.r.t. species density. - * \param[in] iRho_s - */ - void SetdTdU(su2double *val_dTdU_i, su2double *val_dTdU_j); - - /*! - * \brief Sets the value of the derivative of vib-el. temperature w.r.t. species density. - * \param[in] iRho_s - */ - void SetdTvedU(su2double *val_dTvedU_i, su2double *val_dTvedU_j); - - /*! - * \brief Sets the values of the roe dissipation. - * \param[in] diss_i - Dissipation value at node i - * \param[in] diss_j - Dissipation value at node j - */ - void SetDissipation(su2double diss_i, su2double diss_j); - - /*! - * \brief Get the final Roe dissipation factor. - */ - su2double GetDissipation(); - - /*! - * \brief Get the inviscid fluxes. - * \param[in] val_density - Value of the density. - * \param[in] val_velocity - Value of the velocity. - * \param[in] val_pressure - Value of the pressure. - * \param[in] val_enthalpy - Value of the enthalpy. - */ - void GetInviscidFlux(su2double val_density, su2double *val_velocity, su2double val_pressure, su2double val_enthalpy); - - /*! - * \brief Compute the projected inviscid flux vector. - * \param[in] val_density - Pointer to the density. - * \param[in] val_velocity - Pointer to the velocity. - * \param[in] val_pressure - Pointer to the pressure. - * \param[in] val_enthalpy - Pointer to the enthalpy. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[out] val_Proj_Flux - Pointer to the projected flux. - */ - void GetInviscidProjFlux(su2double *val_density, su2double *val_velocity, - su2double *val_pressure, su2double *val_enthalpy, - su2double *val_normal, su2double *val_Proj_Flux); - - /*! - * \brief Compute the projected inviscid flux vector for incompresible simulations - * \param[in] val_density - Pointer to the density. - * \param[in] val_velocity - Pointer to the velocity. - * \param[in] val_pressure - Pointer to the pressure. - * \param[in] val_betainc2 - Value of the artificial compresibility factor. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[out] val_Proj_Flux - Pointer to the projected flux. - */ - void GetInviscidIncProjFlux(su2double *val_density, su2double *val_velocity, - su2double *val_pressure, su2double *val_betainc2, - su2double *val_enthalpy, - su2double *val_normal, su2double *val_Proj_Flux); - - /*! - * \brief Compute the projection of the inviscid Jacobian matrices. - * \param[in] val_velocity Pointer to the velocity. - * \param[in] val_energy Value of the energy. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[in] val_scale - Scale of the projection. - * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. - */ - void GetInviscidProjJac(su2double *val_velocity, su2double *val_energy, - su2double *val_normal, su2double val_scale, - su2double **val_Proj_Jac_tensor); - - /*! - * \brief Compute the projection of the inviscid Jacobian matrices (incompressible). - * \param[in] val_density - Value of the density. - * \param[in] val_velocity - Pointer to the velocity. - * \param[in] val_betainc2 - Value of the artificial compresibility factor. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[in] val_scale - Scale of the projection. - * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. - */ - void GetInviscidIncProjJac(su2double *val_density, su2double *val_velocity, - su2double *val_betainc2, su2double *val_normal, - su2double val_scale, - su2double **val_Proj_Jac_tensor); - - /*! - * \brief Compute the projection of the inviscid Jacobian matrices (overload for low speed preconditioner version). - * \param[in] val_density - Value of the density. - * \param[in] val_velocity - Pointer to the velocity. - * \param[in] val_betainc2 - Value of the artificial compresibility factor. - * \param[in] val_cp - Value of the specific heat at constant pressure. - * \param[in] val_temperature - Value of the temperature. - * \param[in] val_dRhodT - Value of the derivative of density w.r.t. temperature. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[in] val_scale - Scale of the projection. - * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. - */ - void GetInviscidIncProjJac(su2double *val_density, - su2double *val_velocity, - su2double *val_betainc2, - su2double *val_cp, - su2double *val_temperature, - su2double *val_dRhodT, - su2double *val_normal, - su2double val_scale, - su2double **val_Proj_Jac_Tensor); - - /*! - * \brief Compute the low speed preconditioning matrix. - * \param[in] val_density - Value of the density. - * \param[in] val_velocity - Pointer to the velocity. - * \param[in] val_betainc2 - Value of the artificial compresibility factor. - * \param[in] val_cp - Value of the specific heat at constant pressure. - * \param[in] val_temperature - Value of the temperature. - * \param[in] val_dRhodT - Value of the derivative of density w.r.t. temperature. - * \param[out] val_Precon - Pointer to the preconditioning matrix. - */ - void GetPreconditioner(su2double *val_density, - su2double *val_velocity, - su2double *val_betainc2, - su2double *val_cp, - su2double *val_temperature, - su2double *val_drhodt, - su2double **val_Precon); - - /*! - * \brief Compute the projection of the preconditioned inviscid Jacobian matrices. - * \param[in] val_density - Value of the density. - * \param[in] val_velocity - Pointer to the velocity. - * \param[in] val_betainc2 - Value of the artificial compresibility factor. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. - */ - void GetPreconditionedProjJac(su2double *val_density, - su2double *val_velocity, - su2double *val_betainc2, - su2double *val_normal, - su2double **val_Proj_Jac_Tensor); - - /*! - * \brief Compute the projection of the inviscid Jacobian matrices for general fluid model. - * \param[in] val_velocity Pointer to the velocity. - * \param[in] val_energy Value of the energy. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[in] val_scale - Scale of the projection. - * \param[out] val_Proj_Jac_tensor - Pointer to the projected inviscid Jacobian. - */ - void GetInviscidProjJac(su2double *val_velocity, su2double *val_enthalphy, - su2double *val_chi, su2double *val_kappa, - su2double *val_normal, su2double val_scale, - su2double **val_Proj_Jac_tensor); - - /*! - * \brief Mapping between primitives variables P and conservatives variables C. - * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. - * \param[in] val_Mean_PrimVar - Mean Value of the secondary variables. - * \param[out] val_Jac_PC - Pointer to the Jacobian dPdC. - */ - void GetPrimitive2Conservative (su2double *val_Mean_PrimVar, - su2double *val_Mean_SecVar, - su2double **val_Jac_PC); - - /*! - * \overload - * \brief Computation of the matrix P for a generic fluid model - * \param[in] val_density - Value of the density. - * \param[in] val_velocity - Value of the velocity. - * \param[in] val_soundspeed - Value of the sound speed. - * \param[in] val_enthalpy - Value of the Enthalpy - * \param[in] val_chi - Value of the derivative of Pressure with respect to the Density. - * \param[in] val_kappa - Value of the derivative of Pressure with respect to the volume specific Static Energy. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[out] val_p_tensor - Pointer to the P matrix. - */ - void GetPMatrix(su2double *val_density, su2double *val_velocity, - su2double *val_soundspeed, su2double *val_enthalpy, su2double *val_chi, su2double *val_kappa, - su2double *val_normal, su2double **val_p_tensor); - - /*! - * \brief Computation of the matrix P, this matrix diagonalize the conservative Jacobians in - * the form $P^{-1}(A.Normal)P=Lambda$. - * \param[in] val_density - Value of the density. - * \param[in] val_velocity - Value of the velocity. - * \param[in] val_soundspeed - Value of the sound speed. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[out] val_p_tensor - Pointer to the P matrix. - */ - void GetPMatrix(su2double *val_density, su2double *val_velocity, - su2double *val_soundspeed, su2double *val_normal, - su2double **val_p_tensor); - - /*! - * \brief Computation of the matrix Rinv*Pe. - * \param[in] Beta2 - A variable in used to define Pe matrix. - * \param[in] val_enthalpy - value of the enthalpy. - * \param[in] val_soundspeed - value of the sound speed. - * \param[in] val_density - value of the density. - * \param[in] val_velocity - value of the velocity. - * \param[out] val_invR_invPe - Pointer to the matrix of conversion from entropic to conserved variables. - */ - void GetinvRinvPe(su2double Beta2, su2double val_enthalpy, su2double val_soundspeed, - su2double val_density, su2double* val_velocity, - su2double** val_invR_invPe); - - /*! - * \brief Computation of the matrix R. - * \param[in] val_pressure - value of the pressure. - * \param[in] val_soundspeed - value of the sound speed. - * \param[in] val_density - value of the density. - * \param[in] val_velocity - value of the velocity. - * \param[out] val_invR_invPe - Pointer to the matrix of conversion from entropic to conserved variables. - */ - - void GetRMatrix(su2double val_pressure, su2double val_soundspeed, - su2double val_density, su2double* val_velocity, - su2double** val_invR_invPe); - /*! - * \brief Computation of the matrix R. - * \param[in] val_soundspeed - value of the sound speed. - * \param[in] val_density - value of the density. - * \param[out] R_Matrix - Pointer to the matrix of conversion from entropic to conserved variables. - */ - void GetRMatrix(su2double val_soundspeed, su2double val_density, su2double **R_Matrix); - - /*! - * \brief Computation of the matrix R. - * \param[in] val_soundspeed - value of the sound speed. - * \param[in] val_density - value of the density. - * \param[out] L_Matrix - Pointer to the matrix of conversion from conserved to entropic variables. - */ - void GetLMatrix(su2double val_soundspeed, su2double val_density, su2double **L_Matrix); - - /*! - * \brief Computation of the flow Residual Jacoboan Matrix for Non Reflecting BC. - * \param[in] val_soundspeed - value of the sound speed. - * \param[in] val_density - value of the density. - * \param[out] R_c - Residual Jacoboan Matrix - * \param[out] R_c_inv- inverse of the Residual Jacoboan Matrix . - */ - void ComputeResJacobianGiles(CFluidModel *FluidModel, su2double pressure, su2double density, su2double *turboVel, - su2double alphaInBC, su2double gammaInBC, su2double **R_c, su2double **R_c_inv); - - /*! - * \brief Computate the inverse of a 3x3 matrix - * \param[in] matrix - the matrix to invert - * \param[out] invMatrix - inverse matrix. - */ - void InvMatrix3D(su2double **matrix, su2double **invMatrix); - - /*! - * \brief Computate the inverse of a 4x4 matrix - * \param[in] matrix - the matrix to invert - * \param[out] invMatrix - inverse matrix. - */ - void InvMatrix4D(su2double **matrix, su2double **invMatrix); - - /*! - * \brief Computation of the matrix R. - * \param[in] val_soundspeed - value of the sound speed. - * \param[in] val_density - value of the density. - * \param[in] prim_jump - pointer to the vector containing the primitive variable jump (drho, dV, dp). - * \param[out]char_jump - pointer to the vector containing the characteristic variable jump. - */ - void GetCharJump(su2double val_soundspeed, su2double val_density, su2double *prim_jump, su2double *char_jump); - - /*! - * \brief Computation of the matrix Td, this matrix diagonalize the preconditioned conservative Jacobians - * in the form $Tg |Lambda| Td = Pc{-1}|Pc (A.Normal)|$. - * \param[in] Beta2 - A variable in used to define absPeJacobian matrix. - * \param[in] r_hat - A variable in used to define absPeJacobian matrix. - * \param[in] s_hat - A variable in used to define absPeJacobian matrix. - * \param[in] t_hat - A variable in used to define absPeJacobian matrix. - * \param[in] rB2a2 - A variable in used to define absPeJacobian matrix. - * \param[in] val_Lambda - Eigenvalues of the Preconditioned Jacobian. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[out] val_absPeJac - Pointer to the Preconditioned Jacobian matrix. - */ - void GetPrecondJacobian(su2double Beta2, su2double r_hat, su2double s_hat, su2double t_hat, su2double rB2a2, su2double* val_Lambda, su2double* val_normal, su2double** val_absPeJac); - - - /*! - * \brief Computation of the matrix P^{-1}, this matrix diagonalize the conservative Jacobians - * in the form $P^{-1}(A.Normal)P=Lambda$. - * \param[in] val_density - Value of the density. - * \param[in] val_velocity - Value of the velocity. - * \param[in] val_soundspeed - Value of the sound speed. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[out] val_invp_tensor - Pointer to inverse of the P matrix. - */ - void GetPMatrix_inv(su2double **val_invp_tensor, su2double *val_density, - su2double *val_velocity, su2double *val_soundspeed, - su2double *val_chi, su2double *val_kappa, - su2double *val_normal); - - /*! - * \brief Computation of the matrix P^{-1}, this matrix diagonalize the conservative Jacobians - * in the form $P^{-1}(A.Normal)P=Lambda$. - * \param[in] val_density - Value of the density. - * \param[in] val_velocity - Value of the velocity. - * \param[in] val_soundspeed - Value of the sound speed. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[out] val_invp_tensor - Pointer to inverse of the P matrix. - */ - void GetPMatrix_inv(su2double *val_density, su2double *val_velocity, - su2double *val_soundspeed, su2double *val_normal, - su2double **val_invp_tensor); - - /*! - * \brief Compute viscous residual and jacobian. - */ - void GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j, su2double Density_i, su2double Density_j, - su2double ViscDens_i, su2double ViscDens_j, su2double *Velocity_i, su2double *Velocity_j, - su2double sq_vel_i, su2double sq_vel_j, - su2double XiDens_i, su2double XiDens_j, su2double **Mean_GradPhi, su2double *Mean_GradPsiE, - su2double dPhiE_dn, su2double *Normal, su2double *Edge_Vector, su2double dist_ij_2, su2double *val_residual_i, - su2double *val_residual_j, - su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, - su2double **val_Jacobian_jj, bool implicit); - - /*! - * \brief Computation of the projected inviscid lambda (eingenvalues). - * \param[in] val_velocity - Value of the velocity. - * \param[in] val_soundspeed - Value of the sound speed. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[in] val_Lambda_Vector - Pointer to Lambda matrix. - */ - void GetJacInviscidLambda_fabs(su2double *val_velocity, su2double val_soundspeed, - su2double *val_normal, su2double *val_Lambda_Vector); - - /*! - * \brief Compute the numerical residual. - * \param[out] val_residual - Pointer to the total residual. - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double *val_residual, CConfig *config); - - /*! - * \overload - * \param[out] val_residual_i - Pointer to the total residual at point i. - * \param[out] val_residual_j - Pointer to the total residual at point j. - */ - virtual void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j); - - virtual void ComputeResidual_TransLM(su2double *val_residual, - su2double **val_Jacobian_i, - su2double **val_Jacobian_j, CConfig *config, - su2double &gamma_sep) ; - - /*! - * \overload - * \param[out] val_residual_i - Pointer to the total residual at point i. - * \param[out] val_residual_j - Pointer to the total residual at point j. - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double *val_residual_i, - su2double *val_residual_j, CConfig *config); - - /*! - * \overload - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, - su2double **val_Jacobian_j, CConfig *config); - - /*! - * \overload - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[out] val_JacobianMeanFlow_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_JacobianMeanFlow_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, - su2double **val_Jacobian_j, - su2double **val_JacobianMeanFlow_i, - su2double **val_JacobianMeanFlow_j, - CConfig *config); - - /*! - * \overload - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double **val_Jacobian_i, su2double **val_Jacobian_j, - CConfig *config); - - /*! - * \overload - * \param[out] val_resconv - Pointer to the convective residual. - * \param[out] val_resvisc - Pointer to the artificial viscosity residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double *val_resconv, su2double *val_resvisc, - su2double **val_Jacobian_i, su2double **val_Jacobian_j, - CConfig *config); - - /*! - * \overload - * \param[out] val_residual_i - Pointer to the total residual at point i. - * \param[out] val_residual_j - Pointer to the total viscosity residual at point j. - * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. - * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. - * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. - * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, - su2double **val_Jacobian_ii, - su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, - su2double **val_Jacobian_jj, CConfig *config); - - /*! - * \overload - * \param[out] val_resconv_i - Pointer to the convective residual at point i. - * \param[out] val_resvisc_i - Pointer to the artificial viscosity residual at point i. - * \param[out] val_resconv_j - Pointer to the convective residual at point j. - * \param[out] val_resvisc_j - Pointer to the artificial viscosity residual at point j. - * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. - * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. - * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. - * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double *val_resconv_i, su2double *val_resvisc_i, - su2double *val_resconv_j, su2double *val_resvisc_j, - su2double **val_Jacobian_ii, - su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, - su2double **val_Jacobian_jj, CConfig *config); - - /*! - * \overload - * \param[out] val_stiffmatrix_elem - Stiffness matrix for Galerkin computation. - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double **val_stiffmatrix_elem, CConfig *config); - - /*! - * \overload - * \param[in] config - Definition of the particular problem. - * \param[out] val_residual - residual of the source terms - * \param[out] val_Jacobian_i - Jacobian of the source terms - */ - virtual void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, - CConfig *config); - - /*! - * \overload - * \param[out] - Matrix for storing the constants to be used in the calculation of the equilibrium extent of reaction Keq. - * \param[in] config - Definition of the particular problem. - */ - virtual void GetEq_Rxn_Coefficients(su2double **EqnRxnConstants, CConfig *config); - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the source residual containing chemistry terms. - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual_Axisymmetric(su2double *val_residual, CConfig *config); - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the source residual containing chemistry terms. - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual_Axisymmetric_ad(su2double *val_residual, su2double *val_residuald, CConfig *config); - - /*! - * \brief Calculation of axisymmetric source term Jacobian - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - virtual void SetJacobian_Axisymmetric(su2double **val_Jacobian_i, CConfig *config); - - /*! - * \brief Calculation of the translational-vibrational energy exchange source term - * \param[in] config - Definition of the particular problem. - * \param[out] val_residual - residual of the source terms - * \param[out] val_Jacobian_i - Jacobian of the source terms - */ - virtual void ComputeVibRelaxation(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config); - - /*! - * \brief Calculation of the chemistry source term - * \param[in] config - Definition of the particular problem. - * \param[out] val_residual - residual of the source terms - * \param[out] val_Jacobian_i - Jacobian of the source terms - */ - virtual void ComputeChemistry(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config); - - /*! - * \brief Calculates constants used for Keq correlation. - * \param[out] A - Pointer to coefficient array. - * \param[in] val_reaction - Reaction number indicator. - * \param[in] config - Definition of the particular problem. - */ - virtual void GetKeqConstants(su2double *A, unsigned short val_reaction, CConfig *config); - - /*! - * \brief Set intermittency for numerics (used in SA with LM transition model) - */ - virtual void SetIntermittency(su2double intermittency_in); - - /*! - * \brief Residual for source term integration. - * \param[in] val_production - Value of the Production. - */ - virtual void SetProduction(su2double val_production); - - /*! - * \brief Residual for source term integration. - * \param[in] val_destruction - Value of the Destruction. - */ - virtual void SetDestruction(su2double val_destruction); - - /*! - * \brief Residual for source term integration. - * \param[in] val_crossproduction - Value of the CrossProduction. - */ - virtual void SetCrossProduction(su2double val_crossproduction); - - /*! - * \brief Residual for source term integration. - * \param[in] val_production - Value of the Production. - */ - virtual su2double GetProduction(void); - - /*! - * \brief Residual for source term integration. - * \param[in] val_destruction - Value of the Destruction. - */ - virtual su2double GetDestruction(void); - - /*! - * \brief Residual for source term integration. - * \param[in] val_crossproduction - Value of the CrossProduction. - */ - virtual su2double GetCrossProduction(void); - - /*! - * \brief A virtual member. - */ - virtual su2double GetGammaBC(void); - - /*! - * \overload - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double **val_Jacobian_i, - su2double *val_Jacobian_mui, - su2double ***val_Jacobian_gradi, CConfig *config); - - /*! - * \overload - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i - * \param[in] config - Definition of the particular problem. - */ - virtual void ComputeResidual(su2double **val_Jacobian_i, - su2double *val_Jacobian_mui, - su2double ***val_Jacobian_gradi, - su2double **val_Jacobian_j, - su2double *val_Jacobian_muj, - su2double ***val_Jacobian_gradj, CConfig *config); - - /*! - * \brief A virtual member to compute the tangent matrix in structural problems - * \param[in] element_container - Element structure for the particular element integrated. - */ - virtual void Compute_Tangent_Matrix(CElement *element_container, CConfig *config); - - /*! - * \brief A virtual member to compute the nodal stress term in non-linear structural problems - * \param[in] element_container - Definition of the particular element integrated. - */ - virtual void Compute_NodalStress_Term(CElement *element_container, CConfig *config); - - /*! - * \brief Set the element-based local Young's modulus in mesh problems - * \param[in] iElem - Element index. - * \param[in] val_E - Value of elasticity modulus. - */ - virtual void SetMeshElasticProperties(unsigned long iElem, su2double val_E); - - /*! - * \brief A virtual member to set the value of the design variables - * \param[in] i_DV - Index of the design variable. - * \param[in] val_DV - Value of the design variable - */ - virtual void Set_DV_Val(unsigned short i_DV, su2double val_DV); - - /*! - * \brief A virtual member to retrieve the value of the design variables - * \param[in] i_DV - Index of the design variable. - */ - virtual su2double Get_DV_Val(unsigned short i_DV) const; - - /*! - * \brief A virtual member to set the electric field - * \param[in] EField_DV - New electric field computed by adjoint methods. - */ - virtual void Set_ElectricField(unsigned short i_DV, su2double val_EField); - - /*! - * \brief A virtual member to set the material properties - * \param[in] iVal - Index of the region of concern - * \param[in] val_E - Value of the Young Modulus. - * \param[in] val_Nu - Value of the Poisson's ratio. - */ - virtual void SetMaterial_Properties(unsigned short iVal, su2double val_E, su2double val_Nu); - - /*! - * \brief A virtual member to set the material properties - * \param[in] iVal - Index of the region of concern - * \param[in] val_Rho - Value of the density (inertial effects). - * \param[in] val_Rho_DL - Value of the density (dead load effects). - */ - virtual void SetMaterial_Density(unsigned short iVal, su2double val_Rho, su2double val_Rho_DL); - - /*! - * \brief A virtual member to compute the mass matrix - * \param[in] element_container - Element structure for the particular element integrated. - */ - virtual void Compute_Mass_Matrix(CElement *element_container, CConfig *config); - - /*! - * \brief A virtual member to compute the residual component due to dead loads - * \param[in] element_container - Element structure for the particular element integrated. - */ - virtual void Compute_Dead_Load(CElement *element_container, CConfig *config); - - /*! - * \brief A virtual member to compute the averaged nodal stresses - * \param[in] element_container - Element structure for the particular element integrated. - */ - virtual void Compute_Averaged_NodalStress(CElement *element_container, CConfig *config); - - /*! - * \brief Computes a basis of orthogonal vectors from a suppled vector - * \param[in] config - Normal vector - */ - void CreateBasis(su2double *val_Normal); - - /*! - * \brief Set the value of the Tauwall - * \param[in] val_tauwall_i - Tauwall at point i - * \param[in] val_tauwall_j - Tauwall at point j - */ - virtual void SetTauWall(su2double val_tauwall_i, su2double val_tauwall_j); - - /*! - * \brief - Calculate the central/upwind blending function for a face - * - * At its simplest level, this function will calculate the average - * value of the "Roe dissipation" or central/upwind blending function - * at a face. If Ducros shock sensors are used, then this method will - * also adjust the central/upwind blending to account for shocks. - * - * \param[in] Dissipation_i - Value of the blending function at point i - * \param[in] Dissipation_j - Value of the bledning function at point j - * \param[in] Sensor_i - Shock sensor at point i - * \param[in] Sensor_j - Shock sensor at point j - * \param[out] Dissipation_ij - Blending parameter at face - */ - void SetRoe_Dissipation(const su2double Dissipation_i, - const su2double Dissipation_j, - const su2double Sensor_i, const su2double Sensor_j, - su2double& Dissipation_ij, CConfig *config); - - /*! - * \brief Setting the UQ framework usage - * \param[in] val_using_uq - */ - void SetUsing_UQ(bool val_using_uq); - - /*! - * \brief Decomposes the symmetric matrix A_ij, into eigenvectors and eigenvalues - * \param[in] A_i: symmetric matrix to be decomposed - * \param[in] Eig_Vec: strores the eigenvectors - * \param[in] Eig_Val: stores the eigenvalues - * \param[in] n: order of matrix A_ij - */ - static void EigenDecomposition(su2double **A_ij, su2double **Eig_Vec, su2double *Eig_Val, unsigned short n); - - /*! - * \brief Recomposes the eigenvectors and eigenvalues into a matrix - * \param[in] A_ij: recomposed matrix - * \param[in] Eig_Vec: eigenvectors - * \param[in] Eig_Val: eigenvalues - * \param[in] n: order of matrix A_ij - */ - static void EigenRecomposition(su2double **A_ij, su2double **Eig_Vec, su2double *Eig_Val, unsigned short n); - - /*! - * \brief tred2 - * \param[in] V: matrix that needs to be decomposed - * \param[in] d: holds eigenvalues - * \param[in] e: supplemental data structure - * \param[in] n: order of matrix V - */ - static void tred2(su2double **V, su2double *d, su2double *e, unsigned short n); - - /*! - * \brief tql2 - * \param[in] V: matrix that will hold the eigenvectors - * \param[in] d: array that will hold the ordered eigenvalues - * \param[in] e: supplemental data structure - * \param[in] n: order of matrix V - - */ - static void tql2(su2double **V, su2double *d, su2double *e, unsigned short n); - -}; - -/*! - * \class CUpwCUSP_Flow - * \brief Class for centered scheme - CUSP. - * \ingroup ConvDiscr - * \author F. Palacios - */ -class CUpwCUSP_Flow : public CNumerics { - -private: - su2double *Velocity_i, *Velocity_j, *ProjFlux_i, *ProjFlux_j; - bool implicit; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwCUSP_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwCUSP_Flow(void); - - /*! - * \brief Compute the flow residual using a JST method. - * \param[out] val_residual - Pointer to the residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, - CConfig *config); -}; - -/*! - * \class CUpwRoeBase_Flow - * \brief Intermediate base class for Roe schemes on ideal gas. - * \ingroup ConvDiscr - * \author A. Bueno, F. Palacios - */ -class CUpwRoeBase_Flow : public CNumerics { -protected: - bool implicit, dynamic_grid, roe_low_dissipation; - su2double *Velocity_i, *Velocity_j, *ProjFlux_i, *ProjFlux_j, *Conservatives_i, *Conservatives_j; - su2double *Diff_U, *Lambda, **P_Tensor, **invP_Tensor; - su2double *RoeVelocity, RoeDensity, RoeEnthalpy, RoeSoundSpeed, ProjVelocity, RoeSoundSpeed2, kappa; - - /*! - * \brief Derived classes must specialize this method to add the specifics of the scheme they implement (e.g. low-Mach precond.). - * \param[out] val_residual - Convective flux. - * \param[out] val_Jacobian_i - Flux Jacobian wrt node i conservatives (implicit computation). - * \param[out] val_Jacobian_j - Flux Jacobian wrt node j conservatives (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - virtual void FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) = 0; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - * \param[in] val_low_dissipation - Use a low dissipation formulation. - */ - CUpwRoeBase_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config, bool val_low_dissipation); - - /*! - * \brief Destructor of the class. - */ - ~CUpwRoeBase_Flow(void); - - /*! - * \brief Compute the flux from node i to node j, part common to most Roe schemes. - * \param[out] val_residual - Convective flux. - * \param[out] val_Jacobian_i - Flux Jacobian wrt node i conservatives (implicit computation). - * \param[out] val_Jacobian_j - Flux Jacobian wrt node j conservatives (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - -}; - -/*! - * \class CUpwRoe_Flow - * \brief Class for solving an approximate Riemann solver of Roe for the flow equations. - * \ingroup ConvDiscr - * \author A. Bueno, F. Palacios - */ -class CUpwRoe_Flow : public CUpwRoeBase_Flow { -private: - /*! - * \brief Add standard Roe dissipation to the flux. - * \param[out] val_residual - Convective flux. - * \param[out] val_Jacobian_i - Flux Jacobian wrt node i conservatives (implicit computation). - * \param[out] val_Jacobian_j - Flux Jacobian wrt node j conservatives (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - * \param[in] val_low_dissipation - Use a low dissipation formulation. - */ - CUpwRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config, bool val_low_dissipation); - - /*! - * \brief Destructor of the class. - */ - ~CUpwRoe_Flow(void); - -}; - - -/*! - * \class CUpwGeneralRoe_Flow - * \brief Class for solving an approximate Riemann solver of Roe for the flow equations for a general fluid model. - * \ingroup ConvDiscr - * \author S.Vitale, G.Gori, M.Pini - */ -class CUpwGeneralRoe_Flow : public CNumerics { -private: - - bool implicit, dynamic_grid; - - su2double *Diff_U; - su2double *Velocity_i, *Velocity_j, *RoeVelocity; - su2double *ProjFlux_i, *ProjFlux_j; - su2double *delta_wave, *delta_vel; - su2double *Lambda, *Epsilon, MaxLambda, Delta; - su2double **P_Tensor, **invP_Tensor; - su2double sq_vel, Proj_ModJac_Tensor_ij, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, - - Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, R, RoeDensity, RoeEnthalpy, RoeSoundSpeed, RoeSoundSpeed2, - ProjVelocity, ProjVelocity_i, ProjVelocity_j, proj_delta_vel, delta_p, delta_rho, kappa; - unsigned short iDim, iVar, jVar, kVar; - - - su2double StaticEnthalpy_i, StaticEnergy_i, StaticEnthalpy_j, StaticEnergy_j, Kappa_i, Kappa_j, Chi_i, Chi_j, Velocity2_i, Velocity2_j; - su2double RoeKappa, RoeChi; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwGeneralRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwGeneralRoe_Flow(void); - - /*! - * \brief Compute the Roe's flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \brief Compute the Average for a general fluid flux between two nodes i and j. - * Using the approach of Vinokur and Montagne' - */ - - void ComputeRoeAverage(); -}; - -/*! - * \class CUpwL2Roe_Flow - * \brief Class for solving an approximate Riemann solver of L2Roe for the flow equations. - * \ingroup ConvDiscr - * \author E. Molina, A. Bueno, F. Palacios - * \version 7.0.1 "Blackbird" - */ -class CUpwL2Roe_Flow : public CUpwRoeBase_Flow { -private: - /*! - * \brief Add L^2 Roe dissipation to the flux (low-Mach scheme). - * \param[out] val_residual - Convective flux. - * \param[out] val_Jacobian_i - Flux Jacobian wrt node i conservatives (implicit computation). - * \param[out] val_Jacobian_j - Flux Jacobian wrt node j conservatives (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - -public: - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwL2Roe_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwL2Roe_Flow(void); -}; - -/*! - * \class CUpwLMRoe_Flow - * \brief Class for solving an approximate Riemann solver of LMRoe for the flow equations. - * \ingroup ConvDiscr - * \author E. Molina, A. Bueno, F. Palacios - * \version 7.0.1 "Blackbird" - */ -class CUpwLMRoe_Flow : public CUpwRoeBase_Flow { -private: - /*! - * \brief Add LMRoe dissipation to the flux (low-Mach scheme). - * \param[out] val_residual - Convective flux. - * \param[out] val_Jacobian_i - Flux Jacobian wrt node i conservatives (implicit computation). - * \param[out] val_Jacobian_j - Flux Jacobian wrt node j conservatives (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - -public: - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwLMRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwLMRoe_Flow(void); -}; - -/*! - * \class CUpwMSW_Flow - * \brief Class for solving a flux-vector splitting method by Steger & Warming, modified version. - * \ingroup ConvDiscr - * \author S. Copeland - */ -class CUpwMSW_Flow : public CNumerics { -private: - bool implicit; - su2double *Diff_U; - su2double *u_i, *u_j, *ust_i, *ust_j; - su2double *Fc_i, *Fc_j; - su2double *Lambda_i, *Lambda_j; - su2double rhos_i, rhos_j; - su2double *Ust_i, *Ust_j, *Vst_i, *Vst_j, *Velst_i, *Velst_j; - su2double **P_Tensor, **invP_Tensor; - unsigned short nPrimVar, nVar, nDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwMSW_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwMSW_Flow(void); - - /*! - * \brief Compute the Roe's flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - -}; - -/*! - * \class CUpwTurkel_Flow - * \brief Class for solving an approximate Riemann solver of Roe with Turkel Preconditioning for the flow equations. - * \ingroup ConvDiscr - * \author A. K. Lonkar - */ -class CUpwTurkel_Flow : public CNumerics { -private: - bool implicit, dynamic_grid; - su2double *Diff_U; - su2double *Velocity_i, *Velocity_j, *RoeVelocity; - su2double *ProjFlux_i, *ProjFlux_j; - su2double *Lambda, *Epsilon; - su2double **absPeJac, **invRinvPe, **R_Tensor, **Matrix, **Art_Visc; - su2double sq_vel, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, - Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, R, RoePressure, RoeDensity, RoeEnthalpy, RoeSoundSpeed, - ProjVelocity, ProjVelocity_i, ProjVelocity_j; - unsigned short iDim, iVar, jVar, kVar; - su2double Beta, Beta_min, Beta_max; - su2double r_hat, s_hat, t_hat, rhoB2a2, sqr_one_m_Betasqr_Lam1; - su2double Beta2, one_m_Betasqr, one_p_Betasqr, sqr_two_Beta_c_Area; - su2double local_Mach; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwTurkel_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwTurkel_Flow(void); - - /*! - * \brief Compute the Roe's flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - -}; - -/*! - * \class CUpwFDSInc_Flow - * \brief Class for solving a Flux Difference Splitting (FDS) upwind method for the incompressible flow equations. - * \ingroup ConvDiscr - * \author F. Palacios, T. Economon - */ -class CUpwFDSInc_Flow : public CNumerics { -private: - bool implicit, /*!< \brief Implicit calculation. */ - dynamic_grid, /*!< \brief Modification for grid movement. */ - variable_density, /*!< \brief Variable density incompressible flows. */ - energy; /*!< \brief computation with the energy equation. */ - su2double *Diff_V; - su2double *Velocity_i, *Velocity_j, *MeanVelocity; - su2double *ProjFlux_i, *ProjFlux_j; - su2double *Lambda, *Epsilon; - su2double **Precon, **invPrecon_A; - su2double Proj_ModJac_Tensor_ij, Pressure_i, - Pressure_j, ProjVelocity, - MeandRhodT, dRhodT_i, dRhodT_j, /*!< \brief Derivative of density w.r.t. temperature (variable density flows). */ - Temperature_i, Temperature_j, /*!< \brief Temperature at node 0 and 1. */ - MeanDensity, MeanPressure, MeanSoundSpeed, MeanBetaInc2, MeanEnthalpy, MeanCp, MeanTemperature; /*!< \brief Mean values of primitive variables. */ - unsigned short iDim, iVar, jVar, kVar; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwFDSInc_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwFDSInc_Flow(void); - - /*! - * \brief Compute the upwind flux between two nodes i and j. - * \param[out] val_residual - Pointer to the residual array. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, - CConfig *config); -}; - -/*! - * \class CUpwRoe_AdjFlow - * \brief Class for solving an approximate Riemann solver of Roe - * for the adjoint flow equations. - * \ingroup ConvDiscr - * \author F. Palacios - */ -class CUpwRoe_AdjFlow : public CNumerics { -private: - su2double *Residual_Roe; - su2double area, Sx, Sy, Sz, rarea, nx, ny, nz, rho_l, u_l, v_l, w_l, h_l, rho_r, - u_r, v_r, w_r, h_r, psi1, psi2, psi3, psi4, psi5; - su2double h, u, v, w, c, psi1_l, psi2_l, psi3_l, psi4_l, psi5_l, - psi1_r, psi2_r, psi3_r, psi4_r, psi5_r, q_l, q_r, Q_l, Q_r, vn, - rrho_l, weight, rweight1, cc; - su2double l1psi, l2psi, absQ, absQp, absQm, q2, alpha, beta_u, beta_v, beta_w, Q, l1l2p, l1l2m, eta; - su2double RoeDensity, RoeSoundSpeed, *RoeVelocity, *Lambda, *Velocity_i, *Velocity_j, **ProjFlux_i, **ProjFlux_j, - Proj_ModJac_Tensor_ij, **Proj_ModJac_Tensor, Energy_i, Energy_j, **P_Tensor, **invP_Tensor; - unsigned short iDim, iVar, jVar, kVar; - bool implicit, grid_movement; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwRoe_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwRoe_AdjFlow(void); - - /*! - * \brief Compute the adjoint Roe's flux between two nodes i and j. - * \param[out] val_residual_i - Pointer to the total residual at point i. - * \param[out] val_residual_j - Pointer to the total residual at point j. - * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. - * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. - * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. - * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, - su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); -}; - -/*! - * \class CUpwAUSM_Flow - * \brief Class for solving an approximate Riemann AUSM. - * \ingroup ConvDiscr - * \author F. Palacios - */ -class CUpwAUSM_Flow : public CNumerics { -private: - bool implicit; - su2double *Diff_U; - su2double *Velocity_i, *Velocity_j, *RoeVelocity; - su2double *ProjFlux_i, *ProjFlux_j; - su2double *delta_wave, *delta_vel; - su2double *Lambda, *Epsilon; - su2double **P_Tensor, **invP_Tensor; - su2double sq_vel, Proj_ModJac_Tensor_ij, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, - Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, R, RoeDensity, RoeEnthalpy, RoeSoundSpeed, - ProjVelocity, ProjVelocity_i, ProjVelocity_j; - unsigned short iDim, iVar, jVar, kVar; - su2double mL, mR, mLP, mRM, mF, pLP, pRM, pF, Phi; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwAUSM_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwAUSM_Flow(void); - - /*! - * \brief Compute the Roe's flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CUpwAUSMPLUS_SLAU_Base_Flow - * \brief Base class for AUSM+up(2) and SLAU(2) convective schemes. - * \ingroup ConvDiscr - * \author Amit Sachdeva - */ -class CUpwAUSMPLUS_SLAU_Base_Flow : public CNumerics { -protected: - bool implicit; - bool UseAccurateJacobian; - bool HasAnalyticalDerivatives; - su2double FinDiffStep; - - su2double MassFlux, DissFlux, Pressure; - su2double *Velocity_i, *Velocity_j; - su2double *psi_i, *psi_j; - su2double dmdot_dVi[6], dmdot_dVj[6], dpres_dVi[6], dpres_dVj[6]; - - /*--- Roe variables (for approximate Jacobian) ---*/ - su2double *Lambda, *Epsilon, *RoeVelocity, **P_Tensor, **invP_Tensor; - - /*! - * \brief Compute the mass flux and pressure based on Primitives_i/j, derived classes must implement this method. - * \note See the body of the (empty) default implementation for instructions on how to implement the method. - * \param[in] config - Definition of the particular problem. - * \param[out] mdot - The mass flux. - * \param[out] pressure - The pressure at the control volume face. - */ - virtual void ComputeMassAndPressureFluxes(CConfig *config, su2double &mdot, su2double &pressure) = 0; - - /*! - * \brief Compute the flux Jacobians of the Roe scheme to use as an approximation. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - */ - void ApproximateJacobian(su2double **val_Jacobian_i, su2double **val_Jacobian_j); - - /*! - * \brief Compute the flux Jacobians using a mix of finite differences and manual differentiation. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - */ - void AccurateJacobian(CConfig *config, su2double **val_Jacobian_i, su2double **val_Jacobian_j); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwAUSMPLUS_SLAU_Base_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwAUSMPLUS_SLAU_Base_Flow(void); - - /*! - * \brief Compute the AUSM+ and SLAU family of schemes. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CUpwAUSMPLUSUP_Flow - * \brief Class for solving an approximate Riemann AUSM+ -up. - * \ingroup ConvDiscr - * \author Amit Sachdeva - */ -class CUpwAUSMPLUSUP_Flow : public CUpwAUSMPLUS_SLAU_Base_Flow { -private: - su2double Kp, Ku, sigma; - - /*! - * \brief Mass flux and pressure for the AUSM+up scheme. - * \param[in] config - Definition of the particular problem. - * \param[out] mdot - The mass flux. - * \param[out] pressure - The pressure at the control volume face. - */ - void ComputeMassAndPressureFluxes(CConfig *config, su2double &mdot, su2double &pressure); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwAUSMPLUSUP_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwAUSMPLUSUP_Flow(void); -}; - -/*! - * \class CUpwAUSMPLUSUP2_Flow - * \brief Class for solving an approximate Riemann AUSM+ -up. - * \ingroup ConvDiscr - * \author Amit Sachdeva - */ -class CUpwAUSMPLUSUP2_Flow : public CUpwAUSMPLUS_SLAU_Base_Flow { -private: - su2double Kp, sigma; - - /*! - * \brief Mass flux and pressure for the AUSM+up2 scheme. - * \param[in] config - Definition of the particular problem. - * \param[out] mdot - The mass flux. - * \param[out] pressure - The pressure at the control volume face. - */ - void ComputeMassAndPressureFluxes(CConfig *config, su2double &mdot, su2double &pressure); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwAUSMPLUSUP2_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwAUSMPLUSUP2_Flow(void); - -}; - -/*! - * \class CUpwSLAU_Flow - * \brief Class for solving the Low-Dissipation AUSM. - * \ingroup ConvDiscr - * \author E. Molina - */ -class CUpwSLAU_Flow : public CUpwAUSMPLUS_SLAU_Base_Flow { -protected: - bool slau_low_diss; - bool slau2; - - /*! - * \brief Mass flux and pressure for the SLAU and SLAU2 schemes. - * \param[in] config - Definition of the particular problem. - * \param[out] mdot - The mass flux. - * \param[out] pressure - The pressure at the control volume face. - */ - void ComputeMassAndPressureFluxes(CConfig *config, su2double &mdot, su2double &pressure); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwSLAU_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config, bool val_low_dissipation); - - /*! - * \brief Destructor of the class. - */ - ~CUpwSLAU_Flow(void); - -}; - -/*! - * \class CUpwSLAU2_Flow - * \brief Class for solving the Simple Low-Dissipation AUSM 2. - * \ingroup ConvDiscr - * \author E. Molina - */ -class CUpwSLAU2_Flow : public CUpwSLAU_Flow { -public: - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwSLAU2_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config, bool val_low_dissipation); - - /*! - * \brief Destructor of the class. - */ - ~CUpwSLAU2_Flow(void); - -}; - -/*! - * \class CUpwHLLC_Flow - * \brief Class for solving an approximate Riemann HLLC. - * \ingroup ConvDiscr - * \author G. Gori, Politecnico di Milano - * \version 7.0.1 "Blackbird" - */ -class CUpwHLLC_Flow : public CNumerics { -private: - bool implicit, dynamic_grid; - unsigned short iDim, jDim, iVar, jVar; - - su2double *IntermediateState; - su2double *Velocity_i, *Velocity_j, *RoeVelocity; - - su2double sq_vel_i, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, ProjVelocity_i; - su2double sq_vel_j, Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, ProjVelocity_j; - - su2double sq_velRoe, RoeDensity, RoeEnthalpy, RoeSoundSpeed, RoeProjVelocity, ProjInterfaceVel; - - su2double sL, sR, sM, pStar, EStar, rhoSL, rhoSR, Rrho, kappa; - - su2double Omega, RHO, OmegaSM; - su2double *dSm_dU, *dPI_dU, *drhoStar_dU, *dpStar_dU, *dEStar_dU; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwHLLC_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwHLLC_Flow(void); - - /*! - * \brief Compute the Roe's flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - -}; - -/*! - * \class CUpwGeneralHLLC_Flow - * \brief Class for solving an approximate Riemann HLLC. - * \ingroup ConvDiscr - * \author G. Gori, Politecnico di Milano - * \version 7.0.1 "Blackbird" - */ -class CUpwGeneralHLLC_Flow : public CNumerics { -private: - bool implicit, dynamic_grid; - unsigned short iDim, jDim, iVar, jVar; - - su2double *IntermediateState; - su2double *Velocity_i, *Velocity_j, *RoeVelocity; - - su2double sq_vel_i, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, ProjVelocity_i, StaticEnthalpy_i, StaticEnergy_i; - su2double sq_vel_j, Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, ProjVelocity_j, StaticEnthalpy_j, StaticEnergy_j; - - su2double sq_velRoe, RoeDensity, RoeEnthalpy, RoeSoundSpeed, RoeProjVelocity, ProjInterfaceVel; - su2double Kappa_i, Kappa_j, Chi_i, Chi_j, RoeKappa, RoeChi, RoeKappaStaticEnthalpy; - - su2double sL, sR, sM, pStar, EStar, rhoSL, rhoSR, Rrho, kappa; - - su2double Omega, RHO, OmegaSM; - su2double *dSm_dU, *dPI_dU, *drhoStar_dU, *dpStar_dU, *dEStar_dU; - - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwGeneralHLLC_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwGeneralHLLC_Flow(void); - - /*! - - * \brief Compute the Roe's flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \brief Compute the Average quantities for a general fluid flux between two nodes i and j. - * Using the approach of Vinokur and Montagne' - */ - void VinokurMontagne(); -}; - -/*! - * \class CUpwLin_TransLM - * \brief Class for performing a linear upwind solver for the Spalart-Allmaras turbulence model equations with transition - * \ingroup ConvDiscr - * \author A. Aranake - */ -class CUpwLin_TransLM : public CNumerics { -private: - su2double *Velocity_i; - su2double *Velocity_j; - bool implicit, incompressible; - su2double Density_i, Density_j, q_ij, a0, a1; - unsigned short iDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwLin_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwLin_TransLM(void); - - /*! - * \brief Compute the upwind flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual (su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CUpwLin_AdjTurb - * \brief Class for performing a linear upwind solver for the adjoint turbulence equations. - * \ingroup ConvDiscr - * \author A. Bueno. - */ -class CUpwLin_AdjTurb : public CNumerics { -private: - su2double *Velocity_i; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwLin_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwLin_AdjTurb(void); - - /*! - * \brief Compute the adjoint upwind flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual (su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CUpwScalar - * \brief Template class for scalar upwind fluxes between nodes i and j. - * \details This class serves as a template for the scalar upwinding residual - * classes. The general structure of a scalar upwinding calculation is the - * same for many different models, which leads to a lot of repeated code. - * By using the template design pattern, these sections of repeated code are - * moved to this shared base class, and the specifics of each model - * are implemented by derived classes. In order to add a new residual - * calculation for a convection residual, extend this class and implement - * the pure virtual functions with model-specific behavior. - * \ingroup ConvDiscr - * \author C. Pederson, A. Bueno., and A. Campos. - */ -class CUpwScalar : public CNumerics { -private: - - /*! - * \brief A pure virtual function; Adds any extra variables to AD - */ - virtual void ExtraADPreaccIn() = 0; - - /*! - * \brief Model-specific steps in the ComputeResidual method - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - virtual void FinishResidualCalc(su2double *val_residual, - su2double **Jacobian_i, - su2double **Jacobian_j, - CConfig *config) = 0; - -protected: - su2double *Velocity_i, *Velocity_j; /*!< \brief Velocity, minus any grid movement. */ - su2double Density_i, Density_j; - bool implicit, dynamic_grid, incompressible; - su2double q_ij, /*!< \brief Projected velocity at the face. */ - a0, /*!< \brief The maximum of the face-normal velocity and 0 */ - a1; /*!< \brief The minimum of the face-normal velocity and 0 */ - unsigned short iDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwScalar(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwScalar(void); - - /*! - * \brief Compute the scalar upwind flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CUpwSca_TurbSA - * \brief Class for doing a scalar upwind solver for the Spalar-Allmaras turbulence model equations. - * \ingroup ConvDiscr - * \author A. Bueno. - */ -class CUpwSca_TurbSA : public CUpwScalar { -private: - - /*! - * \brief Adds any extra variables to AD - */ - void ExtraADPreaccIn(); - - /*! - * \brief SA specific steps in the ComputeResidual method - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void FinishResidualCalc(su2double *val_residual, su2double **Jacobian_i, - su2double **Jacobian_j, CConfig *config); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwSca_TurbSA(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwSca_TurbSA(void); -}; - -/*! - * \class CUpwSca_TurbSST - * \brief Class for doing a scalar upwind solver for the Menter SST turbulence model equations. - * \ingroup ConvDiscr - * \author A. Campos. - */ -class CUpwSca_TurbSST : public CUpwScalar { -private: - - /*! - * \brief Adds any extra variables to AD - */ - void ExtraADPreaccIn(); - - /*! - * \brief SST specific steps in the ComputeResidual method - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void FinishResidualCalc(su2double *val_residual, su2double **Jacobian_i, - su2double **Jacobian_j, CConfig *config); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwSca_TurbSST(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwSca_TurbSST(void); -}; - -/*! - * \class CUpwSca_TransLM - * \brief Class for doing a scalar upwind solver for the Spalart-Allmaras turbulence model equations with transition. - * \ingroup ConvDiscr - * \author A. Aranake. - */ -class CUpwSca_TransLM : public CNumerics { -private: - su2double *Velocity_i, *Velocity_j; - bool implicit; - su2double q_ij, a0, a1; - unsigned short iDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwSca_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwSca_TransLM(void); - - /*! - * \brief Compute the scalar upwind flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CUpwSca_AdjTurb - * \brief Class for doing a scalar upwind solver for the adjoint turbulence equations. - * \ingroup ConvDiscr - * \author A. Bueno. - */ -class CUpwSca_AdjTurb : public CNumerics { -private: - su2double *Velocity_i, *Velocity_j; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwSca_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwSca_AdjTurb(void); - - /*! - * \param[out] val_residual_i - Pointer to the total residual at point i. - * \param[out] val_residual_j - Pointer to the total viscosity residual at point j. - * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. - * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. - * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. - * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); -}; - -/*! - * \class CUpwSca_Heat - * \brief Class for doing a scalar upwind solver for the heat convection equation. - * \ingroup ConvDiscr - * \author O. Burghardt. - * \version 7.0.1 "Blackbird" - */ -class CUpwSca_Heat : public CNumerics { -private: - su2double *Velocity_i, *Velocity_j; - bool implicit, dynamic_grid; - su2double q_ij, a0, a1; - unsigned short iDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CUpwSca_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CUpwSca_Heat(void); - - /*! - * \brief Compute the scalar upwind flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CCentBase_Flow - * \brief Intermediate class to define centered schemes. - * \ingroup ConvDiscr - * \author F. Palacios - */ -class CCentBase_Flow : public CNumerics { - -protected: - unsigned short iDim, iVar, jVar; /*!< \brief Iteration on dimension and variables. */ - bool dynamic_grid; /*!< \brief Consider grid movement. */ - bool implicit; /*!< \brief Implicit calculation (compute Jacobians). */ - su2double fix_factor; /*!< \brief Fix factor for dissipation Jacobians (more diagonal dominance). */ - - su2double *Velocity_i, *Velocity_j, *MeanVelocity; /*!< \brief Velocity at nodes i and j and mean. */ - su2double ProjVelocity_i, ProjVelocity_j; /*!< \brief Velocities in the face normal direction. */ - su2double sq_vel_i, sq_vel_j; /*!< \brief Squared norm of the velocity vectors. */ - su2double Energy_i, Energy_j, MeanEnergy; /*!< \brief Energy at nodes i and j and mean. */ - su2double MeanDensity, MeanPressure, MeanEnthalpy; /*!< \brief Mean density, pressure, and enthalpy. */ - su2double *ProjFlux; /*!< \brief Projected inviscid flux. */ - - su2double *Diff_U, *Diff_Lapl; /*!< \brief Differences of conservatives and undiv. Laplacians. */ - su2double Local_Lambda_i, Local_Lambda_j, MeanLambda; /*!< \brief Local eingenvalues. */ - su2double Param_p, Phi_i, Phi_j, StretchingFactor; /*!< \brief Streching parameters. */ - su2double cte_0, cte_1; /*!< \brief Constants for the scalar dissipation Jacobian. */ - - su2double ProjGridVel; /*!< \brief Projected grid velocity. */ - - /*! - * \brief Hook method for derived classes to define preaccumulated variables, optional to implement. - * \return true if any variable was set as preacc. input, in which case the residual will be output. - */ - virtual bool SetPreaccInVars(void) {return false;} - - /*! - * \brief Derived classes must implement this method, called in ComputeResidual after inviscid part. - * \param[in,out] val_residual - Pointer to the convective flux contribution to the residual. - * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - */ - virtual void DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) = 0; - - /*! - * \brief Add the contribution of a scalar dissipation term to the Jacobians. - * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i. - * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j. - */ - void ScalarDissipationJacobian(su2double **val_Jacobian_i, su2double **val_Jacobian_j); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CCentBase_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - virtual ~CCentBase_Flow(void); - - /*! - * \brief Compute the flow residual using a centered method with artificial dissipation. - * \param[out] val_residual - Pointer to the convective flux contribution to the residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - -}; - -/*! - * \class CCentLax_Flow - * \brief Class for computing the Lax-Friedrich centered scheme. - * \ingroup ConvDiscr - * \author F. Palacios - */ -class CCentLax_Flow : public CCentBase_Flow { -private: - su2double Param_Kappa_0; /*!< \brief Artificial dissipation parameter. */ - su2double sc0; /*!< \brief Streching parameter. */ - su2double Epsilon_0; /*!< \brief Artificial dissipation coefficient. */ - - /*! - * \brief Lax-Friedrich first order dissipation term. - * \param[in,out] val_residual - Pointer to the convective flux contribution to the residual. - * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - */ - void DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j); - - /*! - * \brief Set input variables for AD preaccumulation. - * \return true, as we will define inputs. - */ - bool SetPreaccInVars(void); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CCentLax_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CCentLax_Flow(void); - -}; - -/*! - * \class CCentJST_KE_Flow - * \brief Class for centered scheme - JST_KE (no 4th dissipation order term). - * \ingroup ConvDiscr - * \author F. Palacios - */ -class CCentJST_KE_Flow : public CCentBase_Flow { - -private: - su2double Param_Kappa_2; /*!< \brief Artificial dissipation parameter. */ - su2double sc2; /*!< \brief Streching parameter. */ - su2double Epsilon_2; /*!< \brief Artificial dissipation coefficient. */ - - /*! - * \brief JST_KE second order dissipation term. - * \param[in,out] val_residual - Pointer to the convective flux contribution to the residual. - * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - */ - void DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j); - - /*! - * \brief Set input variables for AD preaccumulation. - * \return true, as we will define inputs. - */ - bool SetPreaccInVars(void); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CCentJST_KE_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CCentJST_KE_Flow(void); - -}; - -/*! - * \class CCentJST_Flow - * \brief Class for centered scheme - JST. - * \ingroup ConvDiscr - * \author F. Palacios - */ -class CCentJST_Flow : public CCentBase_Flow { - -private: - su2double Param_Kappa_2, Param_Kappa_4; /*!< \brief Artificial dissipation parameters. */ - su2double sc2, sc4; /*!< \brief Streching parameters. */ - su2double Epsilon_2, Epsilon_4; /*!< \brief Artificial dissipation coefficients. */ - - /*! - * \brief JST second and forth order dissipation terms. - * \param[in,out] val_residual - Pointer to the convective flux contribution to the residual. - * \param[in,out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in,out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - */ - void DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j); - - /*! - * \brief Set input variables for AD preaccumulation. - * \return true, as we will define inputs. - */ - bool SetPreaccInVars(void); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CCentJST_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CCentJST_Flow(void); - -}; - -/*! - * \class CCentJSTInc_Flow - * \brief Class for centered scheme - modified JST with incompressible preconditioning. - * \ingroup ConvDiscr - * \author F. Palacios, T. Economon - */ -class CCentJSTInc_Flow : public CNumerics { - -private: - unsigned short iDim, iVar, jVar; /*!< \brief Iteration on dimension and variables. */ - su2double *Diff_V, *Diff_Lapl, /*!< \brief Diference of primitive variables and undivided laplacians. */ - *Velocity_i, *Velocity_j, /*!< \brief Velocity at node 0 and 1. */ - *MeanVelocity, ProjVelocity_i, - ProjVelocity_j, /*!< \brief Mean and projected velocities. */ - sq_vel_i, sq_vel_j, /*!< \brief Modulus of the velocity and the normal vector. */ - Temperature_i, Temperature_j, /*!< \brief Temperature at node 0 and 1. */ - MeanDensity, MeanPressure, - MeanBetaInc2, MeanEnthalpy, - MeanCp, MeanTemperature, /*!< \brief Mean values of primitive variables. */ - MeandRhodT, /*!< \brief Derivative of density w.r.t. temperature (variable density flows). */ - Param_p, Param_Kappa_2, - Param_Kappa_4, /*!< \brief Artificial dissipation parameters. */ - Local_Lambda_i, Local_Lambda_j, - MeanLambda, /*!< \brief Local eingenvalues. */ - Phi_i, Phi_j, sc2, sc4, - StretchingFactor, /*!< \brief Streching parameters. */ - *ProjFlux, /*!< \brief Projected inviscid flux tensor. */ - Epsilon_2, Epsilon_4; /*!< \brief Artificial dissipation values. */ - su2double **Precon; - bool implicit, /*!< \brief Implicit calculation. */ - dynamic_grid, /*!< \brief Modification for grid movement. */ - variable_density, /*!< \brief Variable density incompressible flows. */ - energy; /*!< \brief computation with the energy equation. */ - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CCentJSTInc_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CCentJSTInc_Flow(void); - - /*! - * \brief Compute the flow residual using a JST method. - * \param[out] val_residual - Pointer to the residual array. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CCentJST_AdjFlow - * \brief Class for and adjoint centered scheme - JST. - * \ingroup ConvDiscr - * \author F. Palacios - */ -class CCentJST_AdjFlow : public CNumerics { -private: - su2double *Diff_Psi, *Diff_Lapl; - su2double *Velocity_i, *Velocity_j; - su2double *MeanPhi; - unsigned short iDim, jDim, iVar, jVar; - su2double Residual, ProjVelocity_i, ProjVelocity_j, ProjPhi, ProjPhi_Vel, sq_vel, phis1, phis2; - su2double MeanPsiRho, MeanPsiE, Param_p, Param_Kappa_4, Param_Kappa_2, Local_Lambda_i, Local_Lambda_j, MeanLambda; - su2double Phi_i, Phi_j, sc4, StretchingFactor, Epsilon_4, Epsilon_2; - bool implicit, grid_movement; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CCentJST_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CCentJST_AdjFlow(void); - - /*! - * \brief Compute the adjoint flow residual using a JST method. - * \param[out] val_resconv_i - Pointer to the convective residual at point i. - * \param[out] val_resvisc_i - Pointer to the artificial viscosity residual at point i. - * \param[out] val_resconv_j - Pointer to the convective residual at point j. - * \param[out] val_resvisc_j - Pointer to the artificial viscosity residual at point j. - * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. - * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. - * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. - * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual (su2double *val_resconv_i, su2double *val_resvisc_i, su2double *val_resconv_j, su2double *val_resvisc_j, - su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, - CConfig *config); -}; - -/*! - * \class CCentSca_Heat - * \brief Class for scalar centered scheme. - * \ingroup ConvDiscr - * \author O. Burghardt - * \version 7.0.1 "Blackbird" - */ -class CCentSca_Heat : public CNumerics { - -private: - unsigned short iDim; /*!< \brief Iteration on dimension and variables. */ - su2double *Diff_Lapl, /*!< \brief Diference of conservative variables and undivided laplacians. */ - *MeanVelocity, ProjVelocity, - ProjVelocity_i, ProjVelocity_j, /*!< \brief Mean and projected velocities. */ - Param_Kappa_4, /*!< \brief Artificial dissipation parameters. */ - Local_Lambda_i, Local_Lambda_j, - MeanLambda, /*!< \brief Local eingenvalues. */ - cte_0, cte_1; /*!< \brief Artificial dissipation values. */ - bool implicit, /*!< \brief Implicit calculation. */ - dynamic_grid; /*!< \brief Modification for grid movement. */ - - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CCentSca_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CCentSca_Heat(void); - - /*! - * \brief Compute the flow residual using a JST method. - * \param[out] val_resconv - Pointer to the convective residual. - * \param[out] val_resvisc - Pointer to the artificial viscosity residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, - CConfig *config); -}; - -/*! - * \class CCentLaxInc_Flow - * \brief Class for computing the Lax-Friedrich centered scheme (modified with incompressible preconditioning). - * \ingroup ConvDiscr - * \author F. Palacios, T. Economon - */ -class CCentLaxInc_Flow : public CNumerics { -private: - unsigned short iDim, iVar, jVar; /*!< \brief Iteration on dimension and variables. */ - su2double *Diff_V, /*!< \brief Difference of primitive variables. */ - *Velocity_i, *Velocity_j, /*!< \brief Velocity at node 0 and 1. */ - *MeanVelocity, ProjVelocity_i, - ProjVelocity_j, /*!< \brief Mean and projected velocities. */ - *ProjFlux, /*!< \brief Projected inviscid flux tensor. */ - sq_vel_i, sq_vel_j, /*!< \brief Modulus of the velocity and the normal vector. */ - Temperature_i, Temperature_j, /*!< \brief Temperature at node 0 and 1. */ - MeanDensity, MeanPressure, - MeanBetaInc2, MeanEnthalpy, - MeanCp, MeanTemperature, /*!< \brief Mean values of primitive variables. */ - MeandRhodT, /*!< \brief Derivative of density w.r.t. temperature (variable density flows). */ - Param_p, Param_Kappa_0, /*!< \brief Artificial dissipation parameters. */ - Local_Lambda_i, Local_Lambda_j, - MeanLambda, /*!< \brief Local eingenvalues. */ - Phi_i, Phi_j, sc0, - StretchingFactor, /*!< \brief Streching parameters. */ - Epsilon_0; /*!< \brief Artificial dissipation values. */ - su2double **Precon; - bool implicit, /*!< \brief Implicit calculation. */ - dynamic_grid, /*!< \brief Modification for grid movement. */ - variable_density, /*!< \brief Variable density incompressible flows. */ - energy; /*!< \brief computation with the energy equation. */ - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CCentLaxInc_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CCentLaxInc_Flow(void); - - /*! - * \brief Compute the flow residual using a Lax method. - * \param[out] val_residual - Pointer to the residual array. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CCentLax_AdjFlow - * \brief Class for computing the Lax-Friedrich adjoint centered scheme. - * \ingroup ConvDiscr - * \author F. Palacios - */ -class CCentLax_AdjFlow : public CNumerics { -private: - su2double *Diff_Psi; - su2double *Velocity_i, *Velocity_j; - su2double *MeanPhi; - unsigned short iDim, jDim, iVar, jVar; - su2double Residual, ProjVelocity_i, ProjVelocity_j, ProjPhi, ProjPhi_Vel, sq_vel, phis1, phis2, - MeanPsiRho, MeanPsiE, Param_p, Param_Kappa_0, Local_Lambda_i, Local_Lambda_j, MeanLambda, - Phi_i, Phi_j, sc2, StretchingFactor, Epsilon_0; - bool implicit, grid_movement; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CCentLax_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CCentLax_AdjFlow(void); - - /*! - * \brief Compute the adjoint flow residual using a Lax method. - * \param[out] val_resconv_i - Pointer to the convective residual at point i. - * \param[out] val_resvisc_i - Pointer to the artificial viscosity residual at point i. - * \param[out] val_resconv_j - Pointer to the convective residual at point j. - * \param[out] val_resvisc_j - Pointer to the artificial viscosity residual at point j. - * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. - * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. - * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. - * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual (su2double *val_resconv_i, su2double *val_resvisc_i, su2double *val_resconv_j, su2double *val_resvisc_j, - su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, - CConfig *config); -}; - - -/*! - * \class CAvgGrad_Base - * \brief A base class for computing viscous terms using an average of gradients. - * \details This is the base class for the numerics classes that compute the - * viscous fluxes for the flow solvers (i.e. compressible or incompressible - * Navier Stokes). The actual numerics classes derive from this class. - * This class is used to share functions and variables that are common to all - * of the flow viscous numerics. For example, the turbulent stress tensor - * is computed identically for all three derived classes. - * \ingroup ViscDiscr - * \author C. Pederson, A. Bueno, F. Palacios, T. Economon - */ -class CAvgGrad_Base : public CNumerics { - protected: - const unsigned short nPrimVar; /*!< \brief The size of the primitive variable array used in the numerics class. */ - const bool correct_gradient; /*!< \brief Apply a correction to the gradient term */ - bool implicit; /*!< \brief Implicit calculus. */ - su2double *heat_flux_vector, /*!< \brief Flux of total energy due to molecular and turbulent diffusion */ - *heat_flux_jac_i, /*!< \brief Jacobian of the molecular + turbulent heat flux vector, projected onto the normal vector. */ - **tau_jacobian_i; /*!< \brief Jacobian of the viscous + turbulent stress tensor, projected onto the normal vector. */ - su2double *Mean_PrimVar, /*!< \brief Mean primitive variables. */ - *PrimVar_i, *PrimVar_j, /*!< \brief Primitives variables at point i and 1. */ - **Mean_GradPrimVar, /*!< \brief Mean value of the gradient. */ - Mean_Laminar_Viscosity, /*!< \brief Mean value of the viscosity. */ - Mean_Eddy_Viscosity, /*!< \brief Mean value of the eddy viscosity. */ - Mean_turb_ke, /*!< \brief Mean value of the turbulent kinetic energy. */ - Mean_TauWall, /*!< \brief Mean wall shear stress (wall functions). */ - TauWall_i, TauWall_j, /*!< \brief Wall shear stress at point i and j (wall functions). */ - dist_ij_2, /*!< \brief Length of the edge and face, squared */ - *Proj_Mean_GradPrimVar_Edge, /*!< \brief Inner product of the Mean gradient and the edge vector. */ - *Edge_Vector; /*!< \brief Vector from point i to point j. */ - - - - /*! - * \brief Add a correction using a Quadratic Constitutive Relation - * - * This function requires that the stress tensor already be - * computed using \ref GetStressTensor - * - * See: Spalart, P. R., "Strategies for Turbulence Modelling and - * Simulation," International Journal of Heat and Fluid Flow, Vol. 21, - * 2000, pp. 252-263 - * - * \param[in] val_gradprimvar - */ - void AddQCR(const su2double* const *val_gradprimvar); - - /*! - * \brief Scale the stress tensor using a predefined wall stress. - * - * This function requires that the stress tensor already be - * computed using \ref GetStressTensor - * - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[in] val_tau_wall - The wall stress - */ - void AddTauWall(const su2double *val_normal, - su2double val_tau_wall); - - /** - * \brief Calculate the Jacobian of the viscous + turbulent stress tensor - * - * This function is intended only for the compressible flow solver. - * This Jacobian is projected onto the normal vector, so it is of dimension - * [nDim][nVar] - * - * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. - * \param[in] val_laminar_viscosity - Value of the laminar viscosity. - * \param[in] val_eddy_viscosity - Value of the eddy viscosity. - * \param[in] val_dist_ij - Distance between the points. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - */ - void SetTauJacobian(const su2double* val_Mean_PrimVar, - su2double val_laminar_viscosity, - su2double val_eddy_viscosity, - su2double val_dist_ij, - const su2double *val_normal); - - - /** - * \brief Calculate the Jacobian of the viscous and turbulent stress tensor - * - * This function is intended only for the incompressible flow solver. - * This Jacobian is projected onto the normal vector, so it is of dimension - * [nDim][nVar] - * - * \param[in] val_laminar_viscosity - Value of the laminar viscosity. - * \param[in] val_eddy_viscosity - Value of the eddy viscosity. - * \param[in] val_dist_ij - Distance between the points. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - */ - void SetIncTauJacobian(su2double val_laminar_viscosity, - su2double val_eddy_viscosity, - su2double val_dist_ij, - const su2double *val_normal); - - /*! - * \brief Compute the projection of the viscous fluxes into a direction. - * - * The heat flux vector and the stress tensor must be calculated before - * calling this function. - * - * \param[in] val_primvar - Primitive variables. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - */ - void GetViscousProjFlux(const su2double *val_primvar, - const su2double *val_normal); - - /*! - * \brief TSL-Approximation of Viscous NS Jacobians. - * - * The Jacobians of the heat flux vector and the stress tensor must be - * calculated before calling this function. - * - * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. - * \param[in] val_dS - Area of the face between two nodes. - * \param[in] val_Proj_Visc_Flux - Pointer to the projected viscous flux. - * \param[out] val_Proj_Jac_Tensor_i - Pointer to the projected viscous Jacobian at point i. - * \param[out] val_Proj_Jac_Tensor_j - Pointer to the projected viscous Jacobian at point j. - */ - void GetViscousProjJacs(const su2double *val_Mean_PrimVar, - su2double val_dS, - const su2double *val_Proj_Visc_Flux, - su2double **val_Proj_Jac_Tensor_i, - su2double **val_Proj_Jac_Tensor_j); - - /*! - * \brief Apply a correction to the gradient to reduce the truncation error - * - * \param[in] val_PrimVar_i - Primitive variables at point i - * \param[in] val_PrimVar_j - Primitive variables at point j - * \param[in] val_edge_vector - The vector between points i and j - * \param[in] val_dist_ij_2 - The distance between points i and j, squared - * \param[in] val_nPrimVar - The number of primitive variables - */ - void CorrectGradient(su2double** GradPrimVar, - const su2double* val_PrimVar_i, - const su2double* val_PrimVar_j, - const su2double* val_edge_vector, - su2double val_dist_ij_2, - const unsigned short val_nPrimVar); - - /*! - * \brief Initialize the Reynolds Stress Matrix - * \param[in] turb_ke turbulent kinetic energy of node - */ - void SetReynoldsStressMatrix(su2double turb_ke); - - /*! - * \brief Perturb the Reynolds stress tensor based on parameters - * \param[in] turb_ke: turbulent kinetic energy of the noce - * \param[in] Eig_Val_Comp: Defines type of eigenspace perturbation - * \param[in] beta_delta: Defines the amount of eigenvalue perturbation - */ - void SetPerturbedRSM(su2double turb_ke, CConfig *config); - - /*! - * \brief Get the mean rate of strain matrix based on velocity gradients - * \param[in] S_ij - */ - void GetMeanRateOfStrainMatrix(su2double **S_ij) const; - - public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] val_nPrimVar - Number of primitive variables to use. - * \param[in] val_correct_grad - Apply a correction to the gradient - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_Base(unsigned short val_nDim, unsigned short val_nVar, - unsigned short val_nPrimVar, - bool val_correct_grad, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_Base(); - - /*! - * \brief Set the value of the wall shear stress at point i and j (wall functions). - * \param[in] val_tauwall_i - Value of the wall shear stress at point i. - * \param[in] val_tauwall_j - Value of the wall shear stress at point j. - */ - void SetTauWall(su2double val_tauwall_i, su2double val_tauwall_j); - - /*! - * \brief Calculate the viscous + turbulent stress tensor - * \param[in] val_primvar - Primitive variables. - * \param[in] val_gradprimvar - Gradient of the primitive variables. - * \param[in] val_turb_ke - Turbulent kinetic energy - * \param[in] val_laminar_viscosity - Laminar viscosity. - * \param[in] val_eddy_viscosity - Eddy viscosity. - */ - void SetStressTensor(const su2double *val_primvar, - const su2double* const *val_gradprimvar, - su2double val_turb_ke, - su2double val_laminar_viscosity, - su2double val_eddy_viscosity); - - /*! - * \brief Get a component of the viscous stress tensor. - * - * \param[in] iDim - The first index - * \param[in] jDim - The second index - * \return The component of the viscous stress tensor at iDim, jDim - */ - su2double GetStressTensor(unsigned short iDim, unsigned short jDim) const; - - /*! - * \brief Get a component of the heat flux vector. - * \param[in] iDim - The index of the component - * \return The component of the heat flux vector at iDim - */ - su2double GetHeatFluxVector(unsigned short iDim) const; - -}; - -/*! - * \class CAvgGrad_Flow - * \brief Class for computing viscous term using the average of gradients. - * \ingroup ViscDiscr - * \author A. Bueno, and F. Palacios - */ -class CAvgGrad_Flow : public CAvgGrad_Base { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] val_correct_grad - Apply a correction to the gradient - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_Flow(unsigned short val_nDim, unsigned short val_nVar, - bool val_correct_grad, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_Flow(void); - - /*! - * \brief Compute the viscous flow residual using an average of gradients. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \brief Compute the heat flux due to molecular and turbulent diffusivity - * \param[in] val_gradprimvar - Gradient of the primitive variables. - * \param[in] val_laminar_viscosity - Laminar viscosity. - * \param[in] val_eddy_viscosity - Eddy viscosity. - */ - void SetHeatFluxVector(const su2double* const *val_gradprimvar, - su2double val_laminar_viscosity, - su2double val_eddy_viscosity); - - /*! - * \brief Compute the Jacobian of the heat flux vector - * - * This Jacobian is projected onto the normal vector, so it is of - * dimension nVar. - * - * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. - * \param[in] val_gradprimvar - Mean value of the gradient of the primitive variables. - * \param[in] val_laminar_viscosity - Value of the laminar viscosity. - * \param[in] val_eddy_viscosity - Value of the eddy viscosity. - * \param[in] val_dist_ij - Distance between the points. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - */ - void SetHeatFluxJacobian(const su2double *val_Mean_PrimVar, - su2double val_laminar_viscosity, - su2double val_eddy_viscosity, - su2double val_dist_ij, - const su2double *val_normal); -}; - -/*! - * \class CGeneralAvgGrad_Flow - * \brief Class for computing viscous term using the average of gradients. - * \ingroup ViscDiscr - * \author M.Pini, S. Vitale - */ -class CGeneralAvgGrad_Flow : public CAvgGrad_Base { -private: - su2double *Mean_SecVar, /*!< \brief Mean secondary variables. */ - Mean_Thermal_Conductivity, /*!< \brief Mean value of the thermal conductivity. */ - Mean_Cp; /*!< \brief Mean value of the Cp. */ - - /*! - * \brief Compute the heat flux due to molecular and turbulent diffusivity - * \param[in] val_gradprimvar - Gradient of the primitive variables. - * \param[in] val_laminar_viscosity - Laminar viscosity. - * \param[in] val_eddy_viscosity - Eddy viscosity. - * \param[in] val_thermal_conductivity - Thermal Conductivity. - * \param[in] val_heat_capacity_cp - Heat Capacity at constant pressure. - */ - void SetHeatFluxVector(const su2double* const *val_gradprimvar, - su2double val_laminar_viscosity, - su2double val_eddy_viscosity, - su2double val_thermal_conductivity, - su2double val_heat_capacity_cp); - - /*! - * \brief Compute the Jacobian of the heat flux vector - * - * This Jacobian is projected onto the normal vector, so it is of - * dimension nVar. - * - * \param[in] val_Mean_PrimVar - Mean value of the primitive variables. - * \param[in] val_Mean_SecVar - Mean value of the secondary variables. - * \param[in] val_eddy_viscosity - Value of the eddy viscosity. - * \param[in] val_thermal_conductivity - Value of the thermal conductivity. - * \param[in] val_heat_capacity_cp - Value of the specific heat at constant pressure. - * \param[in] val_dist_ij - Distance between the points. - */ - void SetHeatFluxJacobian(const su2double *val_Mean_PrimVar, - const su2double *val_Mean_SecVar, - su2double val_eddy_viscosity, - su2double val_thermal_conductivity, - su2double val_heat_capacity_cp, - su2double val_dist_ij); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] val_correct_grad - Apply a correction to the gradient - * \param[in] config - Definition of the particular problem. - */ - CGeneralAvgGrad_Flow(unsigned short val_nDim, unsigned short val_nVar, bool val_correct_grad, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CGeneralAvgGrad_Flow(void); - - /*! - * \brief Compute the viscous flow residual using an average of gradients. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - - -/*! - * \class CAvgGradInc_Flow - * \brief Class for computing viscous term using an average of gradients. - * \ingroup ViscDiscr - * \author A. Bueno, F. Palacios, T. Economon - */ -class CAvgGradInc_Flow : public CAvgGrad_Base { -private: - su2double Mean_Thermal_Conductivity; /*!< \brief Mean value of the effective thermal conductivity. */ - bool energy; /*!< \brief computation with the energy equation. */ - - /* - * \brief Compute the projection of the viscous fluxes into a direction - * - * The viscous + turbulent stress tensor must be calculated before calling - * this function. - * - * \param[in] val_gradprimvar - Gradient of the primitive variables. - * \param[in] val_normal - Normal vector, the norm of the vector is the area of the face. - * \param[in] val_thermal_conductivity - Thermal conductivity. - */ - void GetViscousIncProjFlux(const su2double* const *val_gradprimvar, - const su2double *val_normal, - su2double val_thermal_conductivity); - - /*! - * \brief Compute the projection of the viscous Jacobian matrices. - * - * The Jacobian of the stress tensor must be calculated before calling - * this function. - * - * \param[in] val_dS - Area of the face between two nodes. - * \param[out] val_Proj_Jac_Tensor_i - Pointer to the projected viscous Jacobian at point i. - * \param[out] val_Proj_Jac_Tensor_j - Pointer to the projected viscous Jacobian at point j. - */ - void GetViscousIncProjJacs(su2double val_dS, - su2double **val_Proj_Jac_Tensor_i, - su2double **val_Proj_Jac_Tensor_j); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] val_correct_grad - Apply a correction to the gradient - * \param[in] config - Definition of the particular problem. - */ - CAvgGradInc_Flow(unsigned short val_nDim, unsigned short val_nVar, - bool val_correct_grad, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGradInc_Flow(void); - - /*! - * \brief Compute the viscous flow residual using an average of gradients. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CAvgGrad_Scalar - * \brief Template class for computing viscous residual of scalar values - * \details This class serves as a template for the scalar viscous residual - * classes. The general structure of a viscous residual calculation is the - * same for many different models, which leads to a lot of repeated code. - * By using the template design pattern, these sections of repeated code are - * moved to a shared base class, and the specifics of each model - * are implemented by derived classes. In order to add a new residual - * calculation for a viscous residual, extend this class and implement - * the pure virtual functions with model-specific behavior. - * \ingroup ViscDiscr - * \author C. Pederson, A. Bueno, and F. Palacios - */ -class CAvgGrad_Scalar : public CNumerics { - private: - - /*! - * \brief A pure virtual function; Adds any extra variables to AD - */ - virtual void ExtraADPreaccIn() = 0; - - /*! - * \brief Model-specific steps in the ComputeResidual method - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - virtual void FinishResidualCalc(su2double *val_residual, - su2double **Jacobian_i, - su2double **Jacobian_j, - CConfig *config) = 0; - - protected: - bool implicit, incompressible; - bool correct_gradient; - unsigned short iVar, iDim; - su2double **Mean_GradTurbVar; /*!< \brief Average of gradients at cell face */ - su2double *Edge_Vector, /*!< \brief Vector from node i to node j. */ - *Proj_Mean_GradTurbVar_Normal, /*!< \brief Mean_gradTurbVar DOT normal */ - *Proj_Mean_GradTurbVar_Edge, /*!< \brief Mean_gradTurbVar DOT Edge_Vector */ - *Proj_Mean_GradTurbVar; /*!< \brief Mean_gradTurbVar DOT normal, corrected if required*/ - su2double dist_ij_2, /*!< \brief |Edge_Vector|^2 */ - proj_vector_ij; /*!< \brief (Edge_Vector DOT normal)/|Edge_Vector|^2 */ - - public: - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_Scalar(unsigned short val_nDim, unsigned short val_nVar, - bool correct_gradient, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_Scalar(void); - - /*! - * \brief Compute the viscous residual using an average of gradients without correction. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, - su2double **Jacobian_j, CConfig *config); -}; - -/*! - * \class CAvgGrad_TurbSA - * \brief Class for computing viscous term using average of gradients (Spalart-Allmaras Turbulence model). - * \ingroup ViscDiscr - * \author A. Bueno. - */ -class CAvgGrad_TurbSA : public CAvgGrad_Scalar { -private: - - const su2double sigma; - su2double nu_i, nu_j, nu_e; - - /*! - * \brief Adds any extra variables to AD - */ - void ExtraADPreaccIn(void); - - /*! - * \brief SA specific steps in the ComputeResidual method - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void FinishResidualCalc(su2double *val_residual, su2double **Jacobian_i, - su2double **Jacobian_j, CConfig *config); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_TurbSA(unsigned short val_nDim, unsigned short val_nVar, - bool correct_grad, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_TurbSA(void); -}; - -/*! - * \class CAvgGrad_TurbSA_Neg - * \brief Class for computing viscous term using average of gradients (Spalart-Allmaras Turbulence model). - * \ingroup ViscDiscr - * \author F. Palacios - */ -class CAvgGrad_TurbSA_Neg : public CAvgGrad_Scalar { -private: - - const su2double sigma; - const su2double cn1; - su2double fn, Xi; - su2double nu_i, nu_j, nu_ij, nu_tilde_ij, nu_e; - - /*! - * \brief Adds any extra variables to AD - */ - void ExtraADPreaccIn(void); - - /*! - * \brief SA specific steps in the ComputeResidual method - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void FinishResidualCalc(su2double *val_residual, su2double **Jacobian_i, - su2double **Jacobian_j, CConfig *config); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_TurbSA_Neg(unsigned short val_nDim, unsigned short val_nVar, - bool correct_grad, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_TurbSA_Neg(void); -}; - -/*! - * \class CAvgGrad_TransLM - * \brief Class for computing viscous term using average of gradients (Spalart-Allmaras Turbulence model). - * \ingroup ViscDiscr - * \author A. Bueno. - */ -class CAvgGrad_TransLM : public CNumerics { -private: - su2double **Mean_GradTransVar; - su2double *Proj_Mean_GradTransVar_Kappa, *Proj_Mean_GradTransVar_Edge; - su2double *Edge_Vector; - bool implicit, incompressible; - su2double sigma; - //su2double dist_ij_2; - //su2double proj_vector_ij; - //unsigned short iVar, iDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_TransLM(void); - - /*! - * \brief Compute the viscous turbulence terms residual using an average of gradients. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config); -}; - -/*! - * \class CAvgGrad_AdjFlow - * \brief Class for computing the adjoint viscous terms. - * \ingroup ViscDiscr - * \author F. Palacios - */ -class CAvgGrad_AdjFlow : public CNumerics { -private: - su2double *Velocity_i; /*!< \brief Auxiliary vector for storing the velocity of point i. */ - su2double *Velocity_j; /*!< \brief Auxiliary vector for storing the velocity of point j. */ - su2double *Mean_Velocity; - su2double *Mean_GradPsiE; /*!< \brief Counter for dimensions of the problem. */ - su2double **Mean_GradPhi; /*!< \brief Counter for dimensions of the problem. */ - su2double *Edge_Vector; /*!< \brief Vector going from node i to node j. */ - bool implicit; /*!< \brief Implicit calculus. */ - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_AdjFlow(void); - - /*! - * \brief Residual computation. - * \param[out] val_residual_i - Pointer to the total residual at point i. - * \param[out] val_residual_j - Pointer to the total residual at point j. - */ - void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, - su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); -}; - -/*! - * \class CAvgGradCorrected_TransLM - * \brief Class for computing viscous term using average of gradients with correction (Spalart-Allmaras turbulence model). - * \ingroup ViscDiscr - * \author A. Bueno. - */ -class CAvgGradCorrected_TransLM : public CNumerics { -private: - su2double **Mean_GradTurbVar; - su2double *Proj_Mean_GradTurbVar_Kappa, *Proj_Mean_GradTurbVar_Edge, *Proj_Mean_GradTurbVar_Corrected; - su2double *Edge_Vector; - bool implicit, incompressible; - su2double sigma; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGradCorrected_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGradCorrected_TransLM(void); - - /*! - * \brief Compute the viscous turbulent residual using an average of gradients with correction. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config); -}; - -/*! - * \class CAvgGrad_TurbSST - * \brief Class for computing viscous term using average of gradient with correction (Menter SST turbulence model). - * \ingroup ViscDiscr - * \author A. Bueno. - */ -class CAvgGrad_TurbSST : public CAvgGrad_Scalar { -private: - su2double sigma_k1, /*!< \brief Constants for the viscous terms, k-w (1), k-eps (2)*/ - sigma_k2, - sigma_om1, - sigma_om2; - - su2double diff_kine, /*!< \brief Diffusivity for viscous terms of tke eq */ - diff_omega; /*!< \brief Diffusivity for viscous terms of omega eq */ - - su2double F1_i, F1_j; /*!< \brief Menter's first blending function */ - - /*! - * \brief Adds any extra variables to AD - */ - void ExtraADPreaccIn(void); - - /*! - * \brief SST specific steps in the ComputeResidual method - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void FinishResidualCalc(su2double *val_residual, su2double **Jacobian_i, - su2double **Jacobian_j, CConfig *config); - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_TurbSST(unsigned short val_nDim, unsigned short val_nVar, - su2double* constants, bool correct_grad, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_TurbSST(void); - - /*! - * \brief Sets value of first blending function. - */ - void SetF1blending(su2double val_F1_i, su2double val_F1_j) { - F1_i = val_F1_i; F1_j = val_F1_j; - } - -}; - -/*! - * \class CAvgGradCorrected_AdjFlow - * \brief Class for computing the adjoint viscous terms, including correction. - * \ingroup ViscDiscr - * \author A. Bueno. - */ -class CAvgGradCorrected_AdjFlow : public CNumerics { -private: - su2double *Velocity_i; /*!< \brief Auxiliary vector for storing the velocity of point i. */ - su2double *Velocity_j; /*!< \brief Auxiliary vector for storing the velocity of point j. */ - su2double *Mean_Velocity; - su2double **Mean_GradPsiVar; /*!< \brief Counter for dimensions of the problem. */ - su2double *Edge_Vector; /*!< \brief Vector going from node i to node j. */ - su2double *Proj_Mean_GradPsiVar_Edge; /*!< \brief Projection of Mean_GradPsiVar onto Edge_Vector. */ - su2double *Mean_GradPsiE; /*!< \brief Counter for dimensions of the problem. */ - su2double **Mean_GradPhi; /*!< \brief Counter for dimensions of the problem. */ - bool implicit; /*!< \brief Boolean controlling Jacobian calculations. */ - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGradCorrected_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGradCorrected_AdjFlow(void); - - /*! - * \brief Compute the adjoint flow viscous residual in a non-conservative way using an average of gradients and derivative correction. - * \param[out] val_residual_i - Pointer to the viscous residual at point i. - * \param[out] val_residual_j - Pointer to the viscous residual at point j. - * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. - * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. - * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. - * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); -}; - -/*! - * \class CAvgGradCorrected_AdjTurb - * \brief Class for adjoint turbulent using average of gradients with a correction. - * \ingroup ViscDiscr - * \author A. Bueno. - */ -class CAvgGradCorrected_AdjTurb : public CNumerics { -private: - su2double **Mean_GradTurbPsi; - su2double *Proj_Mean_GradTurbPsi_Kappa, *Proj_Mean_GradTurbPsi_Edge, *Proj_Mean_GradTurbPsi_Corrected; - su2double *Edge_Vector; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGradCorrected_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGradCorrected_AdjTurb(void); - - /*! - * \brief Compute the adjoint turbulent residual using average of gradients and a derivative correction. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \overload - * \param[out] val_residual_i - Pointer to the total residual at point i. - * \param[out] val_residual_j - Pointer to the total viscosity residual at point j. - * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. - * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. - * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. - * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); -}; - -/*! - * \class CAvgGrad_AdjTurb - * \brief Class for adjoint turbulent using average of gradients with a correction. - * \ingroup ViscDiscr - * \author F. Palacios - */ -class CAvgGrad_AdjTurb : public CNumerics { -private: - su2double **Mean_GradTurbPsi; - su2double *Proj_Mean_GradTurbPsi_Kappa, *Proj_Mean_GradTurbPsi_Edge, *Proj_Mean_GradTurbPsi_Corrected; - su2double *Edge_Vector; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_AdjTurb(void); - - /*! - * \brief Compute the adjoint turbulent residual using average of gradients and a derivative correction. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \overload - * \param[out] val_residual_i - Pointer to the total residual at point i. - * \param[out] val_residual_j - Pointer to the total viscosity residual at point j. - * \param[out] val_Jacobian_ii - Jacobian of the numerical method at node i (implicit computation) from node i. - * \param[out] val_Jacobian_ij - Jacobian of the numerical method at node i (implicit computation) from node j. - * \param[out] val_Jacobian_ji - Jacobian of the numerical method at node j (implicit computation) from node i. - * \param[out] val_Jacobian_jj - Jacobian of the numerical method at node j (implicit computation) from node j. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config); -}; - - -/*! - * \class CAvgGrad_Heat - * \brief Class for computing viscous term using average of gradients without correction (heat equation). - * \ingroup ViscDiscr - * \author O. Burghardt. - * \version 7.0.1 "Blackbird" - */ -class CAvgGrad_Heat : public CNumerics { -private: - su2double **Mean_GradHeatVar; - su2double *Proj_Mean_GradHeatVar_Normal, *Proj_Mean_GradHeatVar_Corrected; - su2double *Edge_Vector; - bool implicit; - su2double dist_ij_2, proj_vector_ij, Thermal_Diffusivity_Mean; - unsigned short iVar, iDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGrad_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGrad_Heat(void); - - /*! - * \brief Compute the viscous heat residual using an average of gradients with correction. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config); -}; - -/*! - * \class CAvgGradCorrected_Heat - * \brief Class for computing viscous term using average of gradients with correction (heat equation). - * \ingroup ViscDiscr - * \author O. Burghardt. - * \version 7.0.1 "Blackbird" - */ -class CAvgGradCorrected_Heat : public CNumerics { -private: - su2double **Mean_GradHeatVar; - su2double *Proj_Mean_GradHeatVar_Kappa, *Proj_Mean_GradHeatVar_Edge, *Proj_Mean_GradHeatVar_Corrected; - su2double *Edge_Vector; - bool implicit; - su2double dist_ij_2, proj_vector_ij, Thermal_Diffusivity_Mean; - unsigned short iVar, iDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CAvgGradCorrected_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CAvgGradCorrected_Heat(void); - - /*! - * \brief Compute the viscous heat residual using an average of gradients with correction. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config); -}; - -/*! - * \class CGalerkin_Flow - * \brief Class for computing the stiffness matrix of the Galerkin method. - * \ingroup ViscDiscr - * \author F. Palacios - */ -class CGalerkin_Flow : public CNumerics { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CGalerkin_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CGalerkin_Flow(void); - - /*! - * \brief Computing stiffness matrix of the Galerkin method. - * \param[out] val_stiffmatrix_elem - Stiffness matrix for Galerkin computation. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual (su2double **val_stiffmatrix_elem, CConfig *config); -}; - -/*! - * \class CSourceNothing - * \brief Dummy class. - * \ingroup SourceDiscr - * \author F. Palacios - */ -class CSourceNothing : public CNumerics { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceNothing(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceNothing(void); -}; - -/*! - * \class CSourcePieceWise_TurbSA - * \brief Class for integrating the source terms of the Spalart-Allmaras turbulence model equation. - * \ingroup SourceDiscr - * \author A. Bueno. - */ -class CSourcePieceWise_TurbSA : public CNumerics { -private: - su2double cv1_3; - su2double k2; - su2double cb1; - su2double cw2; - su2double ct3; - su2double ct4; - su2double cw3_6; - su2double cb2_sigma; - su2double sigma; - su2double cb2; - su2double cw1; - unsigned short iDim; - su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; - su2double r, g, g_6, glim, fw; - su2double norm2_Grad; - su2double dfv1, dfv2, dShat; - su2double dr, dg, dfw; - bool incompressible; - bool rotating_frame; - bool transition; - su2double gamma_BC; - su2double intermittency; - su2double Production, Destruction, CrossProduction; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourcePieceWise_TurbSA(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourcePieceWise_TurbSA(void); - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \brief Residual for source term integration. - * \param[in] intermittency_in - Value of the intermittency. - */ - void SetIntermittency(su2double intermittency_in); - - /*! - * \brief Residual for source term integration. - * \param[in] val_production - Value of the Production. - */ - void SetProduction(su2double val_production); - - /*! - * \brief Residual for source term integration. - * \param[in] val_destruction - Value of the Destruction. - */ - void SetDestruction(su2double val_destruction); - - /*! - * \brief Residual for source term integration. - * \param[in] val_crossproduction - Value of the CrossProduction. - */ - void SetCrossProduction(su2double val_crossproduction); - - /*! - * \brief ______________. - */ - su2double GetProduction(void); - - /*! - * \brief Get the intermittency for the BC trans. model. - * \return Value of the intermittency. - */ - su2double GetGammaBC(void); - - /*! - * \brief ______________. - */ - su2double GetDestruction(void); - - /*! - * \brief ______________. - */ - su2double GetCrossProduction(void); -}; - -/*! - * \class CSourcePieceWise_TurbSA_E - * \brief Class for integrating the source terms of the Spalart-Allmaras Edwards modification turbulence model equation. - * \ingroup SourceDiscr - * \author E.Molina, A. Bueno. - * \version 7.0.1 "Blackbird" - */ -class CSourcePieceWise_TurbSA_E : public CNumerics { -private: - su2double cv1_3; - su2double k2; - su2double cb1; - su2double cw2; - su2double ct3; - su2double ct4; - su2double cw3_6; - su2double cb2_sigma; - su2double sigma; - su2double cb2; - su2double cw1; - unsigned short iDim; - su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; - su2double r, g, g_6, glim, fw; - su2double norm2_Grad; - su2double dfv1, dfv2, dShat; - su2double dr, dg, dfw; - bool incompressible; - bool rotating_frame; - su2double intermittency; - su2double Production, Destruction, CrossProduction; - su2double Sbar; - unsigned short jDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourcePieceWise_TurbSA_E(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourcePieceWise_TurbSA_E(void); - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \brief Residual for source term integration. - * \param[in] intermittency_in - Value of the intermittency. - */ - void SetIntermittency(su2double intermittency_in); - - /*! - * \brief Residual for source term integration. - * \param[in] val_production - Value of the Production. - */ - void SetProduction(su2double val_production); - - /*! - * \brief Residual for source term integration. - * \param[in] val_destruction - Value of the Destruction. - */ - void SetDestruction(su2double val_destruction); - - /*! - * \brief Residual for source term integration. - * \param[in] val_crossproduction - Value of the CrossProduction. - */ - void SetCrossProduction(su2double val_crossproduction); - - /*! - * \brief ______________. - */ - su2double GetProduction(void); - - /*! - * \brief ______________. - */ - su2double GetDestruction(void); - - /*! - * \brief ______________. - */ - su2double GetCrossProduction(void); -}; - -/*! - * \class CSourcePieceWise_TurbSA_COMP - * \brief Class for integrating the source terms of the Spalart-Allmaras CC modification turbulence model equation. - * \ingroup SourceDiscr - * \author E.Molina, A. Bueno. - * \version 7.0.1 "Blackbird" - */ -class CSourcePieceWise_TurbSA_COMP : public CNumerics { -private: - su2double cv1_3; - su2double k2; - su2double cb1; - su2double cw2; - su2double ct3; - su2double ct4; - su2double cw3_6; - su2double cb2_sigma; - su2double sigma; - su2double cb2; - su2double cw1; - unsigned short iDim; - su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; - su2double r, g, g_6, glim, fw; - su2double norm2_Grad; - su2double dfv1, dfv2, dShat; - su2double dr, dg, dfw; - bool incompressible; - bool rotating_frame; - su2double intermittency; - su2double Production, Destruction, CrossProduction; - su2double aux_cc, CompCorrection, c5; - unsigned short jDim; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourcePieceWise_TurbSA_COMP(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourcePieceWise_TurbSA_COMP(void); - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \brief Residual for source term integration. - * \param[in] intermittency_in - Value of the intermittency. - */ - void SetIntermittency(su2double intermittency_in); - - /*! - * \brief Residual for source term integration. - * \param[in] val_production - Value of the Production. - */ - void SetProduction(su2double val_production); - - /*! - * \brief Residual for source term integration. - * \param[in] val_destruction - Value of the Destruction. - */ - void SetDestruction(su2double val_destruction); - - /*! - * \brief Residual for source term integration. - * \param[in] val_crossproduction - Value of the CrossProduction. - */ - void SetCrossProduction(su2double val_crossproduction); - - /*! - * \brief ______________. - */ - su2double GetProduction(void); - - /*! - * \brief ______________. - */ - su2double GetDestruction(void); - - /*! - * \brief ______________. - */ - su2double GetCrossProduction(void); -}; - -/*! - * \class CSourcePieceWise_TurbSA_E_COMP - * \brief Class for integrating the source terms of the Spalart-Allmaras Edwards modification with CC turbulence model equation. - * \ingroup SourceDiscr - * \author E.Molina, A. Bueno. - * \version 7.0.1 "Blackbird" - */ -class CSourcePieceWise_TurbSA_E_COMP : public CNumerics { -private: - su2double cv1_3; - su2double k2; - su2double cb1; - su2double cw2; - su2double ct3; - su2double ct4; - su2double cw3_6; - su2double cb2_sigma; - su2double sigma; - su2double cb2; - su2double cw1; - unsigned short iDim; - su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; - su2double r, g, g_6, glim, fw; - su2double norm2_Grad; - su2double dfv1, dfv2, dShat; - su2double dr, dg, dfw; - bool incompressible; - bool rotating_frame; - su2double intermittency; - su2double Production, Destruction, CrossProduction; - su2double Sbar; - unsigned short jDim; - su2double aux_cc, CompCorrection, c5; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourcePieceWise_TurbSA_E_COMP(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourcePieceWise_TurbSA_E_COMP(void); - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \brief Residual for source term integration. - * \param[in] intermittency_in - Value of the intermittency. - */ - void SetIntermittency(su2double intermittency_in); - - /*! - * \brief Residual for source term integration. - * \param[in] val_production - Value of the Production. - */ - void SetProduction(su2double val_production); - - /*! - * \brief Residual for source term integration. - * \param[in] val_destruction - Value of the Destruction. - */ - void SetDestruction(su2double val_destruction); - - /*! - * \brief Residual for source term integration. - * \param[in] val_crossproduction - Value of the CrossProduction. - */ - void SetCrossProduction(su2double val_crossproduction); - - /*! - * \brief ______________. - */ - su2double GetProduction(void); - - /*! - * \brief ______________. - */ - su2double GetDestruction(void); - - /*! - * \brief ______________. - */ - su2double GetCrossProduction(void); -}; - -/*! - * \class CSourcePieceWise_TurbSA_Neg - * \brief Class for integrating the source terms of the Spalart-Allmaras turbulence model equation. - * \ingroup SourceDiscr - * \author F. Palacios - */ -class CSourcePieceWise_TurbSA_Neg : public CNumerics { -private: - su2double cv1_3; - su2double k2; - su2double cb1; - su2double cw2; - su2double ct3; - su2double ct4; - su2double cw3_6; - su2double cb2_sigma; - su2double sigma; - su2double cb2; - su2double cw1; - unsigned short iDim; - su2double nu, Ji, fv1, fv2, ft2, Omega, S, Shat, inv_Shat, dist_i_2, Ji_2, Ji_3, inv_k2_d2; - su2double r, g, g_6, glim, fw; - su2double norm2_Grad; - su2double dfv1, dfv2, dShat; - su2double dr, dg, dfw; - bool incompressible; - bool rotating_frame; - su2double intermittency; - su2double Production, Destruction, CrossProduction; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourcePieceWise_TurbSA_Neg(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourcePieceWise_TurbSA_Neg(void); - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \brief Residual for source term integration. - * \param[in] intermittency_in - Value of the intermittency. - */ - void SetIntermittency(su2double intermittency_in); - - /*! - * \brief Residual for source term integration. - * \param[in] val_production - Value of the Production. - */ - void SetProduction(su2double val_production); - - /*! - * \brief Residual for source term integration. - * \param[in] val_destruction - Value of the Destruction. - */ - void SetDestruction(su2double val_destruction); - - /*! - * \brief Residual for source term integration. - * \param[in] val_crossproduction - Value of the CrossProduction. - */ - void SetCrossProduction(su2double val_crossproduction); - - /*! - * \brief ______________. - */ - su2double GetProduction(void); - - /*! - * \brief ______________. - */ - su2double GetDestruction(void); - - /*! - * \brief ______________. - */ - su2double GetCrossProduction(void); -}; - -/*! - * \class CSourcePieceWise_TransLM - * \brief Class for integrating the source terms of the Spalart-Allmaras turbulence model equation. - * \ingroup SourceDiscr - * \author A. Bueno. - */ -class CSourcePieceWise_TransLM : public CNumerics { -private: - - /*-- SA model constants --*/ - su2double cv1_3; - su2double k2; - su2double cb1; - su2double cw2; - su2double cw3_6; - su2double sigma; - su2double cb2; - su2double cw1; - - /*-- gamma-theta model constants --*/ - su2double c_e1; - su2double c_a1; - su2double c_e2; - su2double c_a2; - su2double sigmaf; - su2double s1; - su2double c_theta; - su2double sigmat; - - /*-- Correlation constants --*/ - su2double flen_global; - su2double alpha_global; - su2double Vorticity; - - bool implicit; - -public: - bool debugme; // For debugging only, remove this. -AA - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourcePieceWise_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourcePieceWise_TransLM(void); - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual_TransLM(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config, su2double &gamma_sep); - - void CSourcePieceWise_TransLM__ComputeResidual_TransLM_d(su2double *TransVar_i, su2double *TransVar_id, su2double *val_residual, su2double *val_residuald, CConfig *config); -}; - -/*! - * \class CSourcePieceWise_TurbSST - * \brief Class for integrating the source terms of the Menter SST turbulence model equations. - * \ingroup SourceDiscr - * \author A. Campos. - */ -class CSourcePieceWise_TurbSST : public CNumerics { -private: - su2double F1_i, - F1_j, - F2_i, - F2_j; - - su2double alfa_1, - alfa_2, - beta_1, - beta_2, - sigma_omega_1, - sigma_omega_2, - beta_star, - a1; - - su2double CDkw_i, CDkw_j; - - su2double kAmb, omegaAmb; - - bool incompressible; - bool sustaining_terms; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourcePieceWise_TurbSST(unsigned short val_nDim, unsigned short val_nVar, su2double* constants, - su2double val_kine_Inf, su2double val_omega_Inf, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourcePieceWise_TurbSST(void); - - /*! - * \brief Set the value of the first blending function. - * \param[in] val_F1_i - Value of the first blending function at point i. - * \param[in] val_F1_j - Value of the first blending function at point j. - */ - void SetF1blending(su2double val_F1_i, su2double val_F1_j); - - /*! - * \brief Set the value of the second blending function. - * \param[in] val_F2_i - Value of the second blending function at point i. - * \param[in] val_F2_j - Value of the second blending function at point j. - */ - void SetF2blending(su2double val_F2_i, su2double val_F2_j); - - /*! - * \brief Set the value of the cross diffusion for the SST model. - * \param[in] val_CDkw_i - Value of the cross diffusion at point i. - * \param[in] val_CDkw_j - Value of the cross diffusion at point j. - */ - virtual void SetCrossDiff(su2double val_CDkw_i, su2double val_CDkw_j); - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); - - /*! - * \brief Initialize the Reynolds Stress Matrix - * \param[in] turb_ke turbulent kinetic energy of node - */ - void SetReynoldsStressMatrix(su2double turb_ke); - - /*! - * \brief Perturb the Reynolds stress tensor based on parameters - * \param[in] turb_ke: turbulent kinetic energy of the noce - * \param[in] config: config file - */ - void SetPerturbedRSM(su2double turb_ke, CConfig *config); - /*! - * \brief A virtual member. Get strain magnitude based on perturbed reynolds stress matrix - * \param[in] turb_ke: turbulent kinetic energy of the node - */ - void SetPerturbedStrainMag(su2double turb_ke); - - /*! - * \brief Get the mean rate of strain matrix based on velocity gradients - * \param[in] S_ij - */ - void GetMeanRateOfStrainMatrix(su2double **S_ij); - -}; - -/*! - * \class CSourceGravity - * \brief Class for the source term integration of the gravity force. - * \ingroup SourceDiscr - * \author F. Palacios - */ -class CSourceGravity : public CNumerics { - -public: - - /*! - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceGravity(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceGravity(void); - - /*! - * \brief Source term integration for the poissonal potential. - * \param[out] val_residual - Pointer to the total residual. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, CConfig *config); -}; - -/*! - * \class CSourceBodyForce - * \brief Class for the source term integration of a body force. - * \ingroup SourceDiscr - * \author T. Economon - */ -class CSourceBodyForce : public CNumerics { - su2double *Body_Force_Vector; - -public: - - /*! - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceBodyForce(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceBodyForce(void); - - /*! - * \brief Source term integration for a body force. - * \param[out] val_residual - Pointer to the residual vector. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, CConfig *config); - -}; - -/*! - * \class CSourceIncBodyForce - * \brief Class for the source term integration of a body force in the incompressible solver. - * \ingroup SourceDiscr - * \author T. Economon - * \version 7.0.1 "Blackbird" - */ -class CSourceIncBodyForce : public CNumerics { - su2double *Body_Force_Vector; - -public: - - /*! - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceIncBodyForce(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceIncBodyForce(void); - - /*! - * \brief Source term integration for a body force. - * \param[out] val_residual - Pointer to the residual vector. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, CConfig *config); - -}; - -/*! - * \class CSourceIncRotatingFrame_Flow - * \brief Class for a rotating frame source term. - * \ingroup SourceDiscr - */ -class CSourceIncRotatingFrame_Flow : public CNumerics { - -private: - su2double Omega[3]; /*!< \brief Angular velocity */ - bool implicit; /*!< \brief Implicit calculation. */ - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceIncRotatingFrame_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceIncRotatingFrame_Flow(void); - - /*! - * \brief Residual of the rotational frame source term. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config); - -}; - -/*! - * \class CSourceBoussinesq - * \brief Class for the source term integration of the Boussinesq approximation for incompressible flow. - * \ingroup SourceDiscr - * \author T. Economon - * \version 7.0.1 "Blackbird" - */ -class CSourceBoussinesq : public CNumerics { - su2double *Gravity_Vector; - -public: - - /*! - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceBoussinesq(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceBoussinesq(void); - - /*! - * \brief Source term integration for the Boussinesq approximation. - * \param[out] val_residual - Pointer to the residual vector. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, CConfig *config); - -}; - -/*! - * \class CSourceIncAxisymmetric_Flow - * \brief Class for source term for solving incompressible axisymmetric problems. - * \ingroup SourceDiscr - * \author T. Economon - */ -class CSourceIncAxisymmetric_Flow : public CNumerics { - bool implicit, /*!< \brief Implicit calculation. */ - viscous, /*!< \brief Viscous incompressible flows. */ - energy; /*!< \brief computation with the energy equation. */ - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceIncAxisymmetric_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceIncAxisymmetric_Flow(void); - - /*! - * \brief Residual of the rotational frame source term. - * \param[out] val_residual - Pointer to the total residual. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, CConfig *config); - -}; - -/*! - * \class CSourceViscous_AdjFlow - * \brief Class for source term integration in adjoint problem. - * \ingroup SourceDiscr - * \author F. Palacios - */ -class CSourceViscous_AdjFlow : public CNumerics { -private: - su2double *Velocity, *GradDensity, *GradInvDensity, *dPoDensity2, *alpha, *beta, *Sigma_5_vec; - su2double **GradVel_o_Rho, **sigma, **Sigma_phi, **Sigma_5_Tensor, **Sigma; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceViscous_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceViscous_AdjFlow(void); - - /*! - * \brief Source term integration of the flow adjoint equation. - * \param[out] val_residual - Pointer to the total residual. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual (su2double *val_residual, CConfig *config); - -}; - -/*! - * \class CSourcePieceWise_AdjTurb - * \brief Class for source term integration of the adjoint turbulent equation. - * \ingroup SourceDiscr - * \author A. Bueno. - */ -class CSourcePieceWise_AdjTurb : public CNumerics { -private: - su2double **tau, *Velocity; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourcePieceWise_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourcePieceWise_AdjTurb(void); - - /*! - * \brief Source term integration of the adjoint turbulence equation. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -class CSourceConservative_AdjFlow : public CNumerics { -private: - su2double *Velocity, *Residual_i, *Residual_j, *Mean_Residual; - su2double **Mean_PrimVar_Grad; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceConservative_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceConservative_AdjFlow(void); - - /*! - * \brief Source term integration using a conservative scheme. - * \param[out] val_residual - Pointer to the total residual. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, CConfig *config); -}; - -/*! - * \class CSourceConservative_AdjTurb - * \brief Class for source term integration in adjoint turbulent problem using a conservative scheme. - * \ingroup SourceDiscr - * \author A. Bueno. - */ -class CSourceConservative_AdjTurb : public CNumerics { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceConservative_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceConservative_AdjTurb(void); - - /*! - * \brief Source term integration using a conservative scheme. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CSourceRotatingFrame_Flow - * \brief Class for a rotating frame source term. - * \ingroup SourceDiscr - * \author F. Palacios, T. Economon. - */ -class CSourceRotatingFrame_Flow : public CNumerics { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceRotatingFrame_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceRotatingFrame_Flow(void); - - /*! - * \brief Residual of the rotational frame source term. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config); -}; - -/*! - * \class CSourceRotatingFrame_AdjFlow - * \brief Source term class for rotating frame adjoint. - * \ingroup SourceDiscr - * \author T. Economon. - */ -class CSourceRotatingFrame_AdjFlow : public CNumerics { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceRotatingFrame_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceRotatingFrame_AdjFlow(void); - - /*! - * \brief Residual of the adjoint rotating frame source term. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config); -}; - -/*! - * \class CSourceAxisymmetric_Flow - * \brief Class for source term for solving axisymmetric problems. - * \ingroup SourceDiscr - * \author F. Palacios - */ -class CSourceAxisymmetric_Flow : public CNumerics { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceAxisymmetric_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceAxisymmetric_Flow(void); - - /*! - * \brief Residual of the rotational frame source term. - * \param[out] val_residual - Pointer to the total residual. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, CConfig *config); - -}; - -/*! - * \class CSourceAxisymmetric_AdjFlow - * \brief Class for source term for solving axisymmetric problems. - * \ingroup SourceDiscr - * \author F. Palacios - */ -class CSourceAxisymmetric_AdjFlow : public CNumerics { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceAxisymmetric_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceAxisymmetric_AdjFlow(void); - - /*! - * \brief Residual of the rotational frame source term. - * \param[out] val_residual - Pointer to the total residual. - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **Jacobian_i, CConfig *config); -}; - -/*! - * \class CSourceWindGust - * \brief Class for a source term due to a wind gust. - * \ingroup SourceDiscr - * \author S. Padrón - */ -class CSourceWindGust : public CNumerics { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CSourceWindGust(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSourceWindGust(void); - - /*! - * \brief Residual of the wind gust source term. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config); -}; - -/*! - * \class CSource_Template - * \brief Dummy class. - * \ingroup SourceDiscr - * \author A. Lonkar. - */ -class CSource_Template : public CNumerics { -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Name of the input config file - * - */ - CSource_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - - /*! - * \brief Residual for source term integration. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CSource_Template(void); -}; - -/*! - * \class CConvectiveTemplate - * \brief Class for setting up new method for spatial discretization of convective terms in flow Equations - * \ingroup ConvDiscr - * \author A. Lonkar - */ -class CConvective_Template : public CNumerics { -private: - - /* define private variables here */ - bool implicit; - su2double *Diff_U; - su2double *Velocity_i, *Velocity_j, *RoeVelocity; - su2double *ProjFlux_i, *ProjFlux_j; - su2double *delta_wave, *delta_vel; - su2double *Lambda, *Epsilon; - su2double **P_Tensor, **invP_Tensor; - su2double sq_vel, Proj_ModJac_Tensor_ij, Density_i, Energy_i, SoundSpeed_i, Pressure_i, Enthalpy_i, - Density_j, Energy_j, SoundSpeed_j, Pressure_j, Enthalpy_j, R, RoeDensity, RoeEnthalpy, RoeSoundSpeed, - ProjVelocity, ProjVelocity_i, ProjVelocity_j, proj_delta_vel, delta_p, delta_rho; - unsigned short iDim, iVar, jVar, kVar; - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimensions of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CConvective_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CConvective_Template(void); - - /*! - * \brief Compute the Roe's flux between two nodes i and j. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -/*! - * \class CViscous_Template - * \brief Class for computing viscous term using average of gradients. - * \ingroup ViscDiscr - * \author F. Palacios - */ -class CViscous_Template : public CNumerics { -private: - -public: - - /*! - * \brief Constructor of the class. - * \param[in] val_nDim - Number of dimension of the problem. - * \param[in] val_nVar - Number of variables of the problem. - * \param[in] config - Definition of the particular problem. - */ - CViscous_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config); - - /*! - * \brief Destructor of the class. - */ - ~CViscous_Template(void); - - /*! - * \brief Compute the viscous flow residual using an average of gradients. - * \param[out] val_residual - Pointer to the total residual. - * \param[out] val_Jacobian_i - Jacobian of the numerical method at node i (implicit computation). - * \param[out] val_Jacobian_j - Jacobian of the numerical method at node j (implicit computation). - * \param[in] config - Definition of the particular problem. - */ - void ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config); -}; - -#include "numerics_structure.inl" diff --git a/SU2_CFD/include/numerics_structure.inl b/SU2_CFD/include/numerics_structure.inl deleted file mode 100644 index b3cedf282b89..000000000000 --- a/SU2_CFD/include/numerics_structure.inl +++ /dev/null @@ -1,494 +0,0 @@ -/*! - * \file numerics_structure.inl - * \brief In-Line subroutines of the numerics_structure.hpp file. - * \author F. Palacios, T. Economon - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, 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 - -inline su2double CNumerics::Determinant_3x3(su2double A00, - su2double A01, - su2double A02, - su2double A10, - su2double A11, - su2double A12, - su2double A20, - su2double A21, - su2double A22) { - - return A00*(A11*A22-A12*A21) - A01*(A10*A22-A12*A20) + A02*(A10*A21-A11*A20); - -} - -inline void CNumerics::Compute_Mass_Matrix(CElement *element_container, CConfig *config) { } - -inline void CNumerics::Compute_Dead_Load(CElement *element_container, CConfig *config) { } - -inline void CNumerics::Compute_Tangent_Matrix(CElement *element_container, CConfig *config) { } - -inline void CNumerics::Compute_NodalStress_Term(CElement *element_container, CConfig *config) { } - -inline void CNumerics::Compute_Averaged_NodalStress(CElement *element_container, CConfig *config) { } - -inline void CNumerics::SetMeshElasticProperties(unsigned long iElem, su2double val_E) { } - -inline void CNumerics::Set_DV_Val(unsigned short i_DV, su2double val_DV) { } - -inline su2double CNumerics::Get_DV_Val(unsigned short i_DV) const { return 0.0; } - -inline void CNumerics::Set_ElectricField(unsigned short i_DV, su2double val_EField) { } - -inline void CNumerics::SetMaterial_Properties(unsigned short iVal, su2double val_E, su2double val_Nu) { } - -inline void CNumerics::SetMaterial_Density(unsigned short iVal, su2double val_Rho, su2double val_Rho_DL) { } - -inline void CNumerics::ComputeResidual(su2double *val_residual, CConfig *config) { } - -inline void CNumerics::ComputeResidual(su2double *val_residual_i, su2double *val_residual_j) { } - -inline void CNumerics::ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, CConfig *config) { } - -inline void CNumerics::ComputeResidual(su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { } - -inline void CNumerics::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, - CConfig *config) { } - -inline void CNumerics::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, - su2double **val_JacobianMeanFlow_i, su2double **val_JacobianMeanFlow_j, CConfig *config) { } - -inline void CNumerics::ComputeResidual(su2double *val_resconv, su2double *val_resvisc, su2double **val_Jacobian_i, - su2double **val_Jacobian_j, CConfig *config) { } - -inline void CNumerics::ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, - su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { } - -inline void CNumerics::ComputeResidual(su2double *val_resconv_i, su2double *val_resvisc_i, su2double *val_resconv_j, - su2double *val_resvisc_j, su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { } - -inline void CNumerics::ComputeResidual(su2double **val_stiffmatrix_elem, CConfig *config) { } - -inline void CNumerics::GetEq_Rxn_Coefficients(su2double **EqnRxnConstants, CConfig *config) { }; - -inline void CNumerics::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) { } - -inline void CNumerics::ComputeResidual_TransLM(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config, su2double &gamma_sep) {} - -inline void CNumerics::ComputeResidual_Axisymmetric(su2double *val_residual, CConfig *config) { } - -inline void CNumerics::ComputeResidual_Axisymmetric_ad(su2double *val_residual, su2double *val_residuald, CConfig *config) { } - -inline void CNumerics::SetJacobian_Axisymmetric(su2double **val_Jacobian_i, CConfig *config) { } - -inline void CNumerics::ComputeVibRelaxation(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) { } - -inline void CNumerics::ComputeChemistry(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) { } - -inline void CNumerics::GetKeqConstants(su2double *A, unsigned short val_reaction, CConfig *config) { } - -inline void CNumerics::SetUndivided_Laplacian(su2double *val_und_lapl_i, su2double *val_und_lapl_j) { - Und_Lapl_i = val_und_lapl_i; - Und_Lapl_j = val_und_lapl_j; -} - -inline void CNumerics::SetSensor( su2double val_sensor_i, su2double val_sensor_j) { - Sensor_i = val_sensor_i; - Sensor_j = val_sensor_j; -} - -inline void CNumerics::SetConservative(su2double *val_u_i, su2double *val_u_j) { - U_i = val_u_i; - U_j = val_u_j; -} - -inline void CNumerics::SetConservative_ZeroOrder(su2double *val_u_i, su2double *val_u_j) { - UZeroOrder_i = val_u_i; - UZeroOrder_j = val_u_j; -} - -inline void CNumerics::SetPrimitive(su2double *val_v_i, su2double *val_v_j) { - V_i = val_v_i; - V_j = val_v_j; -} - -inline void CNumerics::SetSecondary(su2double *val_s_i, su2double *val_s_j) { - S_i = val_s_i; - S_j = val_s_j; -} - -inline void CNumerics::SetConservative(su2double *val_u_0, su2double *val_u_1, su2double *val_u_2) { - U_0 = val_u_0; - U_1 = val_u_1; - U_2 = val_u_2; -} - -inline void CNumerics::SetConservative(su2double *val_u_0, su2double *val_u_1, su2double *val_u_2, su2double *val_u_3) { - U_0 = val_u_0; - U_1 = val_u_1; - U_2 = val_u_2; - U_3 = val_u_3; -} - -inline void CNumerics::SetVelocity2_Inf(su2double velocity2) { - vel2_inf = velocity2; -} - -inline void CNumerics::SetVorticity(su2double *val_vorticity_i, su2double *val_vorticity_j) { - Vorticity_i = val_vorticity_i; - Vorticity_j = val_vorticity_j; -} - -inline void CNumerics::SetStrainMag(su2double val_strainmag_i, su2double val_strainmag_j) { - StrainMag_i = val_strainmag_i; - StrainMag_j = val_strainmag_j; -} - -inline void CNumerics::SetTimeStep(su2double val_timestep) {TimeStep = val_timestep;} - -inline void CNumerics::SetLaminarViscosity(su2double val_lam_viscosity_i, su2double val_lam_viscosity_j) { - Laminar_Viscosity_i = val_lam_viscosity_i; - Laminar_Viscosity_j = val_lam_viscosity_j; -} - -inline void CNumerics::SetThermalConductivity(su2double val_therm_conductivity_i, su2double val_therm_conductivity_j) { - Thermal_Conductivity_i = val_therm_conductivity_i; - Thermal_Conductivity_j = val_therm_conductivity_j; -} - -inline void CNumerics::SetThermalConductivity_ve(su2double val_therm_conductivity_ve_i, su2double val_therm_conductivity_ve_j) { - Thermal_Conductivity_ve_i = val_therm_conductivity_ve_i; - Thermal_Conductivity_ve_j = val_therm_conductivity_ve_j; -} - -inline void CNumerics::SetThermalDiffusivity(su2double val_thermal_diffusivity_i,su2double val_thermal_diffusivity_j) { - Thermal_Diffusivity_i = val_thermal_diffusivity_i; - Thermal_Diffusivity_j = val_thermal_diffusivity_j; -} - -inline void CNumerics::SetDiffusionCoeff(su2double* val_diffusioncoeff_i, su2double* val_diffusioncoeff_j) { - Diffusion_Coeff_i = val_diffusioncoeff_i; - Diffusion_Coeff_j = val_diffusioncoeff_j; -} - -inline void CNumerics::SetEddyViscosity(su2double val_eddy_viscosity_i, su2double val_eddy_viscosity_j) { - Eddy_Viscosity_i = val_eddy_viscosity_i; - Eddy_Viscosity_j = val_eddy_viscosity_j; -} - -inline void CNumerics::SetIntermittency(su2double intermittency_in) { } - -inline void CNumerics::SetProduction(su2double val_production) { } - -inline void CNumerics::SetDestruction(su2double val_destruction) { } - -inline void CNumerics::SetCrossProduction(su2double val_crossproduction) { } - -inline su2double CNumerics::GetProduction(void) { return 0; } - -inline su2double CNumerics::GetDestruction(void) { return 0; } - -inline su2double CNumerics::GetCrossProduction(void) { return 0; } - -inline su2double CNumerics::GetGammaBC(void) { return 0.0; } - -inline void CNumerics::SetTurbKineticEnergy(su2double val_turb_ke_i, su2double val_turb_ke_j) { - turb_ke_i = val_turb_ke_i; - turb_ke_j = val_turb_ke_j; -} - -inline void CNumerics::SetDistance(su2double val_dist_i, su2double val_dist_j) { - dist_i = val_dist_i; - dist_j = val_dist_j; -} - -inline void CNumerics::SetAdjointVar(su2double *val_psi_i, su2double *val_psi_j) { - Psi_i = val_psi_i; - Psi_j = val_psi_j; -} - -inline void CNumerics::SetAdjointVarGradient(su2double **val_psivar_grad_i, su2double **val_psivar_grad_j) { - PsiVar_Grad_i = val_psivar_grad_i; - PsiVar_Grad_j = val_psivar_grad_j; -} - -inline void CNumerics::SetTurbVar(su2double *val_turbvar_i, su2double *val_turbvar_j) { - TurbVar_i = val_turbvar_i; - TurbVar_j = val_turbvar_j; -} - -inline void CNumerics::SetTransVar(su2double *val_transvar_i, su2double *val_transvar_j) { - TransVar_i = val_transvar_i; - TransVar_j = val_transvar_j; -} - -inline void CNumerics::SetTurbVarGradient(su2double **val_turbvar_grad_i, su2double **val_turbvar_grad_j) { - TurbVar_Grad_i = val_turbvar_grad_i; - TurbVar_Grad_j = val_turbvar_grad_j; -} - -inline void CNumerics::SetTransVarGradient(su2double **val_transvar_grad_i, su2double **val_transvar_grad_j) { - TransVar_Grad_i = val_transvar_grad_i; - TransVar_Grad_j = val_transvar_grad_j; -} - -inline void CNumerics::SetPrimVarGradient(su2double **val_primvar_grad_i, su2double **val_primvar_grad_j) { - PrimVar_Grad_i = val_primvar_grad_i; - PrimVar_Grad_j = val_primvar_grad_j; -} - - -inline void CNumerics::SetConsVarGradient(su2double **val_consvar_grad_i, su2double **val_consvar_grad_j) { - ConsVar_Grad_i = val_consvar_grad_i; - ConsVar_Grad_j = val_consvar_grad_j; -} - -inline void CNumerics::SetConsVarGradient(su2double **val_consvar_grad_0, su2double **val_consvar_grad_1, su2double **val_consvar_grad_2) { - ConsVar_Grad_0 = val_consvar_grad_0; - ConsVar_Grad_1 = val_consvar_grad_1; - ConsVar_Grad_2 = val_consvar_grad_2; -} - -inline void CNumerics::SetConsVarGradient(su2double **val_consvar_grad_0, su2double **val_consvar_grad_1, su2double **val_consvar_grad_2, su2double **val_consvar_grad_3) { - ConsVar_Grad_0 = val_consvar_grad_0; - ConsVar_Grad_1 = val_consvar_grad_1; - ConsVar_Grad_2 = val_consvar_grad_2; - ConsVar_Grad_3 = val_consvar_grad_3; -} - -inline void CNumerics::SetConsVarGradient(su2double **val_consvar_grad) { - ConsVar_Grad = val_consvar_grad; -} - -inline void CNumerics::SetCoord(su2double *val_coord_i, su2double *val_coord_j) { - Coord_i = val_coord_i; - Coord_j = val_coord_j; -} - -inline void CNumerics::SetCoord(su2double *val_coord_0, su2double *val_coord_1, - su2double *val_coord_2) { - Coord_0 = val_coord_0; - Coord_1 = val_coord_1; - Coord_2 = val_coord_2; -} - -inline void CNumerics::SetCoord(su2double *val_coord_0, su2double *val_coord_1, - su2double *val_coord_2, su2double *val_coord_3) { - Coord_0 = val_coord_0; - Coord_1 = val_coord_1; - Coord_2 = val_coord_2; - Coord_3 = val_coord_3; -} - -inline void CNumerics::SetGridVel(su2double *val_gridvel_i, su2double *val_gridvel_j) { - GridVel_i = val_gridvel_i; - GridVel_j = val_gridvel_j; -} - -inline void CNumerics::SetWindGust(su2double *val_windgust_i, su2double *val_windgust_j) { - WindGust_i = val_windgust_i; - WindGust_j = val_windgust_j; -} - -inline void CNumerics::SetWindGustDer(su2double *val_windgustder_i, su2double *val_windgustder_j) { - WindGustDer_i = val_windgustder_i; - WindGustDer_j = val_windgustder_j; -} - -inline void CNumerics::SetPressure(su2double val_pressure_i, su2double val_pressure_j) { - Pressure_i = val_pressure_i; - Pressure_j = val_pressure_j; -} - -inline void CNumerics::SetDensity(su2double val_densityinc_i, su2double val_densityinc_j) { - DensityInc_i = val_densityinc_i; - DensityInc_j = val_densityinc_j; -} - -inline void CNumerics::SetBetaInc2(su2double val_betainc2_i, su2double val_betainc2_j) { - BetaInc2_i = val_betainc2_i; - BetaInc2_j = val_betainc2_j; -} - -inline void CNumerics::SetSoundSpeed(su2double val_soundspeed_i, su2double val_soundspeed_j) { - SoundSpeed_i = val_soundspeed_i; - SoundSpeed_j = val_soundspeed_j; -} - -inline void CNumerics::SetEnthalpy(su2double val_enthalpy_i, su2double val_enthalpy_j) { - Enthalpy_i = val_enthalpy_i; - Enthalpy_j = val_enthalpy_j; -} - -inline void CNumerics::SetLambda(su2double val_lambda_i, su2double val_lambda_j) { - Lambda_i = val_lambda_i; - Lambda_j = val_lambda_j; -} - -inline void CNumerics::SetNeighbor(unsigned short val_neighbor_i, unsigned short val_neighbor_j) { - Neighbor_i = val_neighbor_i; - Neighbor_j = val_neighbor_j; -} - -inline void CNumerics::SetTurbAdjointVar(su2double *val_turbpsivar_i, su2double *val_turbpsivar_j) { - TurbPsi_i = val_turbpsivar_i; - TurbPsi_j = val_turbpsivar_j; -} - -inline void CNumerics::SetTurbAdjointGradient(su2double **val_turbpsivar_grad_i, su2double **val_turbpsivar_grad_j) { - TurbPsi_Grad_i = val_turbpsivar_grad_i; - TurbPsi_Grad_j = val_turbpsivar_grad_j; -} - -inline void CNumerics::SetTemperature(su2double val_temp_i, su2double val_temp_j) { - Temp_i = val_temp_i; - Temp_j = val_temp_j; -} - -inline void CNumerics::SetAuxVarGrad(su2double *val_auxvargrad_i, su2double *val_auxvargrad_j) { - AuxVar_Grad_i = val_auxvargrad_i; - AuxVar_Grad_j = val_auxvargrad_j; -} - -inline void CNumerics::SetNormal(su2double *val_normal) { Normal = val_normal; } - -inline void CNumerics::SetVolume(su2double val_volume) { Volume = val_volume; } - -inline void CNumerics::SetDissipation(su2double diss_i, su2double diss_j) { - Dissipation_i = diss_i; - Dissipation_j = diss_j; -} - -inline su2double CNumerics::GetDissipation(){ - return Dissipation_ij; -} - -inline void CSourcePieceWise_TurbSST::SetF1blending(su2double val_F1_i, su2double val_F1_j) { - F1_i = val_F1_i; - F1_j = val_F1_j; -} - -inline void CSourcePieceWise_TurbSST::SetF2blending(su2double val_F2_i, su2double val_F2_j) { - F2_i = val_F2_i; - F2_j = val_F2_j; -} - -inline void CSourcePieceWise_TurbSST::SetCrossDiff(su2double val_CDkw_i, su2double val_CDkw_j) { - CDkw_i = val_CDkw_i; - CDkw_j = val_CDkw_j; -} - -inline void CSourcePieceWise_TurbSA::SetIntermittency(su2double intermittency_in) { intermittency = intermittency_in; } - -inline void CSourcePieceWise_TurbSA::SetProduction(su2double val_production) { Production = val_production; } - -inline void CSourcePieceWise_TurbSA::SetDestruction(su2double val_destruction) { Destruction = val_destruction; } - -inline void CSourcePieceWise_TurbSA::SetCrossProduction(su2double val_crossproduction) { CrossProduction = val_crossproduction; } - -inline su2double CSourcePieceWise_TurbSA::GetProduction(void) { return Production; } - -inline su2double CSourcePieceWise_TurbSA::GetGammaBC(void) { return gamma_BC; } - -inline su2double CSourcePieceWise_TurbSA::GetDestruction(void) { return Destruction; } - -inline su2double CSourcePieceWise_TurbSA::GetCrossProduction(void) { return CrossProduction; } - -inline void CSourcePieceWise_TurbSA_E::SetIntermittency(su2double intermittency_in) { intermittency = intermittency_in; } - -inline void CSourcePieceWise_TurbSA_E::SetProduction(su2double val_production) { Production = val_production; } - -inline void CSourcePieceWise_TurbSA_E::SetDestruction(su2double val_destruction) { Destruction = val_destruction; } - -inline void CSourcePieceWise_TurbSA_E::SetCrossProduction(su2double val_crossproduction) { CrossProduction = val_crossproduction; } - -inline su2double CSourcePieceWise_TurbSA_E::GetProduction(void) { return Production; } - -inline su2double CSourcePieceWise_TurbSA_E::GetDestruction(void) { return Destruction; } - -inline su2double CSourcePieceWise_TurbSA_E::GetCrossProduction(void) { return CrossProduction; } - -inline void CSourcePieceWise_TurbSA_E_COMP::SetIntermittency(su2double intermittency_in) { intermittency = intermittency_in; } - -inline void CSourcePieceWise_TurbSA_E_COMP::SetProduction(su2double val_production) { Production = val_production; } - -inline void CSourcePieceWise_TurbSA_E_COMP::SetDestruction(su2double val_destruction) { Destruction = val_destruction; } - -inline void CSourcePieceWise_TurbSA_E_COMP::SetCrossProduction(su2double val_crossproduction) { CrossProduction = val_crossproduction; } - -inline su2double CSourcePieceWise_TurbSA_E_COMP::GetProduction(void) { return Production; } - -inline su2double CSourcePieceWise_TurbSA_E_COMP::GetDestruction(void) { return Destruction; } - -inline su2double CSourcePieceWise_TurbSA_E_COMP::GetCrossProduction(void) { return CrossProduction; } - -inline void CSourcePieceWise_TurbSA_COMP::SetIntermittency(su2double intermittency_in) { intermittency = intermittency_in; } - -inline void CSourcePieceWise_TurbSA_COMP::SetProduction(su2double val_production) { Production = val_production; } - -inline void CSourcePieceWise_TurbSA_COMP::SetDestruction(su2double val_destruction) { Destruction = val_destruction; } - -inline void CSourcePieceWise_TurbSA_COMP::SetCrossProduction(su2double val_crossproduction) { CrossProduction = val_crossproduction; } - -inline su2double CSourcePieceWise_TurbSA_COMP::GetProduction(void) { return Production; } - -inline su2double CSourcePieceWise_TurbSA_COMP::GetDestruction(void) { return Destruction; } - -inline su2double CSourcePieceWise_TurbSA_COMP::GetCrossProduction(void) { return CrossProduction; } - -inline void CSourcePieceWise_TurbSA_Neg::SetIntermittency(su2double intermittency_in) { intermittency = intermittency_in; } - -inline void CSourcePieceWise_TurbSA_Neg::SetProduction(su2double val_production) { Production = val_production; } - -inline void CSourcePieceWise_TurbSA_Neg::SetDestruction(su2double val_destruction) { Destruction = val_destruction; } - -inline void CSourcePieceWise_TurbSA_Neg::SetCrossProduction(su2double val_crossproduction) { CrossProduction = val_crossproduction; } - -inline su2double CSourcePieceWise_TurbSA_Neg::GetProduction(void) { return Production; } - -inline su2double CSourcePieceWise_TurbSA_Neg::GetDestruction(void) { return Destruction; } - -inline su2double CSourcePieceWise_TurbSA_Neg::GetCrossProduction(void) { return CrossProduction; } - -inline void CNumerics::ComputeResidual(su2double **val_Jacobian_i, su2double *val_Jacobian_mui, su2double ***val_Jacobian_gradi, CConfig *config) { } - -inline void CNumerics::ComputeResidual(su2double **val_Jacobian_i, su2double *val_Jacobian_mui, su2double ***val_Jacobian_gradi, - su2double **val_Jacobian_j, su2double *val_Jacobian_muj, su2double ***val_Jacobian_gradj, CConfig *config) { } - -inline void CNumerics::SetTauWall(su2double val_tauwall_i, su2double val_tauwall_j) { } - -inline void CAvgGrad_Base::SetTauWall(su2double val_tauwall_i, su2double val_tauwall_j) { - TauWall_i = val_tauwall_i; - TauWall_j = val_tauwall_j; -} - -inline su2double CAvgGrad_Base::GetStressTensor(unsigned short iDim, unsigned short jDim) const { - return tau[iDim][jDim]; -} - -inline su2double CAvgGrad_Base::GetHeatFluxVector(unsigned short iDim) const { - return heat_flux_vector[iDim]; -} - -inline void CNumerics::SetUsing_UQ(bool val_using_uq) { using_uq = val_using_uq; } diff --git a/SU2_CFD/include/solvers/CAdjEulerSolver.hpp b/SU2_CFD/include/solvers/CAdjEulerSolver.hpp index 03267441250a..2da69ba120ce 100644 --- a/SU2_CFD/include/solvers/CAdjEulerSolver.hpp +++ b/SU2_CFD/include/solvers/CAdjEulerSolver.hpp @@ -124,7 +124,7 @@ class CAdjEulerSolver : public CSolver { * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - void Set_MPI_ActDisk(CSolver **solver_container, CGeometry *geometry, CConfig *config) final; + void Set_MPI_ActDisk(CSolver **solver_container, CGeometry *geometry, CConfig *config); /*! * \brief Created the force projection vector for adjoint boundary conditions. @@ -169,14 +169,14 @@ class CAdjEulerSolver : public CSolver { * \brief Compute the spatial integration using a centered scheme for the adjoint equations. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Centered_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) final; @@ -185,13 +185,13 @@ class CAdjEulerSolver : public CSolver { * \brief Compute the spatial integration using a upwind scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Upwind_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) final; @@ -199,16 +199,15 @@ class CAdjEulerSolver : public CSolver { * \brief Source term integration. * \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] second_numerics - Description of the second numerical method. + * \param[in] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) override; + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) override; /*! * \brief Source term integration. @@ -229,7 +228,7 @@ class CAdjEulerSolver : public CSolver { * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - void SetUndivided_Laplacian(CGeometry *geometry, CConfig *config) final; + void SetUndivided_Laplacian(CGeometry *geometry, CConfig *config); /*! * \brief Value of the characteristic variables at the boundaries. @@ -292,7 +291,7 @@ class CAdjEulerSolver : public CSolver { * \param[in] solver_container - Container vector with all the solutions. * \param[in] config - Definition of the particular problem. */ - void SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *config) final; + void SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *config); /*! * \brief Update the AoA and freestream velocity at the farfield. @@ -306,7 +305,7 @@ class CAdjEulerSolver : public CSolver { CSolver **solver_container, CConfig *config, unsigned short iMesh, - bool Output) final; + bool Output); /*! * \brief Impose via the residual the adjoint Euler wall boundary condition. @@ -710,4 +709,4 @@ class CAdjEulerSolver : public CSolver { int val_iter, bool val_update_geo) final; -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CAdjNSSolver.hpp b/SU2_CFD/include/solvers/CAdjNSSolver.hpp index ebb89b80af79..0bc66d1ca63a 100644 --- a/SU2_CFD/include/solvers/CAdjNSSolver.hpp +++ b/SU2_CFD/include/solvers/CAdjNSSolver.hpp @@ -124,7 +124,7 @@ class CAdjNSSolver final : public CAdjEulerSolver { * \brief Compute the viscous sensitivity of the functional. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. */ void Viscous_Sensitivity(CGeometry *geometry, @@ -143,7 +143,7 @@ class CAdjNSSolver final : public CAdjEulerSolver { */ void Viscous_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) override; @@ -152,15 +152,14 @@ class CAdjNSSolver final : public CAdjEulerSolver { * \brief Source term computation. * \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] second_numerics - Description of the second numerical method. + * \param[in] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) override; + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) override; -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CAdjTurbSolver.hpp b/SU2_CFD/include/solvers/CAdjTurbSolver.hpp index 717318ac9651..043274bfaa2e 100644 --- a/SU2_CFD/include/solvers/CAdjTurbSolver.hpp +++ b/SU2_CFD/include/solvers/CAdjTurbSolver.hpp @@ -139,13 +139,13 @@ class CAdjTurbSolver final : public CSolver { * \brief Compute the spatial integration using a upwind scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Upwind_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) override; @@ -153,14 +153,14 @@ class CAdjTurbSolver final : public CSolver { * \brief Compute the viscous residuals for the turbulent adjoint equation. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Viscous_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) override; @@ -169,16 +169,15 @@ class CAdjTurbSolver final : public CSolver { * \brief Source term computation. * \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] second_numerics - Description of the second numerical method. + * \param[in] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) override; + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) override; /*! * \brief Update the solution using an implicit solver. diff --git a/SU2_CFD/include/solvers/CDiscAdjFEASolver.hpp b/SU2_CFD/include/solvers/CDiscAdjFEASolver.hpp index 496e6c511c74..7a8dae08c24c 100644 --- a/SU2_CFD/include/solvers/CDiscAdjFEASolver.hpp +++ b/SU2_CFD/include/solvers/CDiscAdjFEASolver.hpp @@ -38,61 +38,59 @@ */ class CDiscAdjFEASolver final : public CSolver { private: - unsigned short KindDirect_Solver; - CSolver *direct_solver; - su2double *Sens_E, /*!< \brief Young modulus sensitivity coefficient for each boundary. */ - *Sens_Nu, /*!< \brief Poisson's ratio sensitivity coefficient for each boundary. */ - *Sens_nL, /*!< \brief Normal pressure sensitivity coefficient for each boundary. */ - **CSensitivity; /*!< \brief Shape sensitivity coefficient for each boundary and vertex. */ - - su2double *Solution_Vel, /*!< \brief Velocity componenent of the solution. */ - *Solution_Accel; /*!< \brief Acceleration componenent of the solution. */ - - su2double *SolRest; /*!< \brief Auxiliary vector to restart the solution */ - - su2double ObjFunc_Value; /*!< \brief Value of the objective function. */ - su2double *normalLoads; /*!< \brief Values of the normal loads for each marker iMarker_nL. */ - unsigned long nMarker_nL; /*!< \brief Total number of markers that have a normal load applied. */ - - unsigned short nMPROP; /*!< \brief Number of material properties */ - - su2double *E_i, /*!< \brief Values of the Young's Modulus. */ - *Nu_i, /*!< \brief Values of the Poisson's ratio. */ - *Rho_i, /*!< \brief Values of the density (for inertial effects). */ - *Rho_DL_i; /*!< \brief Values of the density (for volume loading). */ - int *AD_Idx_E_i, /*!< \brief Derivative index of the Young's Modulus. */ - *AD_Idx_Nu_i, /*!< \brief Derivative index of the Poisson's ratio. */ - *AD_Idx_Rho_i, /*!< \brief Derivative index of the density (for inertial effects). */ - *AD_Idx_Rho_DL_i; /*!< \brief Derivative index of the density (for volume loading). */ - - su2double *Local_Sens_E, /*!< \brief Local sensitivity of the Young's modulus. */ - *Global_Sens_E, /*!< \brief Global sensitivity of the Young's modulus. */ - *Total_Sens_E; /*!< \brief Total sensitivity of the Young's modulus (time domain). */ - su2double *Local_Sens_Nu, /*!< \brief Local sensitivity of the Poisson ratio. */ - *Global_Sens_Nu, /*!< \brief Global sensitivity of the Poisson ratio. */ - *Total_Sens_Nu; /*!< \brief Total sensitivity of the Poisson ratio (time domain). */ - su2double *Local_Sens_Rho, /*!< \brief Local sensitivity of the density. */ - *Global_Sens_Rho, /*!< \brief Global sensitivity of the density. */ - *Total_Sens_Rho; /*!< \brief Total sensitivity of the density (time domain). */ - su2double *Local_Sens_Rho_DL, /*!< \brief Local sensitivity of the volume load. */ - *Global_Sens_Rho_DL, /*!< \brief Global sensitivity of the volume load. */ - *Total_Sens_Rho_DL; /*!< \brief Total sensitivity of the volume load (time domain). */ - - bool de_effects; /*!< \brief Determines if DE effects are considered. */ - unsigned short nEField; /*!< \brief Number of electric field areas in the problem. */ - su2double *EField; /*!< \brief Array that stores the electric field as design variables. */ - int *AD_Idx_EField; /*!< \brief Derivative index of the electric field as design variables. */ - su2double *Local_Sens_EField, /*!< \brief Local sensitivity of the Electric Field. */ - *Global_Sens_EField, /*!< \brief Global sensitivity of the Electric Field. */ - *Total_Sens_EField; /*!< \brief Total sensitivity of the Electric Field (time domain). */ - - bool fea_dv; /*!< \brief Determines if the design variable we study is a FEA parameter. */ - unsigned short nDV; /*!< \brief Number of design variables in the problem. */ - su2double *DV_Val; /*!< \brief Values of the design variables. */ - int *AD_Idx_DV_Val; /*!< \brief Derivative index of the design variables. */ - su2double *Local_Sens_DV, /*!< \brief Local sensitivity of the design variables. */ - *Global_Sens_DV, /*!< \brief Global sensitivity of the design variables. */ - *Total_Sens_DV; /*!< \brief Total sensitivity of the design variables (time domain). */ + unsigned short KindDirect_Solver = 0; + CSolver *direct_solver = nullptr; + su2double *Sens_E = nullptr, /*!< \brief Young modulus sensitivity coefficient for each boundary. */ + *Sens_Nu = nullptr, /*!< \brief Poisson's ratio sensitivity coefficient for each boundary. */ + *Sens_nL = nullptr, /*!< \brief Normal pressure sensitivity coefficient for each boundary. */ + **CSensitivity = nullptr; /*!< \brief Shape sensitivity coefficient for each boundary and vertex. */ + + su2double *Solution_Vel = nullptr, /*!< \brief Velocity componenent of the solution. */ + *Solution_Accel = nullptr; /*!< \brief Acceleration componenent of the solution. */ + + su2double ObjFunc_Value = 0.0; /*!< \brief Value of the objective function. */ + su2double *normalLoads = nullptr; /*!< \brief Values of the normal loads for each marker iMarker_nL. */ + unsigned long nMarker_nL = 0; /*!< \brief Total number of markers that have a normal load applied. */ + + unsigned short nMPROP = 0; /*!< \brief Number of material properties */ + + su2double *E_i = nullptr, /*!< \brief Values of the Young's Modulus. */ + *Nu_i = nullptr, /*!< \brief Values of the Poisson's ratio. */ + *Rho_i = nullptr, /*!< \brief Values of the density (for inertial effects). */ + *Rho_DL_i = nullptr; /*!< \brief Values of the density (for volume loading). */ + int *AD_Idx_E_i = nullptr, /*!< \brief Derivative index of the Young's Modulus. */ + *AD_Idx_Nu_i = nullptr, /*!< \brief Derivative index of the Poisson's ratio. */ + *AD_Idx_Rho_i = nullptr, /*!< \brief Derivative index of the density (for inertial effects). */ + *AD_Idx_Rho_DL_i = nullptr; /*!< \brief Derivative index of the density (for volume loading). */ + + su2double *Local_Sens_E = nullptr, /*!< \brief Local sensitivity of the Young's modulus. */ + *Global_Sens_E = nullptr, /*!< \brief Global sensitivity of the Young's modulus. */ + *Total_Sens_E = nullptr; /*!< \brief Total sensitivity of the Young's modulus (time domain). */ + su2double *Local_Sens_Nu = nullptr, /*!< \brief Local sensitivity of the Poisson ratio. */ + *Global_Sens_Nu = nullptr, /*!< \brief Global sensitivity of the Poisson ratio. */ + *Total_Sens_Nu = nullptr; /*!< \brief Total sensitivity of the Poisson ratio (time domain). */ + su2double *Local_Sens_Rho = nullptr, /*!< \brief Local sensitivity of the density. */ + *Global_Sens_Rho = nullptr, /*!< \brief Global sensitivity of the density. */ + *Total_Sens_Rho = nullptr; /*!< \brief Total sensitivity of the density (time domain). */ + su2double *Local_Sens_Rho_DL = nullptr, /*!< \brief Local sensitivity of the volume load. */ + *Global_Sens_Rho_DL = nullptr, /*!< \brief Global sensitivity of the volume load. */ + *Total_Sens_Rho_DL = nullptr; /*!< \brief Total sensitivity of the volume load (time domain). */ + + bool de_effects = false; /*!< \brief Determines if DE effects are considered. */ + unsigned short nEField = 0; /*!< \brief Number of electric field areas in the problem. */ + su2double *EField = nullptr; /*!< \brief Array that stores the electric field as design variables. */ + int *AD_Idx_EField = nullptr; /*!< \brief Derivative index of the electric field as design variables. */ + su2double *Local_Sens_EField = nullptr, /*!< \brief Local sensitivity of the Electric Field. */ + *Global_Sens_EField = nullptr, /*!< \brief Global sensitivity of the Electric Field. */ + *Total_Sens_EField = nullptr; /*!< \brief Total sensitivity of the Electric Field (time domain). */ + + bool fea_dv = false; /*!< \brief Determines if the design variable we study is a FEA parameter. */ + unsigned short nDV = 0; /*!< \brief Number of design variables in the problem. */ + su2double *DV_Val = nullptr; /*!< \brief Values of the design variables. */ + int *AD_Idx_DV_Val = nullptr; /*!< \brief Derivative index of the design variables. */ + su2double *Local_Sens_DV = nullptr, /*!< \brief Local sensitivity of the design variables. */ + *Global_Sens_DV = nullptr, /*!< \brief Global sensitivity of the design variables. */ + *Total_Sens_DV = nullptr; /*!< \brief Total sensitivity of the design variables (time domain). */ CDiscAdjFEABoundVariable* nodes = nullptr; /*!< \brief The highest level in the variable hierarchy this solver can safely use. */ @@ -395,4 +393,4 @@ class CDiscAdjFEASolver final : public CSolver { */ void ComputeResidual_Multizone(CGeometry *geometry, CConfig *config) override; -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CEulerSolver.hpp b/SU2_CFD/include/solvers/CEulerSolver.hpp index bfc653f94587..d90129ef5f6d 100644 --- a/SU2_CFD/include/solvers/CEulerSolver.hpp +++ b/SU2_CFD/include/solvers/CEulerSolver.hpp @@ -29,6 +29,7 @@ #include "CSolver.hpp" #include "../variables/CEulerVariable.hpp" +#include "../../../Common/include/omp_structure.hpp" /*! * \class CSolver @@ -38,292 +39,355 @@ */ class CEulerSolver : public CSolver { 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. */ - su2double - Mach_Inf, /*!< \brief Mach number at the infinity. */ - Density_Inf, /*!< \brief Density at the infinity. */ - Energy_Inf, /*!< \brief Energy at the infinity. */ - Temperature_Inf, /*!< \brief Energy at the infinity. */ - Pressure_Inf, /*!< \brief Pressure at the infinity. */ - *Velocity_Inf; /*!< \brief Flow Velocity vector at the infinity. */ + 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 - *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. */ - *CEquivArea_Inv, /*!< \brief Equivalent area (inviscid contribution) for each boundary. */ - *CNearFieldOF_Inv, /*!< \brief Near field pressure (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. */ - *CEquivArea_Mnt, /*!< \brief Equivalent area (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. */ - ***DonorPrimVar, /*!< \brief Value of the donor 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. */ - su2double - *Inflow_MassFlow, /*!< \brief Mass flow rate for each boundary. */ - *Exhaust_MassFlow, /*!< \brief Mass flow rate for each boundary. */ - *Inflow_Pressure, /*!< \brief Fan face pressure for each boundary. */ - *Inflow_Mach, /*!< \brief Fan face mach number for each boundary. */ - *Inflow_Area, /*!< \brief Boundary total area. */ - *Exhaust_Area, /*!< \brief Boundary total area. */ - *Exhaust_Pressure, /*!< \brief Fan face pressure for each boundary. */ - *Exhaust_Temperature, /*!< \brief Fan face mach number for each boundary. */ - Inflow_MassFlow_Total, /*!< \brief Mass flow rate for each boundary. */ - Exhaust_MassFlow_Total, /*!< \brief Mass flow rate for each boundary. */ - Inflow_Pressure_Total, /*!< \brief Fan face pressure for each boundary. */ - Inflow_Mach_Total, /*!< \brief Fan face mach number for each boundary. */ - InverseDesign; /*!< \brief Inverse design functional for each boundary. */ - unsigned long - **DonorGlobalIndex; /*!< \brief Value of the donor global index. */ - su2double - **ActDisk_DeltaP, /*!< \brief Value of the Delta P. */ - **ActDisk_DeltaT; /*!< \brief Value of the Delta T. */ + 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 - **Inlet_Ptotal, /*!< \brief Value of the Total P. */ - **Inlet_Ttotal, /*!< \brief Value of the Total T. */ - ***Inlet_FlowDir; /*!< \brief Value of the Flow Direction. */ + 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_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_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_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_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. */ - AllBound_CEquivArea_Inv, /*!< \brief equivalent area coefficient (inviscid contribution) for all the boundaries. */ - AllBound_CNearFieldOF_Inv; /*!< \brief Near-Field press coefficient (inviscid contribution) for all the boundaries. */ + 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_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_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_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_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. */ + *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. */ 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_CL_Prev, /*!< \brief Total lift coefficient for all the boundaries (fixed lift mode). */ - Total_SolidCD, /*!< \brief Total drag coefficient for all the boundaries. */ - Total_CD_Prev, /*!< \brief Total drag coefficient for all the boundaries (fixed lift mode). */ - Total_NetThrust, /*!< \brief Total drag coefficient for all the boundaries. */ - Total_Power, /*!< \brief Total drag coefficient for all the boundaries. */ - Total_ReverseFlow, /*!< \brief Total drag coefficient for all the boundaries. */ - Total_IDC, /*!< \brief Total IDC coefficient for all the boundaries. */ - Total_IDC_Mach, /*!< \brief Total IDC coefficient for all the boundaries. */ - Total_IDR, /*!< \brief Total IDC coefficient for all the boundaries. */ - Total_DC60, /*!< \brief Total IDC coefficient for all the boundaries. */ - Total_MFR, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ - Total_Prop_Eff, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ - Total_ByPassProp_Eff, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ - Total_Adiab_Eff, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ - Total_Poly_Eff, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ - Total_Custom_ObjFunc, /*!< \brief Total custom objective function 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_CMx_Prev, /*!< \brief Total drag coefficient for all the boundaries (fixed lift mode). */ - Total_CMy, /*!< \brief Total y moment coefficient for all the boundaries. */ - Total_CMy_Prev, /*!< \brief Total drag coefficient for all the boundaries (fixed lift mode). */ - Total_CMz, /*!< \brief Total z moment coefficient for all the boundaries. */ - Total_CMz_Prev, /*!< \brief Total drag coefficient for all the boundaries (fixed lift mode). */ - 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_AeroCD, /*!< \brief Total aero drag coefficient for all the boundaries. */ - Total_CEquivArea, /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ - Total_CNearFieldOF, /*!< \brief Total Near-Field Pressure coefficient for all the boundaries. */ - Total_CpDiff, /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ - Total_HeatFluxDiff, /*!< \brief Total Equivalent Area coefficient for all the boundaries. */ - Total_MassFlowRate; /*!< \brief Total Mass Flow Rate on monitored boundaries. */ + *Inflow_MassFlow = nullptr, /*!< \brief Mass flow rate for each boundary. */ + *Exhaust_MassFlow = nullptr, /*!< \brief Mass flow rate for each boundary. */ + *Inflow_Pressure = nullptr, /*!< \brief Fan face pressure for each boundary. */ + *Inflow_Mach = nullptr, /*!< \brief Fan face mach number for each boundary. */ + *Inflow_Area = nullptr, /*!< \brief Boundary total area. */ + *Exhaust_Area = nullptr, /*!< \brief Boundary total area. */ + *Exhaust_Pressure = nullptr, /*!< \brief Fan face pressure for each boundary. */ + *Exhaust_Temperature = nullptr,/*!< \brief Fan face mach number for each boundary. */ + Inflow_MassFlow_Total = 0.0, /*!< \brief Mass flow rate for each boundary. */ + Exhaust_MassFlow_Total = 0.0, /*!< \brief Mass flow rate for each boundary. */ + Inflow_Pressure_Total = 0.0, /*!< \brief Fan face pressure for each boundary. */ + Inflow_Mach_Total = 0.0, /*!< \brief Fan face mach number for each boundary. */ + InverseDesign = 0.0; /*!< \brief Inverse design functional for each boundary. */ + unsigned long + **DonorGlobalIndex = nullptr; /*!< \brief Value of the donor global index. */ 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. */ + **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. */ 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. */ + 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). */ + Total_NetThrust = 0.0, /*!< \brief Total drag coefficient for all the boundaries. */ + Total_Power = 0.0, /*!< \brief Total drag coefficient for all the boundaries. */ + Total_ReverseFlow = 0.0, /*!< \brief Total drag coefficient for all the boundaries. */ + Total_IDC = 0.0, /*!< \brief Total IDC coefficient for all the boundaries. */ + Total_IDC_Mach = 0.0, /*!< \brief Total IDC coefficient for all the boundaries. */ + Total_IDR = 0.0, /*!< \brief Total IDC coefficient for all the boundaries. */ + Total_DC60 = 0.0, /*!< \brief Total IDC coefficient for all the boundaries. */ + Total_MFR = 0.0, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ + Total_Prop_Eff = 0.0, /*!< \brief Total Mass Flow Ratio for all the boundaries. */ + 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 - *PrimVar_i, /*!< \brief Auxiliary vector for storing the solution at point i. */ - *PrimVar_j; /*!< \brief Auxiliary vector for storing the solution at point j. */ - su2double **LowMach_Precontioner; /*!< \brief Auxiliary vector for storing the inverse of Roe-turkel preconditioner. */ - 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. */ - - su2double *Secondary, /*!< \brief Auxiliary nPrimVar vector. */ - *Secondary_i, /*!< \brief Auxiliary nPrimVar vector for storing the primitive at point i. */ - *Secondary_j; /*!< \brief Auxiliary nPrimVar vector for storing the primitive at point j. */ - - su2double AoA_Prev, /*!< \brief Old value of the angle of attack (monitored). */ + *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 . */ + + su2double AoA_Prev, /*!< \brief Old value of the angle of attack (monitored). */ AoA_inc; - bool Start_AoA_FD, /*!< \brief Boolean for start of finite differencing for FixedCL mode */ - End_AoA_FD, /*!< \brief Boolean for end of finite differencing for FixedCL mode */ - Update_AoA; /*!< \brief Boolean to signal Angle of Attack Update */ - unsigned long Iter_Update_AoA; /*!< \brief Iteration at which AoA was updated last */ - su2double dCL_dAlpha; /*!< \brief Value of dCL_dAlpha used to control CL in fixed CL mode */ + bool Start_AoA_FD = false, /*!< \brief Boolean for start of finite differencing for FixedCL mode */ + End_AoA_FD = false, /*!< \brief Boolean for end of finite differencing for FixedCL mode */ + Update_AoA = false; /*!< \brief Boolean to signal Angle of Attack Update */ + unsigned long Iter_Update_AoA = 0; /*!< \brief Iteration at which AoA was updated last */ + su2double dCL_dAlpha; /*!< \brief Value of dCL_dAlpha used to control CL in fixed CL mode */ unsigned long BCThrust_Counter; unsigned short nSpanWiseSections; /*!< \brief Number of span-wise sections. */ - unsigned short nSpanMax; /*!< \brief Max number of maximum span-wise sections for all zones */ + unsigned short nSpanMax; /*!< \brief Max number of maximum span-wise sections for all zones. */ unsigned short nMarkerTurboPerf; /*!< \brief Number of turbo performance. */ - CFluidModel *FluidModel; /*!< \brief fluid model used in the solver */ + vector FluidModel; /*!< \brief fluid model used in the solver. */ + + unsigned long ErrorCounter = 0; /*!< \brief Counter for number of un-physical states. */ + + su2double Global_Delta_Time = 0.0, /*!< \brief Time-step for TIME_STEPPING time marching strategy. */ + Global_Delta_UnstTimeND = 0.0; /*!< \brief Unsteady time step for the dual time strategy. */ /*--- Turbomachinery Solver Variables ---*/ - su2double *** AverageFlux, - ***SpanTotalFlux, - ***AverageVelocity, - ***AverageTurboVelocity, - ***OldAverageTurboVelocity, - ***ExtAverageTurboVelocity, - **AveragePressure, - **OldAveragePressure, - **RadialEquilibriumPressure, - **ExtAveragePressure, - **AverageDensity, - **OldAverageDensity, - **ExtAverageDensity, - **AverageNu, - **AverageKine, - **AverageOmega, - **ExtAverageNu, - **ExtAverageKine, - **ExtAverageOmega; - - su2double **DensityIn, - **PressureIn, - ***TurboVelocityIn, - **DensityOut, - **PressureOut, - ***TurboVelocityOut, - **KineIn, - **OmegaIn, - **NuIn, - **KineOut, - **OmegaOut, - **NuOut; - - complex ***CkInflow, - ***CkOutflow1, - ***CkOutflow2; - - /*--- End of Turbomachinery Solver Variables ---*/ - - /* Sliding meshes variables */ - - su2double ****SlidingState; - int **SlidingStateNodes; - - CEulerVariable* nodes = nullptr; /*!< \brief The highest level in the variable hierarchy this solver can safely use. */ + + su2double ***AverageFlux = nullptr, + ***SpanTotalFlux = nullptr, + ***AverageVelocity = nullptr, + ***AverageTurboVelocity = nullptr, + ***OldAverageTurboVelocity = nullptr, + ***ExtAverageTurboVelocity = nullptr, + **AveragePressure = nullptr, + **OldAveragePressure = nullptr, + **RadialEquilibriumPressure = nullptr, + **ExtAveragePressure = nullptr, + **AverageDensity = nullptr, + **OldAverageDensity = nullptr, + **ExtAverageDensity = nullptr, + **AverageNu = nullptr, + **AverageKine = nullptr, + **AverageOmega = nullptr, + **ExtAverageNu = nullptr, + **ExtAverageKine = nullptr, + **ExtAverageOmega = nullptr; + + su2double **DensityIn = nullptr, + **PressureIn = nullptr, + ***TurboVelocityIn = nullptr, + **DensityOut = nullptr, + **PressureOut = nullptr, + ***TurboVelocityOut = nullptr, + **KineIn = nullptr, + **OmegaIn = nullptr, + **NuIn = nullptr, + **KineOut = nullptr, + **OmegaOut = nullptr, + **NuOut = nullptr; + + complex ***CkInflow = nullptr, + ***CkOutflow1 = nullptr, + ***CkOutflow2 = nullptr; + + /*--- 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. */ +#else + array,1> EdgeColoring; +#endif + unsigned long ColorGroupSize; /*!< \brief Group size used for coloring, chunk size in edge loops must be a multiple of this. */ + + /*--- Edge fluxes, for OpenMP parallelization on coarse grids. As it is difficult to + * color them, 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. coarse grids and + * with more than one thread per MPI rank. ---*/ + + 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; } -public: + /*! + * \brief Generic implementation of explicit iterations (RK, Classic RK and EULER). + */ + template + void Explicit_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iRKStep); + + /*! + * \brief Sum the edge fluxes for each cell to populate the residual vector, only used on coarse grids. + * \param[in] geometry - Geometrical definition of the problem. + */ + void SumEdgeFluxes(CGeometry* geometry); + + /*! + * \brief Update the AoA and freestream velocity at the farfield. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - current mesh level for the multigrid. + * \param[in] Output - boolean to determine whether to print output. + */ + void SetFarfield_AoA(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iMesh, bool Output); + + /*! + * \brief Compute a pressure sensor switch. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + */ + void SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *config); + + /*! + * \brief Compute Ducros Sensor for Roe Dissipation. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + */ + void SetUpwind_Ducros_Sensor(CGeometry *geometry, CConfig *config); + /*! + * \brief Compute the Fan face Mach number. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solution - Container vector with all the solutions. + */ + void GetPower_Properties(CGeometry *geometry, CConfig *config, + unsigned short iMesh, bool Output); + + /*! + * \brief Parallelization of Undivided Laplacian. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + */ + void Set_MPI_ActDisk(CSolver **solver_container, CGeometry *geometry, CConfig *config); + + /*! + * \brief Update the AoA and freestream velocity at the farfield. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] iMesh - current mesh level for the multigrid. + * \param[in] Output - boolean to determine whether to print output. + */ + void SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iMesh, bool Output); + + /*! + * \brief Compute the max eigenvalue. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + */ + void SetMax_Eigenvalue(CGeometry *geometry, CConfig *config); + + /*! + * \brief Compute the undivided laplacian for the solution, except the energy equation. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] config - Definition of the particular problem. + */ + void SetUndivided_Laplacian(CGeometry *geometry, CConfig *config); + + /*! + * \brief A virtual member. + * \param[in] geometry - Geometrical definition. + * \param[in] config - Definition of the particular problem. + */ + inline virtual void SetRoe_Dissipation(CGeometry *geometry, CConfig *config) { } + +private: + /*! + * \brief Compute the velocity^2, SoundSpeed, Pressure, Enthalpy, Viscosity. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] Output - boolean to determine whether to print output. + * \return - The number of non-physical points. + */ + unsigned long SetPrimitive_Variables(CSolver **solver_container, + CConfig *config, + bool Output); + +protected: + +public: /*! * \brief Constructor of the class. @@ -331,11 +395,13 @@ class CEulerSolver : public CSolver { CEulerSolver(void); /*! - * \overload + * \overload Main constructor of this class. * \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 CNSSolver. */ - CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh); + CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh, const bool navier_stokes = false); /*! * \brief Destructor of the class. @@ -353,7 +419,7 @@ class CEulerSolver : public CSolver { * \brief Compute the pressure at the infinity. * \return Value of the pressure at the infinity. */ - inline CFluidModel* GetFluidModel(void) const final { return FluidModel;} + inline CFluidModel* GetFluidModel(void) const final { return FluidModel[omp_get_thread_num()]; } /*! * \brief Compute the density at the infinity. @@ -403,7 +469,7 @@ class CEulerSolver : public CSolver { * \brief Get the velocity at the infinity. * \return Value of the velocity at the infinity. */ - inline su2double *GetVelocity_Inf(void) const final { return Velocity_Inf; } + inline su2double *GetVelocity_Inf(void) final { return Velocity_Inf; } /*! * \brief Compute the time step for solving the Euler equations. @@ -417,20 +483,20 @@ class CEulerSolver : public CSolver { CSolver **solver_container, CConfig *config, unsigned short iMesh, - unsigned long Iteration) override; + unsigned long Iteration) final; /*! * \brief Compute the spatial integration using a centered scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Centered_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) final; @@ -439,37 +505,72 @@ class CEulerSolver : public CSolver { * \brief Compute the spatial integration using a upwind scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Upwind_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) final; /*! - * \brief Compute the extrapolated quantities, for MUSCL upwind 2nd reconstruction, - * in a more thermodynamic consistent way + * \brief Compute the viscous contribution for a particular edge. + * \note The convective residual methods include a call to this for each edge, + * this allows convective and viscous loops to be "fused". + * \param[in] iEdge - Edge for which the flux and Jacobians are to be computed. + * \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 ComputeConsExtrapolation(CConfig *config); + inline virtual void Viscous_Residual(unsigned long iEdge, CGeometry *geometry, CSolver **solver_container, + CNumerics *numerics, CConfig *config) { } + + /*! + * \brief Recompute the extrapolated quantities, after MUSCL reconstruction, + * in a more thermodynamically consistent way. + * \note This method is static to improve the chances of it being used in a + * thread-safe manner. + * \param[in,out] fluidModel - The fluid model. + * \param[in] nDim - Number of physical dimensions. + * \param[in,out] primitive - Primitive variables. + * \param[out] secondary - Secondary variables. + */ + static void ComputeConsistentExtrapolation(CFluidModel *fluidModel, + unsigned short nDim, + su2double *primitive, + su2double *secondary); + + /*! + * \brief Apply low Mach number correction to the primitives at two points, + * usually connected by an edge. + * \note This method is static to improve the chances of it being used in a + * thread-safe manner. + * \param[in,out] fluidModel - The fluid model. + * \param[in] nDim - Number of physical dimensions. + * \param[in,out] primitive_i - Primitive variables at point i. + * \param[in,out] primitive_j - Primitive variables at point j. + */ + static void LowMachPrimitiveCorrection(CFluidModel *fluidModel, + unsigned short nDim, + su2double *primitive_i, + su2double *primitive_j); /*! * \brief Source term integration. * \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] second_numerics - Description of the second numerical method. + * \param[in] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) override; + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) override; /*! * \brief Source term integration. @@ -502,45 +603,6 @@ class CEulerSolver : public CSolver { unsigned short RunTime_EqSystem, bool Output) override; - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - */ - void Postprocessing(CGeometry *geometry, - CSolver **solver_container, - CConfig *config, - unsigned short iMesh) final; - - /*! - * \brief Compute the velocity^2, SoundSpeed, Pressure, Enthalpy, Viscosity. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] Output - boolean to determine whether to print output. - * \return - The number of non-physical points. - */ - unsigned long SetPrimitive_Variables(CSolver **solver_container, - CConfig *config, - bool Output) override; - - /*! - * \brief Compute a pressure sensor switch. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - */ - void SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *config) final; - - /*! - * \brief Compute Ducros Sensor for Roe Dissipation. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - */ - void SetUpwind_Ducros_Sensor(CGeometry *geometry, CConfig *config) final; - /*! * \brief Compute the gradient of the primitive variables using Green-Gauss method, * and stores the result in the Gradient_Primitive variable. @@ -572,31 +634,13 @@ class CEulerSolver : public CSolver { /*! * \brief Compute the preconditioner for convergence acceleration by Roe-Turkel method. - * \param[in] iPoint - Index of the grid point * \param[in] config - Definition of the particular problem. + * \param[in] iPoint - Index of the grid point. + * \param[in] delta - Volume over delta t. + * \param[in,out] preconditioner - The preconditioner matrix, must be allocated outside. */ - void SetPreconditioner(CConfig *config, unsigned long iPoint) final; - - /*! - * \brief Compute the undivided laplacian for the solution, except the energy equation. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - void SetUndivided_Laplacian(CGeometry *geometry, CConfig *config) final; - - /*! - * \brief Compute the max eigenvalue. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - void SetMax_Eigenvalue(CGeometry *geometry, CConfig *config) final; - - /*! - * \brief Parallelization of Undivided Laplacian. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - */ - void Set_MPI_ActDisk(CSolver **solver_container, CGeometry *geometry, CConfig *config) final; + void SetPreconditioner(const CConfig *config, unsigned long iPoint, + su2double delta, su2double** preconditioner) const; /*! * \brief Parallelization of Undivided Laplacian. @@ -973,44 +1017,6 @@ class CEulerSolver : public CSolver { CConfig *config, unsigned short iRKStep) final; - /*! - * \brief Compute the Fan face Mach number. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solution - Container vector with all the solutions. - */ - void GetPower_Properties(CGeometry *geometry, - CConfig *config, - unsigned short iMesh, - bool Output) final; - - /*! - * \brief Update the AoA and freestream velocity at the farfield. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - current mesh level for the multigrid. - * \param[in] Output - boolean to determine whether to print output. - */ - void SetActDisk_BCThrust(CGeometry *geometry, - CSolver **solver_container, - CConfig *config, - unsigned short iMesh, - bool Output) final; - - /*! - * \brief Update the AoA and freestream velocity at the farfield. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - current mesh level for the multigrid. - * \param[in] Output - boolean to determine whether to print output. - */ - void SetFarfield_AoA(CGeometry *geometry, - CSolver **solver_container, - CConfig *config, - unsigned short iMesh, - bool Output) final; - /*! * \brief Check for convergence of the Fixed CL mode to the target CL * \param[in] config - Definition of the particular problem. @@ -1115,224 +1121,224 @@ class CEulerSolver : public CSolver { * \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 CL_Inv[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 Surface_CL[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 Surface_CD[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 Surface_CSF[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 Surface_CEff[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 Surface_CFx[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 Surface_CFy[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 Surface_CFz[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 Surface_CMx[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 Surface_CMy[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 Surface_CMz[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 Surface_CL_Inv[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 Surface_CD_Inv[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 Surface_CSF_Inv[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 Surface_CEff_Inv[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 Surface_CFx_Inv[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 Surface_CFy_Inv[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 Surface_CFz_Inv[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 Surface_CMx_Inv[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 Surface_CMy_Inv[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 Surface_CMz_Inv[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 Surface_CL_Mnt[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 Surface_CD_Mnt[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 Surface_CSF_Mnt[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 Surface_CEff_Mnt[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 Surface_CFx_Mnt[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 Surface_CFy_Mnt[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 Surface_CFz_Mnt[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 Surface_CMx_Mnt[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 Surface_CMy_Mnt[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 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]; } + inline su2double GetSurface_CMz_Mnt(unsigned short val_marker) const final { return SurfaceMntCoeff.CMz[val_marker]; } /*! * \brief Provide the mass flow rate. @@ -1367,26 +1373,26 @@ class CEulerSolver : public CSolver { * \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]; } + 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 CEff_Inv[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 Total_CSF; } + 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 Total_CEff; } + inline su2double GetTotal_CEff() const final { return TotalCoeff.CEff; } /*! * \brief Provide the total (inviscid + viscous) non dimensional Equivalent Area coefficient. @@ -1473,13 +1479,13 @@ class CEulerSolver : public CSolver { * \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; } + 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 Total_CD; } + inline su2double GetTotal_CD() const final { return TotalCoeff.CD; } /*! * \brief Provide the total (inviscid + viscous) non dimensional drag coefficient. @@ -1569,73 +1575,73 @@ class CEulerSolver : public CSolver { * \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; } + 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 Total_CMy; } + 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 Total_CMz; } + 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 Total_CoPx; } + 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 Total_CoPy; } + 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 Total_CoPz; } + 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 Total_CFx; } + 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 Total_CFy; } + 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 Total_CFz; } + 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 Total_CT; } + 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 { Total_CT = val_Total_CT; } + 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 Total_CQ; } + inline su2double GetTotal_CQ() const final { return TotalCoeff.CQ; } /*! * \brief Provide the total heat load. @@ -1653,7 +1659,7 @@ class CEulerSolver : public CSolver { * \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; } + inline void SetTotal_CQ(su2double val_Total_CQ) final { TotalCoeff.CQ = val_Total_CQ; } /*! * \brief Store the total heat load. @@ -1671,19 +1677,19 @@ class CEulerSolver : public CSolver { * \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; } + 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 { Total_CD = val_Total_CD; } + 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 { Total_CL = val_Total_CL; } + inline void SetTotal_CL(su2double val_Total_CL) final { TotalCoeff.CL = val_Total_CL; } /*! * \brief Store the total (inviscid + viscous) non dimensional drag coefficient. @@ -1785,157 +1791,157 @@ class CEulerSolver : public CSolver { * \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; } + 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 AllBound_CD_Inv; } + 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 AllBound_CSF_Inv; } + 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 AllBound_CEff_Inv; } + 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 AllBound_CMx_Inv; } + 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 AllBound_CMy_Inv; } + 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 AllBound_CMz_Inv; } + 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 AllBound_CoPx_Inv; } + 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 AllBound_CoPy_Inv; } + 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 AllBound_CoPz_Inv; } + 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 AllBound_CFx_Inv; } + 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 AllBound_CFy_Inv; } + 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 AllBound_CFz_Inv; } + 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 AllBound_CL_Mnt; } + 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 AllBound_CD_Mnt; } + 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 AllBound_CSF_Mnt; } + 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 AllBound_CEff_Mnt; } + 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 AllBound_CMx_Mnt; } + 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 AllBound_CMy_Mnt; } + 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 AllBound_CMz_Mnt; } + 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 AllBound_CoPx_Mnt; } + 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 AllBound_CoPy_Mnt; } + 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 AllBound_CoPz_Mnt; } + 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 AllBound_CFx_Mnt; } + 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 AllBound_CFy_Mnt; } + 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 AllBound_CFz_Mnt; } + inline su2double GetAllBound_CFz_Mnt() const final { return AllBoundMntCoeff.CFz; } /*! * \brief Provide the Pressure coefficient. @@ -2873,4 +2879,9 @@ class CEulerSolver : public CSolver { */ void ComputeVerificationError(CGeometry *geometry, CConfig *config) final; + /*! + * \brief The Euler and NS solvers support MPI+OpenMP (except the BC bits). + */ + inline bool GetHasHybridParallel() const final { return true; } + }; diff --git a/SU2_CFD/include/solvers/CFEASolver.hpp b/SU2_CFD/include/solvers/CFEASolver.hpp index 742573eb56d4..6d1f1ebf5eca 100644 --- a/SU2_CFD/include/solvers/CFEASolver.hpp +++ b/SU2_CFD/include/solvers/CFEASolver.hpp @@ -28,6 +28,7 @@ #pragma once #include "CSolver.hpp" +#include "../../../Common/include/omp_structure.hpp" /*! * \class CFEASolver @@ -38,7 +39,7 @@ class CFEASolver : public CSolver { protected: enum : size_t {MAXNNODE = 8}; enum : size_t {MAXNVAR = 3}; - enum : size_t {OMP_MIN_SIZE = 64}; + enum : size_t {OMP_MIN_SIZE = 32}; enum : size_t {OMP_MAX_SIZE = 512}; unsigned long omp_chunk_size; /*!< \brief Chunk size used in light point loops. */ @@ -74,20 +75,23 @@ class CFEASolver : public CSolver { su2double RelaxCoeff; /*!< \brief Relaxation coefficient . */ su2double FSI_Residual; /*!< \brief FSI residual. */ - struct ElemColor { - unsigned long size; /*!< \brief Number of elements with a given color. */ - const unsigned long* indices; /*!< \brief Array of element indices for a given color. */ - }; - vector ElemColoring; /*!< \brief Element colors. */ +#ifdef HAVE_OMP + vector > ElemColoring; /*!< \brief Element colors. */ +#else + array,1> ElemColoring; +#endif unsigned long ColorGroupSize; /*!< \brief Group size used for coloring, chunk size must be a multiple of this. */ bool element_based; /*!< \brief Bool to determine if an element-based file is used. */ bool topol_filter_applied; /*!< \brief True if density filtering has been performed. */ unsigned long nElement; /*!< \brief Number of elements. */ - unsigned long IterLinSol; /*!< \brief Number of iterations of the linear solver. */ - CVariable* nodes = nullptr; /*!< \brief The highest level in the variable hierarchy this solver can safely use. */ + /*! + * \brief The highest level in the variable hierarchy this solver can safely use, + * CVariable is the common denominator between the FEA and Mesh deformation variables. + */ + CVariable* nodes = nullptr; /*! * \brief Return nodes to allow CSolver::base_nodes to be set. diff --git a/SU2_CFD/include/solvers/CFEM_DG_EulerSolver.hpp b/SU2_CFD/include/solvers/CFEM_DG_EulerSolver.hpp index 0646564a5a22..1990d9767301 100644 --- a/SU2_CFD/include/solvers/CFEM_DG_EulerSolver.hpp +++ b/SU2_CFD/include/solvers/CFEM_DG_EulerSolver.hpp @@ -374,7 +374,7 @@ class CFEM_DG_EulerSolver : public CSolver { * \brief Get the velocity at the infinity. * \return Value of the velocity at the infinity. */ - inline su2double *GetVelocity_Inf(void) const final { return Velocity_Inf; } + inline su2double *GetVelocity_Inf(void) final { return Velocity_Inf; } /*! * \brief Set the freestream pressure. diff --git a/SU2_CFD/include/solvers/CFEM_DG_NSSolver.hpp b/SU2_CFD/include/solvers/CFEM_DG_NSSolver.hpp index ccb33005640c..9da05fa4a4e8 100644 --- a/SU2_CFD/include/solvers/CFEM_DG_NSSolver.hpp +++ b/SU2_CFD/include/solvers/CFEM_DG_NSSolver.hpp @@ -451,18 +451,6 @@ class CFEM_DG_NSSolver final : public CFEM_DG_EulerSolver { */ inline su2double GetStrainMag_Max(void) const override { return StrainMag_Max; } - /*! - * \brief A virtual member. - * \return Value of the StrainMag_Max - */ - inline void SetStrainMag_Max(su2double val_strainmag_max) override { StrainMag_Max = val_strainmag_max; } - - /*! - * \brief A virtual member. - * \return Value of the Omega_Max - */ - inline void SetOmega_Max(su2double val_omega_max) override { Omega_Max = val_omega_max; } - private: /*! @@ -928,4 +916,4 @@ class CFEM_DG_NSSolver final : public CFEM_DG_EulerSolver { su2double &Viscosity, su2double &kOverCv, su2double *normalFlux); -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CHeatSolver.hpp b/SU2_CFD/include/solvers/CHeatSolver.hpp index 7adb3a4f5381..c0cfb740a3d7 100644 --- a/SU2_CFD/include/solvers/CHeatSolver.hpp +++ b/SU2_CFD/include/solvers/CHeatSolver.hpp @@ -113,40 +113,25 @@ class CHeatSolver final : public CSolver { int val_iter, bool val_update_geo) override; - /*! - * \brief Source term computation. - * \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] second_numerics - Description of the second numerical method. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - */ - void Source_Residual(CGeometry *geometry, - CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) override; - /*! * \brief Compute the undivided laplacian for the solution. * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - void SetUndivided_Laplacian(CGeometry *geometry, CConfig *config) override; + void SetUndivided_Laplacian(CGeometry *geometry, CConfig *config); /*! * \brief Compute the spatial integration using a centered scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Centered_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) override; @@ -154,13 +139,13 @@ class CHeatSolver final : public CSolver { * \brief Compute the spatial integration using a upwind scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Upwind_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) override; @@ -168,14 +153,14 @@ class CHeatSolver final : public CSolver { * \brief Compute the viscous residuals for the turbulent equation. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Viscous_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) override; diff --git a/SU2_CFD/include/solvers/CIncEulerSolver.hpp b/SU2_CFD/include/solvers/CIncEulerSolver.hpp index 8f7111f751df..e2228fc5d66c 100644 --- a/SU2_CFD/include/solvers/CIncEulerSolver.hpp +++ b/SU2_CFD/include/solvers/CIncEulerSolver.hpp @@ -299,7 +299,7 @@ class CIncEulerSolver : public CSolver { * \brief Get the velocity at the infinity. * \return Value of the velocity at the infinity. */ - inline su2double *GetVelocity_Inf(void) const final { return Velocity_Inf; } + inline su2double *GetVelocity_Inf(void) final { return Velocity_Inf; } /*! * \brief Set the velocity at infinity. @@ -328,14 +328,14 @@ class CIncEulerSolver : public CSolver { * \brief Compute the spatial integration using a centered scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Centered_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) final; @@ -344,13 +344,13 @@ class CIncEulerSolver : public CSolver { * \brief Compute the spatial integration using a upwind scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Upwind_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) final; @@ -358,16 +358,15 @@ class CIncEulerSolver : public CSolver { * \brief Source term integration. * \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] second_numerics - Description of the second numerical method. + * \param[in] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) final; + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) final; /*! * \brief Source term integration. @@ -421,7 +420,7 @@ class CIncEulerSolver : public CSolver { */ unsigned long SetPrimitive_Variables(CSolver **solver_container, CConfig *config, - bool Output) override; + bool Output); /*! * \brief Compute a pressure sensor switch. @@ -429,7 +428,7 @@ class CIncEulerSolver : public CSolver { * \param[in] solver_container - Container vector with all the solutions. * \param[in] config - Definition of the particular problem. */ - void SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *config) final; + void SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *config); /*! * \brief Compute the gradient of the primitive variables using Green-Gauss method, @@ -465,14 +464,14 @@ class CIncEulerSolver : public CSolver { * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - void SetUndivided_Laplacian(CGeometry *geometry, CConfig *config) final; + void SetUndivided_Laplacian(CGeometry *geometry, CConfig *config); /*! * \brief Compute the max eigenvalue. * \param[in] geometry - Geometrical definition of the problem. * \param[in] config - Definition of the particular problem. */ - void SetMax_Eigenvalue(CGeometry *geometry, CConfig *config) final; + void SetMax_Eigenvalue(CGeometry *geometry, CConfig *config); /*! * \author H. Kline diff --git a/SU2_CFD/include/solvers/CIncNSSolver.hpp b/SU2_CFD/include/solvers/CIncNSSolver.hpp index cc9f273fbfe3..67e3cd38e185 100644 --- a/SU2_CFD/include/solvers/CIncNSSolver.hpp +++ b/SU2_CFD/include/solvers/CIncNSSolver.hpp @@ -315,7 +315,7 @@ class CIncNSSolver final : public CIncEulerSolver { */ unsigned long SetPrimitive_Variables(CSolver **solver_container, CConfig *config, - bool Output) override; + bool Output); /*! * \brief Impose a no-slip condition. @@ -437,14 +437,14 @@ class CIncNSSolver final : public CIncEulerSolver { * \brief Compute the viscous residuals. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Viscous_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) override; @@ -513,16 +513,4 @@ class CIncNSSolver final : public CIncEulerSolver { */ inline su2double GetStrainMag_Max(void) const override { return StrainMag_Max; } - /*! - * \brief A virtual member. - * \return Value of the StrainMag_Max - */ - inline void SetStrainMag_Max(su2double val_strainmag_max) override { StrainMag_Max = val_strainmag_max; } - - /*! - * \brief A virtual member. - * \return Value of the Omega_Max - */ - inline void SetOmega_Max(su2double val_omega_max) override { Omega_Max = val_omega_max; } - -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CNSSolver.hpp b/SU2_CFD/include/solvers/CNSSolver.hpp index 046b0bb6ae73..3aea5661ee30 100644 --- a/SU2_CFD/include/solvers/CNSSolver.hpp +++ b/SU2_CFD/include/solvers/CNSSolver.hpp @@ -39,67 +39,49 @@ class CNSSolver final : public CEulerSolver { private: su2double Viscosity_Inf; /*!< \brief Viscosity at the infinity. */ su2double Tke_Inf; /*!< \brief Turbulent kinetic energy at the infinity. */ - su2double Prandtl_Lam, /*!< \brief Laminar Prandtl number. */ - Prandtl_Turb; /*!< \brief Turbulent Prandtl number. */ - 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. */ - *Surface_Buffet_Metric, /*!< \brief Integrated separation sensor 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. */ - *Buffet_Metric, /*!< \brief Integrated separation sensor 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. */ - **Buffet_Sensor; /*!< \brief Separation sensor for each boundary and vertex. */ - su2double Total_Buffet_Metric; /*!< \brief Integrated separation sensor for all the boundaries. */ - su2double *ForceViscous, /*!< \brief Viscous force for each boundary. */ - *MomentViscous; /*!< \brief Inviscid moment for each boundary. */ + + 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_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. */ + /*! + * \brief A virtual member. + * \param[in] geometry - Geometrical definition. + * \param[in] config - Definition of the particular problem. + */ + void SetRoe_Dissipation(CGeometry *geometry, CConfig *config) override; + +private: + /*! + * \brief Compute the velocity^2, SoundSpeed, Pressure, Enthalpy, Viscosity. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] config - Definition of the particular problem. + * \param[in] Output - boolean to determine whether to print output. + * \return - The number of non-physical points. + */ + unsigned long SetPrimitive_Variables(CSolver **solver_container, + CConfig *config, + bool Output); + +protected: + public: /*! @@ -124,70 +106,70 @@ class CNSSolver final : public CEulerSolver { * \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]; } + 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 Surface_CD_Visc[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 Surface_CSF_Visc[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 Surface_CEff_Visc[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 Surface_CFx_Visc[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 Surface_CFy_Visc[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 Surface_CFz_Visc[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 Surface_CMx_Visc[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 Surface_CMy_Visc[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 Surface_CMz_Visc[val_marker]; } + inline su2double GetSurface_CMz_Visc(unsigned short val_marker) const override { return SurfaceViscCoeff.CMz[val_marker]; } /*! * \brief Provide the buffet metric. @@ -200,79 +182,79 @@ class CNSSolver final : public CEulerSolver { * \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; } + 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 AllBound_CD_Visc; } + 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 AllBound_CSF_Visc; } + 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 AllBound_CEff_Visc; } + 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 AllBound_CMx_Visc; } + 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 AllBound_CMy_Visc; } + 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 AllBound_CMz_Visc; } + 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 AllBound_CoPx_Visc; } + 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 AllBound_CoPy_Visc; } + 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 AllBound_CoPz_Visc; } + 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 AllBound_CFx_Visc; } + 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 AllBound_CFy_Visc; } + 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 AllBound_CFz_Visc; } + inline su2double GetAllBound_CFz_Visc() const override { return AllBoundViscCoeff.CFz; } /*! * \brief Get the buffet metric. @@ -292,20 +274,6 @@ class CNSSolver final : public CEulerSolver { */ 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. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] Iteration - Index of the current iteration. - */ - void SetTime_Step(CGeometry *geometry, - CSolver **solver_container, - CConfig *config, - unsigned short iMesh, - unsigned long Iteration) override; - /*! * \brief Restart residual and compute gradients. * \param[in] geometry - Geometrical definition of the problem. @@ -323,17 +291,6 @@ class CNSSolver final : public CEulerSolver { unsigned short RunTime_EqSystem, bool Output) override; - /*! - * \brief Compute the velocity^2, SoundSpeed, Pressure, Enthalpy, Viscosity. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] Output - boolean to determine whether to print output. - * \return - The number of non-physical points. - */ - unsigned long SetPrimitive_Variables(CSolver **solver_container, - CConfig *config, - bool Output) override; - /*! * \brief Compute weighted-sum "combo" objective output * \param[in] config - Definition of the particular problem. @@ -448,37 +405,32 @@ class CNSSolver final : public CEulerSolver { * \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]; } + 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 CSF_Visc[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 CD_Visc[val_marker]; } + inline su2double GetCD_Visc(unsigned short val_marker) const override { return ViscCoeff.CD[val_marker]; } /*! - * \brief Compute the viscous residuals. + * \brief Compute the viscous contribution for a particular edge. + * \param[in] iEdge - Edge for which the flux and Jacobians are to be computed. * \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. - * \param[in] iMesh - Index of the mesh in multigrid computations. - * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ - void Viscous_Residual(CGeometry *geometry, - CSolver **solver_container, - CNumerics *numerics, - CConfig *config, - unsigned short iMesh, - unsigned short iRKStep) override; + void Viscous_Residual(unsigned long iEdge, CGeometry *geometry, CSolver **solver_container, + CNumerics *numerics, CConfig *config) override; /*! * \brief Get the skin friction coefficient. @@ -554,25 +506,6 @@ class CNSSolver final : public CEulerSolver { */ inline su2double GetStrainMag_Max(void) const override { return StrainMag_Max; } - /*! - * \brief A virtual member. - * \return Value of the StrainMag_Max - */ - inline void SetStrainMag_Max(su2double val_strainmag_max) override { StrainMag_Max = val_strainmag_max; } - - /*! - * \brief A virtual member. - * \return Value of the Omega_Max - */ - inline void SetOmega_Max(su2double val_omega_max) override { Omega_Max = val_omega_max; } - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition. - * \param[in] config - Definition of the particular problem. - */ - void SetRoe_Dissipation(CGeometry *geometry, CConfig *config) override; - /*! * \brief Computes the wall shear stress (Tau_Wall) on the surface using a wall function. * \param[in] geometry - Geometrical definition of the problem. @@ -583,4 +516,4 @@ class CNSSolver final : public CEulerSolver { CSolver** solver_container, CConfig* config) override; -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CSolver.hpp b/SU2_CFD/include/solvers/CSolver.hpp index 58933e3ac340..3da0b15682de 100644 --- a/SU2_CFD/include/solvers/CSolver.hpp +++ b/SU2_CFD/include/solvers/CSolver.hpp @@ -42,7 +42,7 @@ #include "../fluid_model.hpp" #include "../task_definition.hpp" -#include "../numerics_structure.hpp" +#include "../numerics/CNumerics.hpp" #include "../sgs_model.hpp" #include "../../../Common/include/fem_geometry_structure.hpp" #include "../../../Common/include/geometry/CGeometry.hpp" @@ -66,12 +66,12 @@ class CSolver { unsigned short MGLevel; /*!< \brief Multigrid level of this solver object. */ unsigned short IterLinSolver; /*!< \brief Linear solver iterations. */ su2double ResLinSolver; /*!< \brief Final linear solver residual. */ - su2double NonLinRes_Value, /*!< \brief Summed value of the nonlinear residual indicator. */ - NonLinRes_Func; /*!< \brief Current value of the nonlinear residual indicator at one iteration. */ - unsigned short NonLinRes_Counter; /*!< \brief Number of elements of the nonlinear residual indicator series. */ - vector NonLinRes_Series; /*!< \brief Vector holding the nonlinear residual indicator series. */ + su2double NonLinRes_Value, /*!< \brief Summed value of the nonlinear residual indicator. */ + NonLinRes_Func; /*!< \brief Current value of the nonlinear residual indicator at one iteration. */ + unsigned short NonLinRes_Counter; /*!< \brief Number of elements of the nonlinear residual indicator series. */ + vector NonLinRes_Series; /*!< \brief Vector holding the nonlinear residual indicator series. */ su2double Old_Func, /*!< \brief Old value of the nonlinear residual indicator. */ - New_Func; /*!< \brief Current value of the nonlinear residual indicator. */ + New_Func; /*!< \brief Current value of the nonlinear residual indicator. */ unsigned short nVar, /*!< \brief Number of variables of the problem. */ nPrimVar, /*!< \brief Number of primitive variables of the problem. */ nPrimVarGrad, /*!< \brief Number of primitive variables of the problem in the gradient computation. */ @@ -81,8 +81,8 @@ class CSolver { nDim; /*!< \brief Number of dimensions of the problem. */ unsigned long nPoint; /*!< \brief Number of points of the computational grid. */ unsigned long nPointDomain; /*!< \brief Number of points of the computational grid. */ - su2double Max_Delta_Time, /*!< \brief Maximum value of the delta time for all the control volumes. */ - Min_Delta_Time; /*!< \brief Minimum value of the delta time for all the control volumes. */ + su2double Max_Delta_Time, /*!< \brief Maximum value of the delta time for all the control volumes. */ + Min_Delta_Time; /*!< \brief Minimum value of the delta time for all the control volumes. */ su2double Max_CFL_Local; /*!< \brief Maximum value of the CFL across all the control volumes. */ su2double Min_CFL_Local; /*!< \brief Minimum value of the CFL across all the control volumes. */ su2double Avg_CFL_Local; /*!< \brief Average value of the CFL across all the control volumes. */ @@ -126,8 +126,8 @@ class CSolver { passivedouble *Restart_Data; /*!< \brief Auxiliary structure for holding the data values from a restart. */ unsigned short nOutputVariables; /*!< \brief Number of variables to write. */ - unsigned long nMarker, /*!< \brief Total number of markers using the grid information. */ - *nVertex; /*!< \brief Store nVertex at each marker for deallocation */ + unsigned long nMarker, /*!< \brief Total number of markers using the grid information. */ + *nVertex; /*!< \brief Store nVertex at each marker for deallocation */ bool rotate_periodic; /*!< \brief Flag that controls whether the periodic solution needs to be rotated for the solver. */ bool implicit_periodic; /*!< \brief Flag that controls whether the implicit system should be treated by the periodic BC comms. */ @@ -155,7 +155,7 @@ class CSolver { private: /*--- Private to prevent use by derived solvers, each solver MUST have its own "nodes" member of the - most derived type possible, e.g. CEulerVariable has nodes of CEulerVariable* and not CVariable*. + most derived type possible, e.g. CEulerSolver has nodes of CEulerVariable* and not CVariable*. This variable is to avoid two virtual functions calls per call i.e. CSolver::GetNodes() returns directly instead of calling GetBaseClassPointerToNodes() or doing something equivalent. ---*/ CVariable* base_nodes; /*!< \brief Pointer to CVariable to allow polymorphic access to solver nodes. */ @@ -742,14 +742,14 @@ class CSolver { * \brief A virtual member. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ inline virtual void Centered_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { } @@ -758,13 +758,13 @@ class CSolver { * \brief A virtual member. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ inline virtual void Upwind_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { } @@ -820,22 +820,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 SetUndivided_Laplacian(CGeometry *geometry, 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 Set_MPI_ActDisk(CSolver **solver_container, - CGeometry *geometry, - CConfig *config) { } - /*! * \brief A virtual member. * \param[in] geometry - Geometrical definition of the problem. @@ -843,29 +827,6 @@ class CSolver { */ inline virtual void Set_MPI_Nearfield(CGeometry *geometry, 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 SetMax_Eigenvalue(CGeometry *geometry, CConfig *config) { } - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - */ - inline virtual void SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *config) { } - - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - */ - inline virtual void SetUpwind_Ducros_Sensor(CGeometry *geometry, CConfig *config) { } - /*! * \brief A virtual member. * \param[in] geometry - Geometrical definition of the problem. @@ -1707,14 +1668,14 @@ class CSolver { * \brief A virtual member. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ inline virtual void Viscous_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { } @@ -1723,15 +1684,14 @@ class CSolver { * \brief A virtual member. * \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] numerics_container - Description of the numerical method. * \param[in] second_numerics - Description of the second numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ inline virtual void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { } @@ -2265,18 +2225,6 @@ class CSolver { */ inline virtual su2double GetInflow_MassFlow(unsigned short val_marker) const { return 0; } - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - current mesh level for the multigrid. - * \param[in] Output - boolean to determine whether to print output. - */ - inline virtual void GetPower_Properties(CGeometry *geometry, - CConfig *config, - unsigned short iMesh, - bool Output) { } - /*! * \brief A virtual member. * \param[in] geometry - Geometrical definition of the problem. @@ -2289,20 +2237,6 @@ class CSolver { unsigned short iMesh, bool Output) { } - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - current mesh level for the multigrid. - * \param[in] Output - boolean to determine whether to print output. - */ - inline virtual void SetFarfield_AoA(CGeometry *geometry, - CSolver **solver_container, - CConfig *config, - unsigned short iMesh, - bool Output) { } - /*! * \brief A virtual member. * \param[in] config - Definition of the particular problem. @@ -2341,20 +2275,6 @@ class CSolver { */ inline virtual su2double GetAoA_inc(void) const { return 0.0; } - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition of the problem. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] iMesh - current mesh level for the multigrid. - * \param[in] Output - boolean to determine whether to print output. - */ - inline virtual void SetActDisk_BCThrust(CGeometry *geometry, - CSolver **solver_container, - CConfig *config, - unsigned short iMesh, - bool Output) { } - /*! * \brief A virtual member. * \param[in] val_marker - Surface marker where the coefficient is computed. @@ -3328,18 +3248,6 @@ class CSolver { */ inline virtual su2double GetOmega_Max(void) const { return 0; } - /*! - * \brief A virtual member. - * \return Value of the StrainMag_Max - */ - inline virtual void SetStrainMag_Max(su2double val_strainmag_max) { } - - /*! - * \brief A virtual member. - * \return Value of the Omega_Max - */ - inline virtual void SetOmega_Max(su2double val_omega_max) { } - /*! * \brief A virtual member. * \return Value of the adjoint density at the infinity. @@ -3456,7 +3364,7 @@ class CSolver { * \brief A virtual member. * \return Value of the velocity at the infinity. */ - inline virtual su2double *GetVelocity_Inf(void) const { return 0; } + inline virtual su2double *GetVelocity_Inf(void) { return 0; } /*! * \brief A virtual member. @@ -3622,7 +3530,7 @@ class CSolver { * \brief A virtual member. * \return A pointer to an array containing a set of constants */ - inline virtual su2double* GetConstants() const { return NULL; } + inline virtual const su2double* GetConstants() const { return nullptr; } /*! * \brief A virtual member. @@ -4190,16 +4098,6 @@ class CSolver { */ inline virtual su2double GetLoad_Increment() const { return 0; } - /*! - * \brief A virtual member. - * \param[in] solver_container - Container vector with all the solutions. - * \param[in] config - Definition of the particular problem. - * \param[in] Output - boolean to determine whether to print output. - */ - inline virtual unsigned long SetPrimitive_Variables(CSolver **solver_container, - CConfig *config, - bool Output) { return 0; } - /*! * \brief A virtual member. * \param[in] Value of freestream pressure. @@ -4661,23 +4559,6 @@ class CSolver { CConfig *config, unsigned short iMesh) { } - /*! - * \brief A virtual member. - * \param[in] geometry - Geometrical definition. - * \param[in] config - Definition of the particular problem. - */ - inline virtual void SetRoe_Dissipation(CGeometry *geometry, CConfig *config) {} - - /*! - * \brief A virtual member. - * \param[in] solver - Solver container - * \param[in] geometry - Geometrical definition. - * \param[in] config - Definition of the particular problem. - */ - inline virtual void SetDES_LengthScale(CSolver** solver, - CGeometry *geometry, - CConfig *config) { } - /*! * \brief A virtual member. * \param[in] geometry - Geometrical definition. @@ -4824,6 +4705,13 @@ class CSolver { */ virtual su2double GetMaximum_Volume() const { return 0.0; } + /*! + * \brief Whether the methods of the solver called by multi/single-grid + * iteration can be executed by multiple threads. + * \return Should return true if "yes", false if "no". + */ + inline virtual bool GetHasHybridParallel() const { return false; } + protected: /*! * \brief Allocate the memory for the verification solution, if necessary. diff --git a/SU2_CFD/include/solvers/CTemplateSolver.hpp b/SU2_CFD/include/solvers/CTemplateSolver.hpp index cbade9368f35..da6a5ee48689 100644 --- a/SU2_CFD/include/solvers/CTemplateSolver.hpp +++ b/SU2_CFD/include/solvers/CTemplateSolver.hpp @@ -100,14 +100,14 @@ class CTemplateSolver final : public CSolver { * \brief Compute the spatial integration using a centered scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Centered_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) override; @@ -116,13 +116,13 @@ class CTemplateSolver final : public CSolver { * \brief Compute the spatial integration using a upwind scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Upwind_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) override; @@ -130,16 +130,15 @@ class CTemplateSolver final : public CSolver { * \brief Source term integration. * \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] second_numerics - Description of the second numerical method. + * \param[in] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) override; + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) override; /*! * \brief Source term integration. @@ -295,4 +294,4 @@ class CTemplateSolver final : public CSolver { CSolver **solver_container, CConfig *config) override; -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CTransLMSolver.hpp b/SU2_CFD/include/solvers/CTransLMSolver.hpp index 01534da7108e..9ec5bd7fd73a 100644 --- a/SU2_CFD/include/solvers/CTransLMSolver.hpp +++ b/SU2_CFD/include/solvers/CTransLMSolver.hpp @@ -92,13 +92,13 @@ class CTransLMSolver final : public CTurbSolver { * \brief Compute the spatial integration using a upwind scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Upwind_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) override; @@ -106,14 +106,14 @@ class CTransLMSolver final : public CTurbSolver { * \brief Compute the viscous residuals for the turbulent equation. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Viscous_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) override; @@ -122,16 +122,15 @@ class CTransLMSolver final : public CTurbSolver { * \brief Source term computation. * \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] second_numerics - Description of the second numerical method. + * \param[in] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) override; + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) override; /*! * \brief Source term computation. @@ -237,6 +236,11 @@ class CTransLMSolver final : public CTurbSolver { CSolver **solver_container, CConfig *config) override; + /*! + * \brief No support for OpenMP+MPI. + */ + inline bool GetHasHybridParallel() const override { return false; } + // Another set of matrix structures for the Lm equations CSysMatrix JacobianItmc; /*!< \brief Complete sparse Jacobian structure for implicit computations. */ su2double *LinSysSolItmc; /*!< \brief vector to store iterative solution of implicit linear system. */ @@ -246,4 +250,4 @@ class CTransLMSolver final : public CTurbSolver { su2double *LinSysSolReth; /*!< \brief vector to store iterative solution of implicit linear system. */ su2double *LinSysResReth; /*!< \brief vector to store iterative residual of implicit linear system. */ su2double *rhsReth; /*!< \brief right hand side of implicit linear system. */ -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CTurbSASolver.hpp b/SU2_CFD/include/solvers/CTurbSASolver.hpp index e1e75788ba46..403f5c3fe9c1 100644 --- a/SU2_CFD/include/solvers/CTurbSASolver.hpp +++ b/SU2_CFD/include/solvers/CTurbSASolver.hpp @@ -41,6 +41,16 @@ class CTurbSASolver final : public CTurbSolver { private: su2double nu_tilde_Inf, nu_tilde_Engine, nu_tilde_ActDisk; + /*! + * \brief A virtual member. + * \param[in] solver - Solver container + * \param[in] geometry - Geometrical definition. + * \param[in] config - Definition of the particular problem. + */ + void SetDES_LengthScale(CSolver** solver, + CGeometry *geometry, + CConfig *config); + public: /*! * \brief Constructor of the class. @@ -93,16 +103,15 @@ class CTurbSASolver final : public CTurbSolver { * \brief Source term computation. * \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] second_numerics - Description of the second numerical method. + * \param[in] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) override; + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) override; /*! * \brief Source term computation. @@ -362,17 +371,6 @@ class CTurbSASolver final : public CTurbSolver { for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++) nodes->SetSolution(iPoint, 0, nu_tilde_Inf); } - - /*! - * \brief A virtual member. - * \param[in] solver - Solver container - * \param[in] geometry - Geometrical definition. - * \param[in] config - Definition of the particular problem. - */ - void SetDES_LengthScale(CSolver** solver, - CGeometry *geometry, - CConfig *config) override; - /*! * \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. @@ -431,4 +429,4 @@ class CTurbSASolver final : public CTurbSolver { CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) override; -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CTurbSSTSolver.hpp b/SU2_CFD/include/solvers/CTurbSSTSolver.hpp index fbc7e7d5b727..c296f098a653 100644 --- a/SU2_CFD/include/solvers/CTurbSSTSolver.hpp +++ b/SU2_CFD/include/solvers/CTurbSSTSolver.hpp @@ -35,10 +35,10 @@ * \ingroup Turbulence_Model * \author A. Campos, F. Palacios, T. Economon */ - class CTurbSSTSolver final : public CTurbSolver { private: - su2double *constants, /*!< \brief Constants for the model. */ + su2double + constants[10] = {0.0}, /*!< \brief Constants for the model. */ kine_Inf, /*!< \brief Free-stream turbulent kinetic energy. */ omega_Inf; /*!< \brief Free-stream specific dissipation. */ @@ -95,16 +95,15 @@ class CTurbSSTSolver final : public CTurbSolver { * \brief Source term computation. * \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] second_numerics - Description of the second numerical method. + * \param[in] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Source_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, - CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) override; + CNumerics **numerics_container, + CConfig *config, + unsigned short iMesh) override; /*! * \brief Source term computation. @@ -247,7 +246,7 @@ class CTurbSSTSolver final : public CTurbSolver { * \brief Get the constants for the SST model. * \return A pointer to an array containing a set of constants */ - inline su2double* GetConstants() const override { return constants; } + inline const su2double* GetConstants() const override { return constants; } /*! * \brief Set the solution using the Freestream values. @@ -309,4 +308,4 @@ class CTurbSSTSolver final : public CTurbSolver { */ inline su2double GetOmega_Inf(void) const override { return omega_Inf; } -}; \ No newline at end of file +}; diff --git a/SU2_CFD/include/solvers/CTurbSolver.hpp b/SU2_CFD/include/solvers/CTurbSolver.hpp index 9c976df4f1b3..b0284a378c54 100644 --- a/SU2_CFD/include/solvers/CTurbSolver.hpp +++ b/SU2_CFD/include/solvers/CTurbSolver.hpp @@ -29,6 +29,7 @@ #include "CSolver.hpp" #include "../variables/CTurbVariable.hpp" +#include "../../../Common/include/omp_structure.hpp" /*! * \class CTurbSolver @@ -38,22 +39,40 @@ */ class CTurbSolver : public CSolver { protected: - su2double *FlowPrimVar_i, /*!< \brief Store the flow solution at point i. */ - *FlowPrimVar_j, /*!< \brief Store the flow solution at point j. */ - *lowerlimit, /*!< \brief contains lower limits for turbulence variables. */ - *upperlimit; /*!< \brief contains upper limits for turbulence variables. */ - su2double Gamma; /*!< \brief Fluid's Gamma constant (ratio of specific heats). */ - su2double Gamma_Minus_One; /*!< \brief Fluids's Gamma - 1.0 . */ - su2double*** Inlet_TurbVars; /*!< \brief Turbulence variables at inlet profiles */ + enum : size_t {MAXNDIM = 3}; /*!< \brief Max number of space dimensions, used in some static arrays. */ + enum : size_t {MAXNVAR = 2}; /*!< \brief Max number of variables, used in some static arrays. */ + enum : size_t {MAXNVARFLOW = 12}; /*!< \brief Max number of flow variables, used in some static arrays. */ - CTurbVariable* snode; /*!< \brief The highest level in the variable hierarchy this solver can safely use. */ + 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 + lowerlimit[MAXNVAR] = {0.0}, /*!< \brief contains lower limits for turbulence variables. */ + upperlimit[MAXNVAR] = {0.0}, /*!< \brief contains upper limits for turbulence variables. */ + Gamma, /*!< \brief Fluid's Gamma constant (ratio of specific heats). */ + Gamma_Minus_One, /*!< \brief Fluids's Gamma - 1.0 . */ + ***Inlet_TurbVars = nullptr; /*!< \brief Turbulence variables at inlet profiles */ /* Sliding meshes variables */ - su2double ****SlidingState; - int **SlidingStateNodes; + su2double ****SlidingState = nullptr; + int **SlidingStateNodes = nullptr; + + /*--- Shallow copy of grid coloring for OpenMP parallelization. ---*/ - CTurbVariable* nodes = nullptr; /*!< \brief The highest level in the variable hierarchy this solver can safely use. */ +#ifdef HAVE_OMP + vector > EdgeColoring; /*!< \brief Edge colors. */ +#else + array,1> EdgeColoring; +#endif + unsigned long ColorGroupSize; /*!< \brief Group size used for coloring, chunk size in edge loops must be a multiple of this. */ + + /*! + * \brief The highest level in the variable hierarchy this solver can safely use. + */ + CTurbVariable* nodes = nullptr; /*! * \brief Return nodes to allow CSolver::base_nodes to be set. @@ -83,14 +102,14 @@ class CTurbSolver : public CSolver { * \brief Compute the spatial integration using a upwind scheme. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. */ void Upwind_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) override; @@ -98,14 +117,14 @@ class CTurbSolver : public CSolver { * \brief Compute the viscous residuals for the turbulent equation. * \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] numerics_container - Description of the numerical method. * \param[in] config - Definition of the particular problem. * \param[in] iMesh - Index of the mesh in multigrid computations. * \param[in] iRKStep - Current step of the Runge-Kutta iteration. */ void Viscous_Residual(CGeometry *geometry, CSolver **solver_container, - CNumerics *numerics, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) override; @@ -337,4 +356,9 @@ class CTurbSolver : public CSolver { Inlet_TurbVars[val_marker][val_vertex][val_dim] = val_turb_var; } -}; \ No newline at end of file + /*! + * \brief SA and SST support OpenMP+MPI. + */ + inline bool GetHasHybridParallel() const override { return true; } + +}; diff --git a/SU2_CFD/include/variables/CFEABoundVariable.hpp b/SU2_CFD/include/variables/CFEABoundVariable.hpp index 434b371194a9..28e59f9ccb05 100644 --- a/SU2_CFD/include/variables/CFEABoundVariable.hpp +++ b/SU2_CFD/include/variables/CFEABoundVariable.hpp @@ -82,14 +82,6 @@ class CFEABoundVariable final : public CFEAVariable { for (unsigned long iVar = 0; iVar < nVar; iVar++) Residual_Ext_Surf(iPoint,iVar) += val_surfForce[iVar]; } - /*! - * \brief Set surface load of the residual term (for dampers - deletes all the other loads) - */ - inline void Set_SurfaceLoad_Res(unsigned long iPoint, unsigned long iVar, su2double val_surfForce) override { - if (!VertexMap.GetVertexIndex(iPoint)) return; - Residual_Ext_Surf(iPoint,iVar) = val_surfForce; - } - /*! * \brief Get the residual term due to surface load */ @@ -101,10 +93,7 @@ class CFEABoundVariable final : public CFEAVariable { /*! * \brief Clear the surface load residual */ - inline void Clear_SurfaceLoad_Res(unsigned long iPoint) override { - if (!VertexMap.GetVertexIndex(iPoint)) return; - for (unsigned long iVar = 0; iVar < nVar; iVar++) Residual_Ext_Surf(iPoint,iVar) = 0.0; - } + inline void Clear_SurfaceLoad_Res() override; /*! * \brief Store the surface load as the load for the previous time step. diff --git a/SU2_CFD/include/variables/CTurbSAVariable.hpp b/SU2_CFD/include/variables/CTurbSAVariable.hpp index ad2d9a18539a..64f6e069e903 100644 --- a/SU2_CFD/include/variables/CTurbSAVariable.hpp +++ b/SU2_CFD/include/variables/CTurbSAVariable.hpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -108,7 +108,8 @@ class CTurbSAVariable final : public CTurbVariable { * \brief Set the vortex tilting measure for computation of the EDDES length scale * \param[in] iPoint - Point index. */ - void SetVortex_Tilting(unsigned long iPoint, su2double **PrimGrad_Flow, su2double* Vorticity, su2double LaminarViscosity) override; + void SetVortex_Tilting(unsigned long iPoint, const su2double* const* PrimGrad_Flow, + const su2double* Vorticity, su2double LaminarViscosity) override; /*! * \brief Get the vortex tilting measure for computation of the EDDES length scale diff --git a/SU2_CFD/include/variables/CVariable.hpp b/SU2_CFD/include/variables/CVariable.hpp index dcc4b7e1f380..846a887cf736 100644 --- a/SU2_CFD/include/variables/CVariable.hpp +++ b/SU2_CFD/include/variables/CVariable.hpp @@ -121,13 +121,13 @@ class CVariable { su2matrix AD_InputIndex; /*!< \brief Indices of Solution variables in the adjoint vector. */ su2matrix AD_OutputIndex; /*!< \brief Indices of Solution variables in the adjoint vector after having been updated. */ - unsigned long nPoint = {0}; /*!< \brief Number of points in the domain. */ - unsigned long nDim = {0}; /*!< \brief Number of dimension of the problem. */ - unsigned long nVar = {0}; /*!< \brief Number of variables of the problem. */ - unsigned long nPrimVar = {0}; /*!< \brief Number of primitive variables. */ - unsigned long nPrimVarGrad = {0}; /*!< \brief Number of primitives for which a gradient is computed. */ - unsigned long nSecondaryVar = {0}; /*!< \brief Number of secondary variables. */ - unsigned long nSecondaryVarGrad = {0}; /*!< \brief Number of secondaries for which a gradient is computed. */ + unsigned long nPoint = 0; /*!< \brief Number of points in the domain. */ + unsigned long nDim = 0; /*!< \brief Number of dimension of the problem. */ + unsigned long nVar = 0; /*!< \brief Number of variables of the problem. */ + unsigned long nPrimVar = 0; /*!< \brief Number of primitive variables. */ + unsigned long nPrimVarGrad = 0; /*!< \brief Number of primitives for which a gradient is computed. */ + unsigned long nSecondaryVar = 0; /*!< \brief Number of secondary variables. */ + unsigned long nSecondaryVarGrad = 0; /*!< \brief Number of secondaries for which a gradient is computed. */ public: @@ -197,7 +197,7 @@ class CVariable { } else { Non_Physical_Counter(iPoint)++; if (Non_Physical_Counter(iPoint) > 20) { - Non_Physical(iPoint) = val_value; + Non_Physical(iPoint) = false; } } } @@ -524,7 +524,9 @@ class CVariable { /*! * \brief Set summed residual vector to zero value. */ - void SetResidualSumZero(); + inline void SetResidualSumZero(unsigned long iPoint) { + for (unsigned long iVar = 0; iVar < nVar; iVar++) Residual_Sum(iPoint,iVar) = 0.0; + } /*! * \brief Set the velocity of the truncation error to zero. @@ -1773,11 +1775,6 @@ class CVariable { */ inline virtual void Add_SurfaceLoad_Res(unsigned long iPoint, const su2double *val_surfForce) {} - /*! - * \brief A virtual member. - */ - inline virtual void Set_SurfaceLoad_Res(unsigned long iPoint, unsigned long iVar, su2double val_surfForce) {} - /*! * \brief A virtual member. */ @@ -1786,7 +1783,7 @@ class CVariable { /*! * \brief A virtual member. */ - inline virtual void Clear_SurfaceLoad_Res(unsigned long iPoint) {} + inline virtual void Clear_SurfaceLoad_Res() {} /*! * \brief A virtual member. @@ -2738,7 +2735,8 @@ class CVariable { inline virtual su2double GetTauWall(unsigned long iPoint) const { return 0.0; } - inline virtual void SetVortex_Tilting(unsigned long iPoint, su2double **PrimGrad_Flow, su2double* Vorticity, su2double LaminarViscosity) {} + inline virtual void SetVortex_Tilting(unsigned long iPoint, const su2double* const* PrimGrad_Flow, + const su2double* Vorticity, su2double LaminarViscosity) {} inline virtual su2double GetVortex_Tilting(unsigned long iPoint) const { return 0.0; } diff --git a/SU2_CFD/obj/Makefile.am b/SU2_CFD/obj/Makefile.am index 1a2cb0127c98..4a4199913532 100644 --- a/SU2_CFD/obj/Makefile.am +++ b/SU2_CFD/obj/Makefile.am @@ -54,8 +54,11 @@ libSU2Core_sources = ../src/definition_structure.cpp \ ../src/fluid_model_pvdw.cpp \ ../src/fluid_model_ppr.cpp \ ../src/fluid_model_inc.cpp \ - ../src/integration_structure.cpp \ - ../src/integration_time.cpp \ + ../src/integration/CIntegration.cpp \ + ../src/integration/CSingleGridIntegration.cpp \ + ../src/integration/CMultiGridIntegration.cpp \ + ../src/integration/CStructuralIntegration.cpp \ + ../src/integration/CFEM_DG_Integration.cpp \ ../src/drivers/CMultizoneDriver.cpp \ ../src/drivers/CSinglezoneDriver.cpp \ ../src/drivers/CDiscAdjSinglezoneDriver.cpp \ @@ -63,23 +66,29 @@ libSU2Core_sources = ../src/definition_structure.cpp \ ../src/drivers/CDriver.cpp \ ../src/drivers/CDummyDriver.cpp \ ../src/iteration_structure.cpp \ - ../src/numerics_adjoint_mean.cpp \ - ../src/numerics_adjoint_turbulent.cpp \ - ../src/numerics_direct_heat.cpp \ - ../src/numerics_direct_mean.cpp \ - ../src/numerics_direct_mean_inc.cpp \ - ../src/numerics_direct_transition.cpp \ - ../src/numerics_direct_turbulent.cpp \ + ../src/numerics/CNumerics.cpp \ + ../src/numerics/template.cpp \ + ../src/numerics/transition.cpp \ + ../src/numerics/heat.cpp \ + ../src/numerics/flow/convection/roe.cpp \ + ../src/numerics/flow/convection/fds.cpp \ + ../src/numerics/flow/convection/fvs.cpp \ + ../src/numerics/flow/convection/cusp.cpp \ + ../src/numerics/flow/convection/hllc.cpp \ + ../src/numerics/flow/convection/ausm_slau.cpp \ + ../src/numerics/flow/convection/centered.cpp \ + ../src/numerics/flow/flow_diffusion.cpp \ + ../src/numerics/flow/flow_sources.cpp \ + ../src/numerics/continuous_adjoint/adj_convection.cpp \ + ../src/numerics/continuous_adjoint/adj_diffusion.cpp \ + ../src/numerics/continuous_adjoint/adj_sources.cpp \ + ../src/numerics/turbulent/turb_convection.cpp \ + ../src/numerics/turbulent/turb_diffusion.cpp \ + ../src/numerics/turbulent/turb_sources.cpp \ ../src/numerics/elasticity/CFEAElasticity.cpp \ ../src/numerics/elasticity/CFEALinearElasticity.cpp \ - ../src/numerics/elasticity/CFEAMeshElasticity.cpp \ ../src/numerics/elasticity/CFEANonlinearElasticity.cpp \ - ../src/numerics/elasticity/CFEM_NeoHookean_Comp.cpp \ - ../src/numerics/elasticity/CFEM_Knowles_NearInc.cpp \ - ../src/numerics/elasticity/CFEM_IdealDE.cpp \ - ../src/numerics/elasticity/CFEM_DielectricElastomer.cpp \ - ../src/numerics_structure.cpp \ - ../src/numerics_template.cpp \ + ../src/numerics/elasticity/nonlinear_models.cpp \ ../src/output/filewriter/CCSVFileWriter.cpp \ ../src/output/filewriter/CSTLFileWriter.cpp \ ../src/output/filewriter/CFEMDataSorter.cpp \ @@ -138,6 +147,7 @@ libSU2Core_sources = ../src/definition_structure.cpp \ ../src/solvers/CTurbSolver.cpp \ ../src/solvers/CTurbSASolver.cpp \ ../src/solvers/CTurbSSTSolver.cpp \ + ../src/limiters/CLimiterDetails.cpp \ ../src/CMarkerProfileReaderFVM.cpp \ ../src/interfaces/CInterface.cpp \ ../src/interfaces/cfd/CConservativeVarsInterface.cpp \ @@ -175,7 +185,6 @@ libSU2Core_sources = ../src/definition_structure.cpp \ ../src/variables/CEulerVariable.cpp su2_cfd_sources = \ - ../include/SU2_CFD.hpp \ ../src/SU2_CFD.cpp libSU2Core_cxx_flags = -fPIC -std=c++11 diff --git a/SU2_CFD/src/drivers/CDiscAdjMultizoneDriver.cpp b/SU2_CFD/src/drivers/CDiscAdjMultizoneDriver.cpp index 3194c8c151d1..0bcfc80e661c 100644 --- a/SU2_CFD/src/drivers/CDiscAdjMultizoneDriver.cpp +++ b/SU2_CFD/src/drivers/CDiscAdjMultizoneDriver.cpp @@ -26,6 +26,7 @@ */ #include "../../include/drivers/CDiscAdjMultizoneDriver.hpp" +#include "../../include/solvers/CFEASolver.hpp" CDiscAdjMultizoneDriver::CDiscAdjMultizoneDriver(char* confFile, unsigned short val_nZone, diff --git a/SU2_CFD/src/drivers/CDriver.cpp b/SU2_CFD/src/drivers/CDriver.cpp index 0b23e05421e9..978b9c199d9c 100644 --- a/SU2_CFD/src/drivers/CDriver.cpp +++ b/SU2_CFD/src/drivers/CDriver.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -32,15 +32,6 @@ #include "../../../Common/include/geometry/CPhysicalGeometry.hpp" #include "../../../Common/include/geometry/CMultiGridGeometry.hpp" -#include "../../include/numerics/elasticity/CFEALinearElasticity.hpp" -#include "../../include/numerics/elasticity/CFEAMeshElasticity.hpp" -#include "../../include/numerics/elasticity/CFEM_NeoHookean_Comp.hpp" -#include "../../include/numerics/elasticity/CFEM_Knowles_NearInc.hpp" -#include "../../include/numerics/elasticity/CFEM_IdealDE.hpp" -#include "../../include/numerics/elasticity/CFEM_DielectricElastomer.hpp" - -#include "../../../Common/include/omp_structure.hpp" - #include "../../include/solvers/CEulerSolver.hpp" #include "../../include/solvers/CIncEulerSolver.hpp" #include "../../include/solvers/CNSSolver.hpp" @@ -58,6 +49,48 @@ #include "../../include/solvers/CDiscAdjFEASolver.hpp" #include "../../include/solvers/CFEM_DG_EulerSolver.hpp" #include "../../include/solvers/CFEM_DG_NSSolver.hpp" +#include "../../include/solvers/CDiscAdjMeshSolver.hpp" +#include "../../include/solvers/CMeshSolver.hpp" + +#include "../../include/interfaces/cfd/CConservativeVarsInterface.hpp" +#include "../../include/interfaces/cfd/CMixingPlaneInterface.hpp" +#include "../../include/interfaces/cfd/CSlidingInterface.hpp" +#include "../../include/interfaces/cht/CConjugateHeatInterface.hpp" +#include "../../include/interfaces/fsi/CDisplacementsInterface.hpp" +#include "../../include/interfaces/fsi/CFlowTractionInterface.hpp" +#include "../../include/interfaces/fsi/CDiscAdjFlowTractionInterface.hpp" +#include "../../include/interfaces/fsi/CDisplacementsInterfaceLegacy.hpp" +#include "../../include/interfaces/fsi/CDiscAdjDisplacementsInterfaceLegacy.hpp" + +#include "../../include/numerics/template.hpp" +#include "../../include/numerics/transition.hpp" +#include "../../include/numerics/heat.hpp" +#include "../../include/numerics/flow/convection/roe.hpp" +#include "../../include/numerics/flow/convection/fds.hpp" +#include "../../include/numerics/flow/convection/fvs.hpp" +#include "../../include/numerics/flow/convection/cusp.hpp" +#include "../../include/numerics/flow/convection/hllc.hpp" +#include "../../include/numerics/flow/convection/ausm_slau.hpp" +#include "../../include/numerics/flow/convection/centered.hpp" +#include "../../include/numerics/flow/flow_diffusion.hpp" +#include "../../include/numerics/flow/flow_sources.hpp" +#include "../../include/numerics/continuous_adjoint/adj_convection.hpp" +#include "../../include/numerics/continuous_adjoint/adj_diffusion.hpp" +#include "../../include/numerics/continuous_adjoint/adj_sources.hpp" +#include "../../include/numerics/turbulent/turb_convection.hpp" +#include "../../include/numerics/turbulent/turb_diffusion.hpp" +#include "../../include/numerics/turbulent/turb_sources.hpp" +#include "../../include/numerics/elasticity/CFEAElasticity.hpp" +#include "../../include/numerics/elasticity/CFEALinearElasticity.hpp" +#include "../../include/numerics/elasticity/CFEANonlinearElasticity.hpp" +#include "../../include/numerics/elasticity/nonlinear_models.hpp" + +#include "../../include/integration/CSingleGridIntegration.hpp" +#include "../../include/integration/CMultiGridIntegration.hpp" +#include "../../include/integration/CStructuralIntegration.hpp" +#include "../../include/integration/CFEM_DG_Integration.hpp" + +#include "../../../Common/include/omp_structure.hpp" #include @@ -1907,41 +1940,90 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol numerics = new CNumerics***[config->GetnMGLevels()+1]; - su2double *constants = NULL; + const su2double *constants = nullptr; su2double kine_Inf = 0.0, omega_Inf = 0.0; bool compressible = false; bool incompressible = false; - bool ideal_gas = (config->GetKind_FluidModel() == STANDARD_AIR || config->GetKind_FluidModel() == IDEAL_GAS ); - bool roe_low_dissipation = config->GetKind_RoeLowDiss() != NO_ROELOWDISS; + bool ideal_gas = (config->GetKind_FluidModel() == STANDARD_AIR) || (config->GetKind_FluidModel() == IDEAL_GAS); + bool roe_low_dissipation = (config->GetKind_RoeLowDiss() != NO_ROELOWDISS); /*--- Initialize some useful booleans ---*/ - bool euler, ns, turbulent, adj_euler, adj_ns, adj_turb, fem, fem_euler, fem_ns, fem_turbulent; + bool euler, ns, turbulent, adj_euler, adj_ns, adj_turb, fem_euler, fem_ns, fem_turbulent; bool spalart_allmaras, neg_spalart_allmaras, e_spalart_allmaras, comp_spalart_allmaras, e_comp_spalart_allmaras, menter_sst; - bool heat, transition, template_solver; + bool fem, heat, transition, template_solver; - euler = ns = turbulent = adj_euler = adj_ns = adj_turb = fem = fem_euler = fem_ns = fem_turbulent = false; + euler = ns = turbulent = adj_euler = adj_ns = adj_turb = fem_euler = fem_ns = fem_turbulent = false; spalart_allmaras = neg_spalart_allmaras = e_spalart_allmaras = comp_spalart_allmaras = e_comp_spalart_allmaras = menter_sst = false; - heat = transition = template_solver = false; + fem = heat = transition = template_solver = false; /*--- Assign booleans ---*/ switch (config->GetKind_Solver()) { - case TEMPLATE_SOLVER: template_solver = true; break; - case EULER : case DISC_ADJ_EULER: compressible = true; euler = true; break; - case NAVIER_STOKES: case DISC_ADJ_NAVIER_STOKES:compressible = true; ns = true; break; - case RANS : case DISC_ADJ_RANS: ns = true; compressible = true; turbulent = true; if (config->GetKind_Trans_Model() == LM) transition = true; break; - case INC_EULER : case DISC_ADJ_INC_EULER: incompressible =true; euler = true; break; - case INC_NAVIER_STOKES: case DISC_ADJ_INC_NAVIER_STOKES:incompressible =true; ns = true; heat = config->GetWeakly_Coupled_Heat(); break; - case INC_RANS : case DISC_ADJ_INC_RANS: incompressible =true; ns = true; turbulent = true; heat = config->GetWeakly_Coupled_Heat(); if (config->GetKind_Trans_Model() == LM) transition = true; break; - case FEM_EULER : case DISC_ADJ_FEM_EULER : compressible =true; fem_euler = true; break; - case FEM_NAVIER_STOKES: case DISC_ADJ_FEM_NS : compressible =true; fem_ns = true; break; - case FEM_RANS : case DISC_ADJ_FEM_RANS : compressible =true; fem_ns = true; fem_turbulent = true; break; - case FEM_LES : compressible =true; fem_ns = true; break; - case HEAT_EQUATION: case DISC_ADJ_HEAT: heat = true; break; - case FEM_ELASTICITY: case DISC_ADJ_FEM: fem = true; break; - case ADJ_EULER : compressible =true; euler = true; adj_euler = true; break; - case ADJ_NAVIER_STOKES : compressible =true; ns = true; turbulent = (config->GetKind_Turb_Model() != NONE); adj_ns = true; break; - case ADJ_RANS : compressible =true; ns = true; turbulent = true; adj_ns = true; adj_turb = (!config->GetFrozen_Visc_Cont()); break; + case TEMPLATE_SOLVER: + template_solver = true; break; + + case EULER : + case DISC_ADJ_EULER: + euler = compressible = true; break; + + case NAVIER_STOKES: + case DISC_ADJ_NAVIER_STOKES: + ns = compressible = true; break; + + case RANS: + case DISC_ADJ_RANS: + ns = compressible = turbulent = true; + transition = (config->GetKind_Trans_Model() == LM); break; + + case INC_EULER: + case DISC_ADJ_INC_EULER: + euler = incompressible = true; break; + + case INC_NAVIER_STOKES: + case DISC_ADJ_INC_NAVIER_STOKES: + ns = incompressible = true; + heat = config->GetWeakly_Coupled_Heat(); break; + + case INC_RANS: + case DISC_ADJ_INC_RANS: + ns = incompressible = turbulent = true; + heat = config->GetWeakly_Coupled_Heat(); + transition = (config->GetKind_Trans_Model() == LM); break; + + case FEM_EULER: + case DISC_ADJ_FEM_EULER: + fem_euler = compressible = true; break; + + case FEM_NAVIER_STOKES: + case DISC_ADJ_FEM_NS: + fem_ns = compressible = true; break; + + case FEM_RANS: + case DISC_ADJ_FEM_RANS: + fem_ns = compressible = fem_turbulent = true; break; + + case FEM_LES: + fem_ns = compressible = true; break; + + case HEAT_EQUATION: + case DISC_ADJ_HEAT: + heat = true; break; + + case FEM_ELASTICITY: + case DISC_ADJ_FEM: + fem = true; break; + + case ADJ_EULER: + adj_euler = euler = compressible = true; break; + + case ADJ_NAVIER_STOKES: + adj_ns = ns = compressible = true; + turbulent = (config->GetKind_Turb_Model() != NONE); break; + + case ADJ_RANS: + adj_ns = ns = compressible = turbulent = true; + adj_turb = !config->GetFrozen_Visc_Cont(); break; + } /*--- Assign turbulence model booleans ---*/ @@ -1955,7 +2037,9 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol case SA_E_COMP: e_comp_spalart_allmaras = true; break; case SST: menter_sst = true; break; case SST_SUST: menter_sst = true; break; - default: SU2_MPI::Error("Specified turbulence model unavailable or none selected", CURRENT_FUNCTION); break; + default: + SU2_MPI::Error("Specified turbulence model unavailable or none selected", CURRENT_FUNCTION); + break; } /*--- If the Menter SST model is used, store the constants of the model and determine the @@ -1978,8 +2062,8 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol if (turbulent) nVar_Turb = solver[MESH_0][TURB_SOL]->GetnVar(); if (transition) nVar_Trans = solver[MESH_0][TRANS_SOL]->GetnVar(); - if (fem_euler) nVar_Flow = solver[MESH_0][FLOW_SOL]->GetnVar(); - if (fem_ns) nVar_Flow = solver[MESH_0][FLOW_SOL]->GetnVar(); + if (fem_euler) nVar_Flow = solver[MESH_0][FLOW_SOL]->GetnVar(); + if (fem_ns) nVar_Flow = solver[MESH_0][FLOW_SOL]->GetnVar(); //if (fem_turbulent) nVar_Turb = solver_container[MESH_0][FEM_TURB_SOL]->GetnVar(); if (fem) nVar_FEM = solver[MESH_0][FEA_SOL]->GetnVar(); @@ -1987,9 +2071,9 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol /*--- Number of variables for adjoint problem ---*/ - if (adj_euler) nVar_Adj_Flow = solver[MESH_0][ADJFLOW_SOL]->GetnVar(); - if (adj_ns) nVar_Adj_Flow = solver[MESH_0][ADJFLOW_SOL]->GetnVar(); - if (adj_turb) nVar_Adj_Turb = solver[MESH_0][ADJTURB_SOL]->GetnVar(); + if (adj_euler) nVar_Adj_Flow = solver[MESH_0][ADJFLOW_SOL]->GetnVar(); + if (adj_ns) nVar_Adj_Flow = solver[MESH_0][ADJFLOW_SOL]->GetnVar(); + if (adj_turb) nVar_Adj_Turb = solver[MESH_0][ADJTURB_SOL]->GetnVar(); /*--- Definition of the Class for the numerical method: numerics_container[INSTANCE_LEVEL][MESH_LEVEL][EQUATION][EQ_TERM] ---*/ @@ -1999,6 +2083,23 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol numerics[iMGlevel][iSol] = new CNumerics* [MAX_TERMS*omp_get_max_threads()](); } + /*--- Instantiate one numerics object per thread for each required term. ---*/ + + for (int thread = 0; thread < omp_get_max_threads(); ++thread) + { + const int offset = thread * MAX_TERMS; + + const int conv_term = CONV_TERM + offset; + const int visc_term = VISC_TERM + offset; + + const int source_first_term = SOURCE_FIRST_TERM + offset; + const int source_second_term = SOURCE_SECOND_TERM + offset; + + const int conv_bound_term = CONV_BOUND_TERM + offset; + const int visc_bound_term = VISC_BOUND_TERM + offset; + + const int fea_term = FEA_TERM + offset; + /*--- Solver definition for the template problem ---*/ if (template_solver) { @@ -2006,22 +2107,25 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol switch (config->GetKind_ConvNumScheme_Template()) { case SPACE_CENTERED : case SPACE_UPWIND : for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][TEMPLATE_SOL][CONV_TERM] = new CConvective_Template(nDim, nVar_Template, config); + numerics[iMGlevel][TEMPLATE_SOL][conv_term] = new CConvective_Template(nDim, nVar_Template, config); + break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Convective scheme not implemented (template_solver).", CURRENT_FUNCTION); break; - default : SU2_MPI::Error("Convective scheme not implemented (template_solver).", CURRENT_FUNCTION); break; } /*--- Definition of the viscous scheme for each equation and mesh level ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][TEMPLATE_SOL][VISC_TERM] = new CViscous_Template(nDim, nVar_Template, config); + numerics[iMGlevel][TEMPLATE_SOL][visc_term] = new CViscous_Template(nDim, nVar_Template, config); /*--- Definition of the source term integration scheme for each equation and mesh level ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][TEMPLATE_SOL][SOURCE_FIRST_TERM] = new CSource_Template(nDim, nVar_Template, config); + numerics[iMGlevel][TEMPLATE_SOL][source_first_term] = new CSource_Template(nDim, nVar_Template, config); /*--- Definition of the boundary condition method ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][TEMPLATE_SOL][CONV_BOUND_TERM] = new CConvective_Template(nDim, nVar_Template, config); + numerics[iMGlevel][TEMPLATE_SOL][conv_bound_term] = new CConvective_Template(nDim, nVar_Template, config); } } @@ -2032,6 +2136,7 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol /*--- Definition of the convective scheme for each equation and mesh level ---*/ switch (config->GetKind_ConvNumScheme_Flow()) { case NO_CONVECTIVE : + SU2_OMP_MASTER SU2_MPI::Error("Config file is missing the CONV_NUM_METHOD_FLOW option.", CURRENT_FUNCTION); break; @@ -2039,33 +2144,39 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol if (compressible) { /*--- Compressible flow ---*/ switch (config->GetKind_Centered_Flow()) { - case LAX : numerics[MESH_0][FLOW_SOL][CONV_TERM] = new CCentLax_Flow(nDim, nVar_Flow, config); break; - case JST : numerics[MESH_0][FLOW_SOL][CONV_TERM] = new CCentJST_Flow(nDim, nVar_Flow, config); break; - case JST_KE : numerics[MESH_0][FLOW_SOL][CONV_TERM] = new CCentJST_KE_Flow(nDim, nVar_Flow, config); break; - default : SU2_MPI::Error("Invalid centered scheme or not implemented.", CURRENT_FUNCTION); break; + case LAX : numerics[MESH_0][FLOW_SOL][conv_term] = new CCentLax_Flow(nDim, nVar_Flow, config); break; + case JST : numerics[MESH_0][FLOW_SOL][conv_term] = new CCentJST_Flow(nDim, nVar_Flow, config); break; + case JST_KE : numerics[MESH_0][FLOW_SOL][conv_term] = new CCentJST_KE_Flow(nDim, nVar_Flow, config); break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Invalid centered scheme or not implemented.", CURRENT_FUNCTION); + break; } for (iMGlevel = 1; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CCentLax_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CCentLax_Flow(nDim, nVar_Flow, config); /*--- Definition of the boundary condition method ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwRoe_Flow(nDim, nVar_Flow, config, false); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwRoe_Flow(nDim, nVar_Flow, config, false); } if (incompressible) { /*--- Incompressible flow, use preconditioning method ---*/ switch (config->GetKind_Centered_Flow()) { - case LAX : numerics[MESH_0][FLOW_SOL][CONV_TERM] = new CCentLaxInc_Flow(nDim, nVar_Flow, config); break; - case JST : numerics[MESH_0][FLOW_SOL][CONV_TERM] = new CCentJSTInc_Flow(nDim, nVar_Flow, config); break; - default : SU2_MPI::Error("Invalid centered scheme or not implemented.\n Currently, only JST and LAX-FRIEDRICH are available for incompressible flows.", CURRENT_FUNCTION); break; + case LAX : numerics[MESH_0][FLOW_SOL][conv_term] = new CCentLaxInc_Flow(nDim, nVar_Flow, config); break; + case JST : numerics[MESH_0][FLOW_SOL][conv_term] = new CCentJSTInc_Flow(nDim, nVar_Flow, config); break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Invalid centered scheme or not implemented.\n Currently, only JST and LAX-FRIEDRICH are available for incompressible flows.", CURRENT_FUNCTION); + break; } for (iMGlevel = 1; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CCentLaxInc_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CCentLaxInc_Flow(nDim, nVar_Flow, config); /*--- Definition of the boundary condition method ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwFDSInc_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwFDSInc_Flow(nDim, nVar_Flow, config); } break; @@ -2077,103 +2188,106 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol if (ideal_gas) { for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwRoe_Flow(nDim, nVar_Flow, config, roe_low_dissipation); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwRoe_Flow(nDim, nVar_Flow, config, false); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwRoe_Flow(nDim, nVar_Flow, config, roe_low_dissipation); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwRoe_Flow(nDim, nVar_Flow, config, false); } } else { for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwGeneralRoe_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwGeneralRoe_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwGeneralRoe_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwGeneralRoe_Flow(nDim, nVar_Flow, config); } } break; case AUSM: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwAUSM_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwAUSM_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwAUSM_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwAUSM_Flow(nDim, nVar_Flow, config); } break; case AUSMPLUSUP: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwAUSMPLUSUP_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwAUSMPLUSUP_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwAUSMPLUSUP_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwAUSMPLUSUP_Flow(nDim, nVar_Flow, config); } break; case AUSMPLUSUP2: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwAUSMPLUSUP2_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwAUSMPLUSUP2_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwAUSMPLUSUP2_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwAUSMPLUSUP2_Flow(nDim, nVar_Flow, config); } break; case TURKEL: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwTurkel_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwTurkel_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwTurkel_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwTurkel_Flow(nDim, nVar_Flow, config); } break; case L2ROE: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwL2Roe_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwL2Roe_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwL2Roe_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwL2Roe_Flow(nDim, nVar_Flow, config); } break; case LMROE: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwLMRoe_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwLMRoe_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwLMRoe_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwLMRoe_Flow(nDim, nVar_Flow, config); } break; case SLAU: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwSLAU_Flow(nDim, nVar_Flow, config, roe_low_dissipation); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwSLAU_Flow(nDim, nVar_Flow, config, false); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwSLAU_Flow(nDim, nVar_Flow, config, roe_low_dissipation); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwSLAU_Flow(nDim, nVar_Flow, config, false); } break; case SLAU2: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwSLAU2_Flow(nDim, nVar_Flow, config, roe_low_dissipation); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwSLAU2_Flow(nDim, nVar_Flow, config, false); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwSLAU2_Flow(nDim, nVar_Flow, config, roe_low_dissipation); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwSLAU2_Flow(nDim, nVar_Flow, config, false); } break; case HLLC: if (ideal_gas) { for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwHLLC_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwHLLC_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwHLLC_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwHLLC_Flow(nDim, nVar_Flow, config); } } else { for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwGeneralHLLC_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwGeneralHLLC_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwGeneralHLLC_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwGeneralHLLC_Flow(nDim, nVar_Flow, config); } } break; case MSW: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwMSW_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwMSW_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwMSW_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwMSW_Flow(nDim, nVar_Flow, config); } break; case CUSP: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwCUSP_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwCUSP_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwCUSP_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwCUSP_Flow(nDim, nVar_Flow, config); } break; - default : SU2_MPI::Error("Invalid upwind scheme or not implemented.", CURRENT_FUNCTION); break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Invalid upwind scheme or not implemented.", CURRENT_FUNCTION); + break; } } @@ -2182,16 +2296,20 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol switch (config->GetKind_Upwind_Flow()) { case FDS: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwFDSInc_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwFDSInc_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwFDSInc_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwFDSInc_Flow(nDim, nVar_Flow, config); } break; - default : SU2_MPI::Error("Invalid upwind scheme or not implemented.\n Currently, only FDS is available for incompressible flows.", CURRENT_FUNCTION); break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Invalid upwind scheme or not implemented.\n Currently, only FDS is available for incompressible flows.", CURRENT_FUNCTION); + break; } } break; - default : + default: + SU2_OMP_MASTER SU2_MPI::Error("Invalid convective scheme for the Euler / Navier-Stokes equations.", CURRENT_FUNCTION); break; } @@ -2201,66 +2319,73 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol if (ideal_gas) { /*--- Compressible flow Ideal gas ---*/ - numerics[MESH_0][FLOW_SOL][VISC_TERM] = new CAvgGrad_Flow(nDim, nVar_Flow, true, config); + numerics[MESH_0][FLOW_SOL][visc_term] = new CAvgGrad_Flow(nDim, nVar_Flow, true, config); for (iMGlevel = 1; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][VISC_TERM] = new CAvgGrad_Flow(nDim, nVar_Flow, false, config); + numerics[iMGlevel][FLOW_SOL][visc_term] = new CAvgGrad_Flow(nDim, nVar_Flow, false, config); /*--- Definition of the boundary condition method ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][VISC_BOUND_TERM] = new CAvgGrad_Flow(nDim, nVar_Flow, false, config); + numerics[iMGlevel][FLOW_SOL][visc_bound_term] = new CAvgGrad_Flow(nDim, nVar_Flow, false, config); } else { - /*--- Compressible flow Realgas ---*/ - numerics[MESH_0][FLOW_SOL][VISC_TERM] = new CGeneralAvgGrad_Flow(nDim, nVar_Flow, true, config); + /*--- Compressible flow Real gas ---*/ + numerics[MESH_0][FLOW_SOL][visc_term] = new CGeneralAvgGrad_Flow(nDim, nVar_Flow, true, config); for (iMGlevel = 1; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][VISC_TERM] = new CGeneralAvgGrad_Flow(nDim, nVar_Flow, false, config); + numerics[iMGlevel][FLOW_SOL][visc_term] = new CGeneralAvgGrad_Flow(nDim, nVar_Flow, false, config); /*--- Definition of the boundary condition method ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][VISC_BOUND_TERM] = new CGeneralAvgGrad_Flow(nDim, nVar_Flow, false, config); + numerics[iMGlevel][FLOW_SOL][visc_bound_term] = new CGeneralAvgGrad_Flow(nDim, nVar_Flow, false, config); } } if (incompressible) { /*--- Incompressible flow, use preconditioning method ---*/ - numerics[MESH_0][FLOW_SOL][VISC_TERM] = new CAvgGradInc_Flow(nDim, nVar_Flow, true, config); + numerics[MESH_0][FLOW_SOL][visc_term] = new CAvgGradInc_Flow(nDim, nVar_Flow, true, config); for (iMGlevel = 1; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][VISC_TERM] = new CAvgGradInc_Flow(nDim, nVar_Flow, false, config); + numerics[iMGlevel][FLOW_SOL][visc_term] = new CAvgGradInc_Flow(nDim, nVar_Flow, false, config); /*--- Definition of the boundary condition method ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][FLOW_SOL][VISC_BOUND_TERM] = new CAvgGradInc_Flow(nDim, nVar_Flow, false, config); + numerics[iMGlevel][FLOW_SOL][visc_bound_term] = new CAvgGradInc_Flow(nDim, nVar_Flow, false, config); } /*--- Definition of the source term integration scheme for each equation and mesh level ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - if (config->GetBody_Force() == YES) + if (config->GetBody_Force() == YES) { if (incompressible) - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceIncBodyForce(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceIncBodyForce(nDim, nVar_Flow, config); else - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceBodyForce(nDim, nVar_Flow, config); - else if (incompressible && (config->GetKind_DensityModel() == BOUSSINESQ)) - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceBoussinesq(nDim, nVar_Flow, config); - else if (config->GetRotating_Frame() == YES) + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceBodyForce(nDim, nVar_Flow, config); + } + else if (incompressible && (config->GetKind_DensityModel() == BOUSSINESQ)) { + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceBoussinesq(nDim, nVar_Flow, config); + } + else if (config->GetRotating_Frame() == YES) { if (incompressible) - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceIncRotatingFrame_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceIncRotatingFrame_Flow(nDim, nVar_Flow, config); else - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceRotatingFrame_Flow(nDim, nVar_Flow, config); - else if (config->GetAxisymmetric() == YES) + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceRotatingFrame_Flow(nDim, nVar_Flow, config); + } + else if (config->GetAxisymmetric() == YES) { if (incompressible) - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceIncAxisymmetric_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceIncAxisymmetric_Flow(nDim, nVar_Flow, config); else - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceAxisymmetric_Flow(nDim, nVar_Flow, config); - else if (config->GetGravityForce() == YES) - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceGravity(nDim, nVar_Flow, config); - else if (config->GetWind_Gust() == YES) - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceWindGust(nDim, nVar_Flow, config); - else - numerics[iMGlevel][FLOW_SOL][SOURCE_FIRST_TERM] = new CSourceNothing(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceAxisymmetric_Flow(nDim, nVar_Flow, config); + } + else if (config->GetGravityForce() == YES) { + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceGravity(nDim, nVar_Flow, config); + } + else if (config->GetWind_Gust() == YES) { + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceWindGust(nDim, nVar_Flow, config); + } + else { + numerics[iMGlevel][FLOW_SOL][source_first_term] = new CSourceNothing(nDim, nVar_Flow, config); + } - numerics[iMGlevel][FLOW_SOL][SOURCE_SECOND_TERM] = new CSourceNothing(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][source_second_term] = new CSourceNothing(nDim, nVar_Flow, config); } } @@ -2269,7 +2394,6 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol if ((fem_euler) || (fem_ns)) { switch (config->GetRiemann_Solver_FEM()) { - case NO_UPWIND : cout << "Riemann solver disabled." << endl; break; case ROE: case LAX_FRIEDRICH: /* Hard coded optimized implementation is used in the DG solver. No need to allocate the @@ -2278,41 +2402,43 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol case AUSM: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwAUSM_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwAUSM_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwAUSM_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwAUSM_Flow(nDim, nVar_Flow, config); } break; case TURKEL: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwTurkel_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwTurkel_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwTurkel_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwTurkel_Flow(nDim, nVar_Flow, config); } break; case HLLC: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwHLLC_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwHLLC_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwHLLC_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwHLLC_Flow(nDim, nVar_Flow, config); } break; case MSW: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwMSW_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwMSW_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwMSW_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwMSW_Flow(nDim, nVar_Flow, config); } break; case CUSP: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][FLOW_SOL][CONV_TERM] = new CUpwCUSP_Flow(nDim, nVar_Flow, config); - numerics[iMGlevel][FLOW_SOL][CONV_BOUND_TERM] = new CUpwCUSP_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_term] = new CUpwCUSP_Flow(nDim, nVar_Flow, config); + numerics[iMGlevel][FLOW_SOL][conv_bound_term] = new CUpwCUSP_Flow(nDim, nVar_Flow, config); } break; - default : + default: + SU2_OMP_MASTER SU2_MPI::Error("Riemann solver not implemented.", CURRENT_FUNCTION); + break; } } @@ -2324,18 +2450,20 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol /*--- Definition of the convective scheme for each equation and mesh level ---*/ switch (config->GetKind_ConvNumScheme_Turb()) { - case NO_UPWIND : + case NO_UPWIND: + SU2_OMP_MASTER SU2_MPI::Error("Config file is missing the CONV_NUM_METHOD_TURB option.", CURRENT_FUNCTION); break; case SPACE_UPWIND : for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { if (spalart_allmaras || neg_spalart_allmaras || e_spalart_allmaras || comp_spalart_allmaras || e_comp_spalart_allmaras ) { - numerics[iMGlevel][TURB_SOL][CONV_TERM] = new CUpwSca_TurbSA(nDim, nVar_Turb, config); + numerics[iMGlevel][TURB_SOL][conv_term] = new CUpwSca_TurbSA(nDim, nVar_Turb, config); } - else if (menter_sst) numerics[iMGlevel][TURB_SOL][CONV_TERM] = new CUpwSca_TurbSST(nDim, nVar_Turb, config); + else if (menter_sst) numerics[iMGlevel][TURB_SOL][conv_term] = new CUpwSca_TurbSST(nDim, nVar_Turb, config); } break; - default : + default: + SU2_OMP_MASTER SU2_MPI::Error("Invalid convective scheme for the turbulence equations.", CURRENT_FUNCTION); break; } @@ -2344,38 +2472,38 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { if (spalart_allmaras || e_spalart_allmaras || comp_spalart_allmaras || e_comp_spalart_allmaras){ - numerics[iMGlevel][TURB_SOL][VISC_TERM] = new CAvgGrad_TurbSA(nDim, nVar_Turb, true, config); + numerics[iMGlevel][TURB_SOL][visc_term] = new CAvgGrad_TurbSA(nDim, nVar_Turb, true, config); } - else if (neg_spalart_allmaras) numerics[iMGlevel][TURB_SOL][VISC_TERM] = new CAvgGrad_TurbSA_Neg(nDim, nVar_Turb, true, config); - else if (menter_sst) numerics[iMGlevel][TURB_SOL][VISC_TERM] = new CAvgGrad_TurbSST(nDim, nVar_Turb, constants, true, config); + else if (neg_spalart_allmaras) numerics[iMGlevel][TURB_SOL][visc_term] = new CAvgGrad_TurbSA_Neg(nDim, nVar_Turb, true, config); + else if (menter_sst) numerics[iMGlevel][TURB_SOL][visc_term] = new CAvgGrad_TurbSST(nDim, nVar_Turb, constants, true, config); } /*--- Definition of the source term integration scheme for each equation and mesh level ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - if (spalart_allmaras) numerics[iMGlevel][TURB_SOL][SOURCE_FIRST_TERM] = new CSourcePieceWise_TurbSA(nDim, nVar_Turb, config); - else if (e_spalart_allmaras) numerics[iMGlevel][TURB_SOL][SOURCE_FIRST_TERM] = new CSourcePieceWise_TurbSA_E(nDim, nVar_Turb, config); - else if (comp_spalart_allmaras) numerics[iMGlevel][TURB_SOL][SOURCE_FIRST_TERM] = new CSourcePieceWise_TurbSA_COMP(nDim, nVar_Turb, config); - else if (e_comp_spalart_allmaras) numerics[iMGlevel][TURB_SOL][SOURCE_FIRST_TERM] = new CSourcePieceWise_TurbSA_E_COMP(nDim, nVar_Turb, config); - else if (neg_spalart_allmaras) numerics[iMGlevel][TURB_SOL][SOURCE_FIRST_TERM] = new CSourcePieceWise_TurbSA_Neg(nDim, nVar_Turb, config); - else if (menter_sst) numerics[iMGlevel][TURB_SOL][SOURCE_FIRST_TERM] = new CSourcePieceWise_TurbSST(nDim, nVar_Turb, constants, kine_Inf, omega_Inf, config); - numerics[iMGlevel][TURB_SOL][SOURCE_SECOND_TERM] = new CSourceNothing(nDim, nVar_Turb, config); + if (spalart_allmaras) numerics[iMGlevel][TURB_SOL][source_first_term] = new CSourcePieceWise_TurbSA(nDim, nVar_Turb, config); + else if (e_spalart_allmaras) numerics[iMGlevel][TURB_SOL][source_first_term] = new CSourcePieceWise_TurbSA_E(nDim, nVar_Turb, config); + else if (comp_spalart_allmaras) numerics[iMGlevel][TURB_SOL][source_first_term] = new CSourcePieceWise_TurbSA_COMP(nDim, nVar_Turb, config); + else if (e_comp_spalart_allmaras) numerics[iMGlevel][TURB_SOL][source_first_term] = new CSourcePieceWise_TurbSA_E_COMP(nDim, nVar_Turb, config); + else if (neg_spalart_allmaras) numerics[iMGlevel][TURB_SOL][source_first_term] = new CSourcePieceWise_TurbSA_Neg(nDim, nVar_Turb, config); + else if (menter_sst) numerics[iMGlevel][TURB_SOL][source_first_term] = new CSourcePieceWise_TurbSST(nDim, nVar_Turb, constants, kine_Inf, omega_Inf, config); + numerics[iMGlevel][TURB_SOL][source_second_term] = new CSourceNothing(nDim, nVar_Turb, config); } /*--- Definition of the boundary condition method ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { if (spalart_allmaras || e_spalart_allmaras || comp_spalart_allmaras || e_comp_spalart_allmaras) { - numerics[iMGlevel][TURB_SOL][CONV_BOUND_TERM] = new CUpwSca_TurbSA(nDim, nVar_Turb, config); - numerics[iMGlevel][TURB_SOL][VISC_BOUND_TERM] = new CAvgGrad_TurbSA(nDim, nVar_Turb, false, config); + numerics[iMGlevel][TURB_SOL][conv_bound_term] = new CUpwSca_TurbSA(nDim, nVar_Turb, config); + numerics[iMGlevel][TURB_SOL][visc_bound_term] = new CAvgGrad_TurbSA(nDim, nVar_Turb, false, config); } else if (neg_spalart_allmaras) { - numerics[iMGlevel][TURB_SOL][CONV_BOUND_TERM] = new CUpwSca_TurbSA(nDim, nVar_Turb, config); - numerics[iMGlevel][TURB_SOL][VISC_BOUND_TERM] = new CAvgGrad_TurbSA_Neg(nDim, nVar_Turb, false, config); + numerics[iMGlevel][TURB_SOL][conv_bound_term] = new CUpwSca_TurbSA(nDim, nVar_Turb, config); + numerics[iMGlevel][TURB_SOL][visc_bound_term] = new CAvgGrad_TurbSA_Neg(nDim, nVar_Turb, false, config); } else if (menter_sst) { - numerics[iMGlevel][TURB_SOL][CONV_BOUND_TERM] = new CUpwSca_TurbSST(nDim, nVar_Turb, config); - numerics[iMGlevel][TURB_SOL][VISC_BOUND_TERM] = new CAvgGrad_TurbSST(nDim, nVar_Turb, constants, false, config); + numerics[iMGlevel][TURB_SOL][conv_bound_term] = new CUpwSca_TurbSST(nDim, nVar_Turb, config); + numerics[iMGlevel][TURB_SOL][visc_bound_term] = new CAvgGrad_TurbSST(nDim, nVar_Turb, constants, false, config); } } } @@ -2385,33 +2513,35 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol /*--- Definition of the convective scheme for each equation and mesh level ---*/ switch (config->GetKind_ConvNumScheme_Turb()) { - case NO_UPWIND : + case NO_UPWIND: + SU2_OMP_MASTER SU2_MPI::Error("Config file is missing the CONV_NUM_METHOD_TURB option.", CURRENT_FUNCTION); break; - case SPACE_UPWIND : + case SPACE_UPWIND: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][TRANS_SOL][CONV_TERM] = new CUpwSca_TransLM(nDim, nVar_Trans, config); + numerics[iMGlevel][TRANS_SOL][conv_term] = new CUpwSca_TransLM(nDim, nVar_Trans, config); } break; - default : + default: + SU2_OMP_MASTER SU2_MPI::Error("Invalid convective scheme for the transition equations.", CURRENT_FUNCTION); break; } /*--- Definition of the viscous scheme for each equation and mesh level ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][TRANS_SOL][VISC_TERM] = new CAvgGradCorrected_TransLM(nDim, nVar_Trans, config); + numerics[iMGlevel][TRANS_SOL][visc_term] = new CAvgGradCorrected_TransLM(nDim, nVar_Trans, config); } /*--- Definition of the source term integration scheme for each equation and mesh level ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][TRANS_SOL][SOURCE_FIRST_TERM] = new CSourcePieceWise_TransLM(nDim, nVar_Trans, config); - numerics[iMGlevel][TRANS_SOL][SOURCE_SECOND_TERM] = new CSourceNothing(nDim, nVar_Trans, config); + numerics[iMGlevel][TRANS_SOL][source_first_term] = new CSourcePieceWise_TransLM(nDim, nVar_Trans, config); + numerics[iMGlevel][TRANS_SOL][source_second_term] = new CSourceNothing(nDim, nVar_Trans, config); } /*--- Definition of the boundary condition method ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][TRANS_SOL][CONV_BOUND_TERM] = new CUpwLin_TransLM(nDim, nVar_Trans, config); + numerics[iMGlevel][TRANS_SOL][conv_bound_term] = new CUpwLin_TransLM(nDim, nVar_Trans, config); } } @@ -2421,22 +2551,23 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol /*--- Definition of the viscous scheme for each equation and mesh level ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][HEAT_SOL][VISC_TERM] = new CAvgGradCorrected_Heat(nDim, nVar_Heat, config); - numerics[iMGlevel][HEAT_SOL][VISC_BOUND_TERM] = new CAvgGrad_Heat(nDim, nVar_Heat, config); + numerics[iMGlevel][HEAT_SOL][visc_term] = new CAvgGradCorrected_Heat(nDim, nVar_Heat, config); + numerics[iMGlevel][HEAT_SOL][visc_bound_term] = new CAvgGrad_Heat(nDim, nVar_Heat, config); switch (config->GetKind_ConvNumScheme_Heat()) { case SPACE_UPWIND : - numerics[iMGlevel][HEAT_SOL][CONV_TERM] = new CUpwSca_Heat(nDim, nVar_Heat, config); - numerics[iMGlevel][HEAT_SOL][CONV_BOUND_TERM] = new CUpwSca_Heat(nDim, nVar_Heat, config); + numerics[iMGlevel][HEAT_SOL][conv_term] = new CUpwSca_Heat(nDim, nVar_Heat, config); + numerics[iMGlevel][HEAT_SOL][conv_bound_term] = new CUpwSca_Heat(nDim, nVar_Heat, config); break; case SPACE_CENTERED : - numerics[iMGlevel][HEAT_SOL][CONV_TERM] = new CCentSca_Heat(nDim, nVar_Heat, config); - numerics[iMGlevel][HEAT_SOL][CONV_BOUND_TERM] = new CUpwSca_Heat(nDim, nVar_Heat, config); + numerics[iMGlevel][HEAT_SOL][conv_term] = new CCentSca_Heat(nDim, nVar_Heat, config); + numerics[iMGlevel][HEAT_SOL][conv_bound_term] = new CUpwSca_Heat(nDim, nVar_Heat, config); break; - default : + default: + SU2_OMP_MASTER SU2_MPI::Error("Invalid convective scheme for the heat transfer equations.", CURRENT_FUNCTION); break; } @@ -2448,12 +2579,14 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol if (adj_euler || adj_ns) { if (incompressible) + SU2_OMP_MASTER SU2_MPI::Error("Convective schemes not implemented for incompressible continuous adjoint.", CURRENT_FUNCTION); /*--- Definition of the convective scheme for each equation and mesh level ---*/ switch (config->GetKind_ConvNumScheme_AdjFlow()) { - case NO_CONVECTIVE : + case NO_CONVECTIVE: + SU2_OMP_MASTER SU2_MPI::Error("Config file is missing the CONV_NUM_METHOD_ADJFLOW option.", CURRENT_FUNCTION); break; @@ -2464,16 +2597,19 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol /*--- Compressible flow ---*/ switch (config->GetKind_Centered_AdjFlow()) { - case LAX : numerics[MESH_0][ADJFLOW_SOL][CONV_TERM] = new CCentLax_AdjFlow(nDim, nVar_Adj_Flow, config); break; - case JST : numerics[MESH_0][ADJFLOW_SOL][CONV_TERM] = new CCentJST_AdjFlow(nDim, nVar_Adj_Flow, config); break; - default : SU2_MPI::Error("Centered scheme not implemented.", CURRENT_FUNCTION); break; + case LAX : numerics[MESH_0][ADJFLOW_SOL][conv_term] = new CCentLax_AdjFlow(nDim, nVar_Adj_Flow, config); break; + case JST : numerics[MESH_0][ADJFLOW_SOL][conv_term] = new CCentJST_AdjFlow(nDim, nVar_Adj_Flow, config); break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Centered scheme not implemented.", CURRENT_FUNCTION); + break; } for (iMGlevel = 1; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][ADJFLOW_SOL][CONV_TERM] = new CCentLax_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][conv_term] = new CCentLax_AdjFlow(nDim, nVar_Adj_Flow, config); for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][ADJFLOW_SOL][CONV_BOUND_TERM] = new CUpwRoe_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][conv_bound_term] = new CUpwRoe_AdjFlow(nDim, nVar_Adj_Flow, config); } break; @@ -2487,16 +2623,20 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol switch (config->GetKind_Upwind_AdjFlow()) { case ROE: for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][ADJFLOW_SOL][CONV_TERM] = new CUpwRoe_AdjFlow(nDim, nVar_Adj_Flow, config); - numerics[iMGlevel][ADJFLOW_SOL][CONV_BOUND_TERM] = new CUpwRoe_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][conv_term] = new CUpwRoe_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][conv_bound_term] = new CUpwRoe_AdjFlow(nDim, nVar_Adj_Flow, config); } break; - default : SU2_MPI::Error("Upwind scheme not implemented.", CURRENT_FUNCTION); break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Upwind scheme not implemented.", CURRENT_FUNCTION); + break; } } break; - default : + default: + SU2_OMP_MASTER SU2_MPI::Error("Invalid convective scheme for the continuous adjoint Euler / Navier-Stokes equations.", CURRENT_FUNCTION); break; } @@ -2507,12 +2647,12 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol /*--- Compressible flow ---*/ - numerics[MESH_0][ADJFLOW_SOL][VISC_TERM] = new CAvgGradCorrected_AdjFlow(nDim, nVar_Adj_Flow, config); - numerics[MESH_0][ADJFLOW_SOL][VISC_BOUND_TERM] = new CAvgGrad_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[MESH_0][ADJFLOW_SOL][visc_term] = new CAvgGradCorrected_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[MESH_0][ADJFLOW_SOL][visc_bound_term] = new CAvgGrad_AdjFlow(nDim, nVar_Adj_Flow, config); for (iMGlevel = 1; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][ADJFLOW_SOL][VISC_TERM] = new CAvgGrad_AdjFlow(nDim, nVar_Adj_Flow, config); - numerics[iMGlevel][ADJFLOW_SOL][VISC_BOUND_TERM] = new CAvgGrad_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][visc_term] = new CAvgGrad_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][visc_bound_term] = new CAvgGrad_AdjFlow(nDim, nVar_Adj_Flow, config); } } @@ -2527,25 +2667,25 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol if (adj_ns) { - numerics[iMGlevel][ADJFLOW_SOL][SOURCE_FIRST_TERM] = new CSourceViscous_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][source_first_term] = new CSourceViscous_AdjFlow(nDim, nVar_Adj_Flow, config); if (config->GetRotating_Frame() == YES) - numerics[iMGlevel][ADJFLOW_SOL][SOURCE_SECOND_TERM] = new CSourceRotatingFrame_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][source_second_term] = new CSourceRotatingFrame_AdjFlow(nDim, nVar_Adj_Flow, config); else - numerics[iMGlevel][ADJFLOW_SOL][SOURCE_SECOND_TERM] = new CSourceConservative_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][source_second_term] = new CSourceConservative_AdjFlow(nDim, nVar_Adj_Flow, config); } else { if (config->GetRotating_Frame() == YES) - numerics[iMGlevel][ADJFLOW_SOL][SOURCE_FIRST_TERM] = new CSourceRotatingFrame_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][source_first_term] = new CSourceRotatingFrame_AdjFlow(nDim, nVar_Adj_Flow, config); else if (config->GetAxisymmetric() == YES) - numerics[iMGlevel][ADJFLOW_SOL][SOURCE_FIRST_TERM] = new CSourceAxisymmetric_AdjFlow(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][source_first_term] = new CSourceAxisymmetric_AdjFlow(nDim, nVar_Adj_Flow, config); else - numerics[iMGlevel][ADJFLOW_SOL][SOURCE_FIRST_TERM] = new CSourceNothing(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][source_first_term] = new CSourceNothing(nDim, nVar_Adj_Flow, config); - numerics[iMGlevel][ADJFLOW_SOL][SOURCE_SECOND_TERM] = new CSourceNothing(nDim, nVar_Adj_Flow, config); + numerics[iMGlevel][ADJFLOW_SOL][source_second_term] = new CSourceNothing(nDim, nVar_Adj_Flow, config); } @@ -2559,139 +2699,135 @@ void CDriver::Numerics_Preprocessing(CConfig *config, CGeometry **geometry, CSol if (adj_turb) { if (!spalart_allmaras) + SU2_OMP_MASTER SU2_MPI::Error("Only the SA turbulence model can be used with the continuous adjoint solver.", CURRENT_FUNCTION); - + /*--- Definition of the convective scheme for each equation and mesh level ---*/ switch (config->GetKind_ConvNumScheme_AdjTurb()) { - case NO_CONVECTIVE : + case NO_CONVECTIVE: + SU2_OMP_MASTER SU2_MPI::Error("Config file is missing the CONV_NUM_METHOD_ADJTURB option.", CURRENT_FUNCTION); break; case SPACE_UPWIND : for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][ADJTURB_SOL][CONV_TERM] = new CUpwSca_AdjTurb(nDim, nVar_Adj_Turb, config); + numerics[iMGlevel][ADJTURB_SOL][conv_term] = new CUpwSca_AdjTurb(nDim, nVar_Adj_Turb, config); break; - default : + default: + SU2_OMP_MASTER SU2_MPI::Error("Convective scheme not implemented (adjoint turbulence).", CURRENT_FUNCTION); break; } /*--- Definition of the viscous scheme for each equation and mesh level ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][ADJTURB_SOL][VISC_TERM] = new CAvgGradCorrected_AdjTurb(nDim, nVar_Adj_Turb, config); + numerics[iMGlevel][ADJTURB_SOL][visc_term] = new CAvgGradCorrected_AdjTurb(nDim, nVar_Adj_Turb, config); /*--- Definition of the source term integration scheme for each equation and mesh level ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) { - numerics[iMGlevel][ADJTURB_SOL][SOURCE_FIRST_TERM] = new CSourcePieceWise_AdjTurb(nDim, nVar_Adj_Turb, config); - numerics[iMGlevel][ADJTURB_SOL][SOURCE_SECOND_TERM] = new CSourceConservative_AdjTurb(nDim, nVar_Adj_Turb, config); + numerics[iMGlevel][ADJTURB_SOL][source_first_term] = new CSourcePieceWise_AdjTurb(nDim, nVar_Adj_Turb, config); + numerics[iMGlevel][ADJTURB_SOL][source_second_term] = new CSourceConservative_AdjTurb(nDim, nVar_Adj_Turb, config); } /*--- Definition of the boundary condition method ---*/ for (iMGlevel = 0; iMGlevel <= config->GetnMGLevels(); iMGlevel++) - numerics[iMGlevel][ADJTURB_SOL][CONV_BOUND_TERM] = new CUpwLin_AdjTurb(nDim, nVar_Adj_Turb, config); + numerics[iMGlevel][ADJTURB_SOL][conv_bound_term] = new CUpwLin_AdjTurb(nDim, nVar_Adj_Turb, config); } - /*--- Numerics definition for FEM-like problems. Instantiate one numerics per thread. ---*/ + /*--- Numerics definition for FEM-like problems. ---*/ - SU2_OMP_PARALLEL - { - int thread = omp_get_thread_num(); - int offset = thread * MAX_TERMS; - int fea_term = FEA_TERM + offset; - - if (fem) { - /*--- Initialize the container for FEA_TERM. This will be the only one for most of the cases ---*/ - switch (config->GetGeometricConditions()) { - case SMALL_DEFORMATIONS: - switch (config->GetMaterialModel()) { - case LINEAR_ELASTIC: - numerics[MESH_0][FEA_SOL][fea_term] = new CFEALinearElasticity(nDim, nVar_FEM, config); - break; - case NEO_HOOKEAN: - SU2_OMP_MASTER - SU2_MPI::Error("Material model does not correspond to geometric conditions.", CURRENT_FUNCTION); - break; - default: + if (fem) { + /*--- Initialize the container for FEA_TERM. This will be the only one for most of the cases. ---*/ + switch (config->GetGeometricConditions()) { + case SMALL_DEFORMATIONS: + switch (config->GetMaterialModel()) { + case LINEAR_ELASTIC: + numerics[MESH_0][FEA_SOL][fea_term] = new CFEALinearElasticity(nDim, nVar_FEM, config); + break; + case NEO_HOOKEAN: + SU2_OMP_MASTER + SU2_MPI::Error("Material model does not correspond to geometric conditions.", CURRENT_FUNCTION); + break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Material model not implemented.", CURRENT_FUNCTION); + break; + } + break; + case LARGE_DEFORMATIONS : + switch (config->GetMaterialModel()) { + case LINEAR_ELASTIC: + SU2_OMP_MASTER + SU2_MPI::Error("Material model does not correspond to geometric conditions.", CURRENT_FUNCTION); + break; + case NEO_HOOKEAN: + if (config->GetMaterialCompressibility() == COMPRESSIBLE_MAT) { + numerics[MESH_0][FEA_SOL][fea_term] = new CFEM_NeoHookean_Comp(nDim, nVar_FEM, config); + } else { SU2_OMP_MASTER SU2_MPI::Error("Material model not implemented.", CURRENT_FUNCTION); - break; - } - break; - case LARGE_DEFORMATIONS : - switch (config->GetMaterialModel()) { - case LINEAR_ELASTIC: + } + break; + case KNOWLES: + if (config->GetMaterialCompressibility() == NEARLY_INCOMPRESSIBLE_MAT) { + numerics[MESH_0][FEA_SOL][fea_term] = new CFEM_Knowles_NearInc(nDim, nVar_FEM, config); + } else { SU2_OMP_MASTER - SU2_MPI::Error("Material model does not correspond to geometric conditions.", CURRENT_FUNCTION); - break; - case NEO_HOOKEAN: - if (config->GetMaterialCompressibility() == COMPRESSIBLE_MAT) { - numerics[MESH_0][FEA_SOL][fea_term] = new CFEM_NeoHookean_Comp(nDim, nVar_FEM, config); - } else { - SU2_OMP_MASTER - SU2_MPI::Error("Material model not implemented.", CURRENT_FUNCTION); - } - break; - case KNOWLES: - if (config->GetMaterialCompressibility() == NEARLY_INCOMPRESSIBLE_MAT) { - numerics[MESH_0][FEA_SOL][fea_term] = new CFEM_Knowles_NearInc(nDim, nVar_FEM, config); - } else { - SU2_OMP_MASTER - SU2_MPI::Error("Material model not implemented.", CURRENT_FUNCTION); - } - break; - case IDEAL_DE: - if (config->GetMaterialCompressibility() == NEARLY_INCOMPRESSIBLE_MAT) { - numerics[MESH_0][FEA_SOL][fea_term] = new CFEM_IdealDE(nDim, nVar_FEM, config); - } else { - SU2_OMP_MASTER - SU2_MPI::Error("Material model not implemented.", CURRENT_FUNCTION); - } - break; - default: + SU2_MPI::Error("Material model not implemented.", CURRENT_FUNCTION); + } + break; + case IDEAL_DE: + if (config->GetMaterialCompressibility() == NEARLY_INCOMPRESSIBLE_MAT) { + numerics[MESH_0][FEA_SOL][fea_term] = new CFEM_IdealDE(nDim, nVar_FEM, config); + } else { SU2_OMP_MASTER SU2_MPI::Error("Material model not implemented.", CURRENT_FUNCTION); - break; - } - break; - default: - SU2_OMP_MASTER - SU2_MPI::Error("Solver not implemented.", CURRENT_FUNCTION); - break; - } + } + break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Material model not implemented.", CURRENT_FUNCTION); + break; + } + break; + default: + SU2_OMP_MASTER + SU2_MPI::Error("Solver not implemented.", CURRENT_FUNCTION); + break; + } - /*--- The following definitions only make sense if we have a non-linear solution. ---*/ - if (config->GetGeometricConditions() == LARGE_DEFORMATIONS) { + /*--- The following definitions only make sense if we have a non-linear solution. ---*/ + if (config->GetGeometricConditions() == LARGE_DEFORMATIONS) { - /*--- This allocates a container for electromechanical effects. ---*/ + /*--- This allocates a container for electromechanical effects. ---*/ - bool de_effects = config->GetDE_Effects(); - if (de_effects) - numerics[MESH_0][FEA_SOL][DE_TERM+offset] = new CFEM_DielectricElastomer(nDim, nVar_FEM, config); + bool de_effects = config->GetDE_Effects(); + if (de_effects) + numerics[MESH_0][FEA_SOL][DE_TERM+offset] = new CFEM_DielectricElastomer(nDim, nVar_FEM, config); - string filename; - ifstream properties_file; + ifstream properties_file; - filename = config->GetFEA_FileName(); - if (nZone > 1) - filename = config->GetMultizone_FileName(filename, iZone, ".dat"); + string filename = config->GetFEA_FileName(); + if (nZone > 1) + filename = config->GetMultizone_FileName(filename, iZone, ".dat"); - properties_file.open(filename.data(), ios::in); + properties_file.open(filename.data(), ios::in); - /*--- In case there is a properties file, containers are allocated for a number of material models. ---*/ + /*--- In case there is a properties file, containers are allocated for a number of material models. ---*/ - if (!(properties_file.fail())) { - numerics[MESH_0][FEA_SOL][MAT_NHCOMP+offset] = new CFEM_NeoHookean_Comp(nDim, nVar_FEM, config); - numerics[MESH_0][FEA_SOL][MAT_IDEALDE+offset] = new CFEM_IdealDE(nDim, nVar_FEM, config); - numerics[MESH_0][FEA_SOL][MAT_KNOWLES+offset] = new CFEM_Knowles_NearInc(nDim, nVar_FEM, config); - } + if (!(properties_file.fail())) { + numerics[MESH_0][FEA_SOL][MAT_NHCOMP+offset] = new CFEM_NeoHookean_Comp(nDim, nVar_FEM, config); + numerics[MESH_0][FEA_SOL][MAT_IDEALDE+offset] = new CFEM_IdealDE(nDim, nVar_FEM, config); + numerics[MESH_0][FEA_SOL][MAT_KNOWLES+offset] = new CFEM_Knowles_NearInc(nDim, nVar_FEM, config); } } + } - /*--- Instantiate the numerics for the mesh solver. ---*/ - if (config->GetDeform_Mesh()) - numerics[MESH_0][MESH_SOL][fea_term] = new CFEAMeshElasticity(nDim, nDim, geometry[MESH_0]->GetnElem(), config); + /*--- Instantiate the numerics for the mesh solver. ---*/ + if (config->GetDeform_Mesh()) + numerics[MESH_0][MESH_SOL][fea_term] = new CFEAMeshElasticity(nDim, nDim, geometry[MESH_0]->GetnElem(), config); - } // end SU2_OMP_PARALLEL + } // end "per-thread" allocation loop } diff --git a/SU2_CFD/src/integration/CFEM_DG_Integration.cpp b/SU2_CFD/src/integration/CFEM_DG_Integration.cpp new file mode 100644 index 000000000000..a5202ada63dc --- /dev/null +++ b/SU2_CFD/src/integration/CFEM_DG_Integration.cpp @@ -0,0 +1,184 @@ +/*! + * \file CFEM_DG_Integration.cpp + * \brief Definition of time and space integration for the DG solver. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../include/integration/CFEM_DG_Integration.hpp" + + +CFEM_DG_Integration::CFEM_DG_Integration(CConfig *config) : CIntegration(config) { } + +void CFEM_DG_Integration::SingleGrid_Iteration(CGeometry ****geometry, + CSolver *****solver_container, + CNumerics ******numerics_container, + CConfig **config, + unsigned short RunTime_EqSystem, + unsigned short iZone, + unsigned short iInst) { + + unsigned short iMesh, iStep, iLimit = 1; + unsigned short SolContainer_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); + unsigned short FinestMesh = config[iZone]->GetFinestMesh(); + + /*--- For now, we assume no geometric multigrid. ---*/ + iMesh = FinestMesh; + + /*--- Check if only the Jacobian of the spatial discretization must + be computed. If so, call the appropriate function and return. ---*/ + if (config[iZone]->GetJacobian_Spatial_Discretization_Only()) { + solver_container[iZone][iInst][iMesh][SolContainer_Position]->ComputeSpatialJacobian(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], + numerics_container[iZone][iInst][iMesh][SolContainer_Position], + config[iZone], iMesh, RunTime_EqSystem); + return; + } + + /*--- Determine the number of stages in the time stepping algorithm. + For the Runge-Kutta schemes this is the number of RK stages, + while for ADER-DG this information is not used, because a more + complicated algorithm must be used to facilitate time accurate + local time stepping. Note that we are currently hard-coding + the classical RK4 scheme. ---*/ + bool useADER = false; + switch (config[iZone]->GetKind_TimeIntScheme()) { + case RUNGE_KUTTA_EXPLICIT: iLimit = config[iZone]->GetnRKStep(); break; + case CLASSICAL_RK4_EXPLICIT: iLimit = 4; break; + case ADER_DG: iLimit = 1; useADER = true; break; + case EULER_EXPLICIT: case EULER_IMPLICIT: iLimit = 1; break; } + + /*--- In case an unsteady simulation is carried out, it is possible that a + synchronization time step is specified. If so, set the boolean + TimeSynSpecified to true, which leads to an outer loop in the + algorithm below. ---*/ + bool TimeSyncSpecified = false; + const su2double TimeSync = config[iZone]->GetTime_Step()/config[iZone]->GetTime_Ref(); + if(config[iZone]->GetTime_Marching() == TIME_STEPPING && + config[iZone]->GetUnst_CFL() != 0.0 && + TimeSync != 0.0) TimeSyncSpecified = true; + + /*--- Outer loop, which is only active when a synchronization time has been + specified for an unsteady simulation. ---*/ + bool syncTimeReached = false; + su2double timeEvolved = 0.0; + while( !syncTimeReached ) { + + /* Compute the time step for stability. */ + solver_container[iZone][iInst][iMesh][SolContainer_Position]->SetTime_Step(geometry[iZone][iInst][iMesh], + solver_container[iZone][iInst][iMesh], + config[iZone], iMesh, config[iZone]->GetTimeIter()); + /* Possibly overrule the specified time step when a synchronization time was + specified and determine whether or not the time loop must be continued. + When TimeSyncSpecified is false, the loop is always terminated. */ + if( TimeSyncSpecified ) + solver_container[iZone][iInst][iMesh][SolContainer_Position]->CheckTimeSynchronization(config[iZone], + TimeSync, timeEvolved, + syncTimeReached); + else + syncTimeReached = true; + + /*--- For ADER in combination with time accurate local time stepping, the + space and time integration are tightly coupled and cannot be treated + segregatedly. Therefore a different function is called for ADER to + carry out the space and time integration. ---*/ + if( useADER ) { + solver_container[iZone][iInst][iMesh][SolContainer_Position]->ADER_SpaceTimeIntegration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], + numerics_container[iZone][iInst][iMesh][SolContainer_Position], + config[iZone], iMesh, RunTime_EqSystem); + } + else { + + /*--- Time and space integration can be decoupled. ---*/ + for (iStep = 0; iStep < iLimit; iStep++) { + + /*--- Preprocessing ---*/ + solver_container[iZone][iInst][iMesh][SolContainer_Position]->Preprocessing(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], + config[iZone], iMesh, iStep, RunTime_EqSystem, false); + + /*--- Space integration ---*/ + Space_Integration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], + numerics_container[iZone][iInst][iMesh][SolContainer_Position], + config[iZone], iMesh, iStep, RunTime_EqSystem); + + /*--- Time integration, update solution using the old solution plus the solution increment ---*/ + Time_Integration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], + config[iZone], iStep, RunTime_EqSystem); + + /*--- Postprocessing ---*/ + solver_container[iZone][iInst][iMesh][SolContainer_Position]->Postprocessing(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], + config[iZone], iMesh); + } + } + } + + /*--- Calculate the inviscid and viscous forces ---*/ + solver_container[iZone][iInst][FinestMesh][SolContainer_Position]->Pressure_Forces(geometry[iZone][iInst][iMesh], config[iZone]); + + solver_container[iZone][iInst][FinestMesh][SolContainer_Position]->Friction_Forces(geometry[iZone][iInst][iMesh], config[iZone]); + + /*--- Convergence strategy ---*/ + + //Convergence_Monitoring(geometry[iZone][iInst][FinestMesh], config[iZone], Iteration, monitor, FinestMesh); +} + +void CFEM_DG_Integration::Space_Integration(CGeometry *geometry, + CSolver **solver_container, + CNumerics **numerics, + CConfig *config, unsigned short iMesh, + unsigned short iStep, + unsigned short RunTime_EqSystem) { + + unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); + + /*--- Runge-Kutta type of time integration schemes. In the first step, i.e. + if iStep == 0, set the old solution (working solution for the DG part), + and if needed, the new solution. ---*/ + if (iStep == 0) { + solver_container[MainSolver]->Set_OldSolution(geometry); + + if (config->GetKind_TimeIntScheme() == CLASSICAL_RK4_EXPLICIT) { + solver_container[MainSolver]->Set_NewSolution(geometry); + } + } + + /*--- Compute the spatial residual by processing the task list. ---*/ + solver_container[MainSolver]->ProcessTaskList_DG(geometry, solver_container, numerics, config, iMesh); +} + +void CFEM_DG_Integration::Time_Integration(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iStep, + unsigned short RunTime_EqSystem) { + + unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); + + /*--- Perform the time integration ---*/ + switch (config->GetKind_TimeIntScheme()) { + case (RUNGE_KUTTA_EXPLICIT): + solver_container[MainSolver]->ExplicitRK_Iteration(geometry, solver_container, config, iStep); + break; + case (CLASSICAL_RK4_EXPLICIT): + solver_container[MainSolver]->ClassicalRK4_Iteration(geometry, solver_container, config, iStep); + break; + default: + SU2_MPI::Error("Time integration scheme not implemented.", CURRENT_FUNCTION); + } +} diff --git a/SU2_CFD/src/integration_structure.cpp b/SU2_CFD/src/integration/CIntegration.cpp similarity index 54% rename from SU2_CFD/src/integration_structure.cpp rename to SU2_CFD/src/integration/CIntegration.cpp index 60301c777090..99aa92e8e5bf 100644 --- a/SU2_CFD/src/integration_structure.cpp +++ b/SU2_CFD/src/integration/CIntegration.cpp @@ -1,12 +1,12 @@ /*! - * \file integration_structure.cpp - * \brief This subroutine includes the space and time integration structure + * \file CIntegration.cpp + * \brief Implementation of the base class for space and time integration. * \author F. Palacios, T. Economon * \version 7.0.1 "Blackbird" * * 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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -25,8 +25,9 @@ * License along with SU2. If not, see . */ +#include "../../include/integration/CIntegration.hpp" +#include "../../../Common/include/omp_structure.hpp" -#include "../include/integration_structure.hpp" CIntegration::CIntegration(CConfig *config) { rank = SU2_MPI::GetRank(); @@ -39,14 +40,10 @@ CIntegration::CIntegration(CConfig *config) { Convergence = false; Convergence_FSI = false; Convergence_FullMG = false; - Cauchy_Serie = new su2double [config->GetCauchy_Elems()+1]; + Cauchy_Serie.resize(config->GetCauchy_Elems()+1, 0.0); InitResidual = 0.0; } -CIntegration::~CIntegration(void) { - delete [] Cauchy_Serie; -} - void CIntegration::Space_Integration(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, @@ -54,38 +51,43 @@ void CIntegration::Space_Integration(CGeometry *geometry, unsigned short iRKStep, unsigned short RunTime_EqSystem) { unsigned short iMarker, KindBC; - + unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || (config->GetTime_Marching() == DT_STEPPING_2ND)); /*--- Compute inviscid residuals ---*/ - + switch (config->GetKind_ConvNumScheme()) { case SPACE_CENTERED: - solver_container[MainSolver]->Centered_Residual(geometry, solver_container, numerics[CONV_TERM], config, iMesh, iRKStep); + solver_container[MainSolver]->Centered_Residual(geometry, solver_container, numerics, config, iMesh, iRKStep); break; case SPACE_UPWIND: - solver_container[MainSolver]->Upwind_Residual(geometry, solver_container, numerics[CONV_TERM], config, iMesh); + solver_container[MainSolver]->Upwind_Residual(geometry, solver_container, numerics, config, iMesh); break; case FINITE_ELEMENT: solver_container[MainSolver]->Convective_Residual(geometry, solver_container, numerics[CONV_TERM], config, iMesh, iRKStep); break; } - + /*--- Compute viscous residuals ---*/ - - solver_container[MainSolver]->Viscous_Residual(geometry, solver_container, numerics[VISC_TERM], config, iMesh, iRKStep); - + + solver_container[MainSolver]->Viscous_Residual(geometry, solver_container, numerics, config, iMesh, iRKStep); + /*--- Compute source term residuals ---*/ - solver_container[MainSolver]->Source_Residual(geometry, solver_container, numerics[SOURCE_FIRST_TERM], numerics[SOURCE_SECOND_TERM], config, iMesh); - + solver_container[MainSolver]->Source_Residual(geometry, solver_container, numerics, config, iMesh); + /*--- Add viscous and convective residuals, and compute the Dual Time Source term ---*/ - + if (dual_time) solver_container[MainSolver]->SetResidual_DualTime(geometry, solver_container, config, iRKStep, iMesh, RunTime_EqSystem); - + + /// TODO: No boundary condition supports hybrid parallelism yet, master thread does all the work. + + SU2_OMP_MASTER + { + /*--- Boundary conditions that depend on other boundaries (they require MPI sincronization)---*/ solver_container[MainSolver]->BC_Fluid_Interface(geometry, solver_container, numerics[CONV_BOUND_TERM], numerics[VISC_BOUND_TERM], config); @@ -99,7 +101,7 @@ void CIntegration::Space_Integration(CGeometry *geometry, } /*--- Weak boundary conditions ---*/ - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { KindBC = config->GetMarker_All_KindBC(iMarker); switch (KindBC) { @@ -155,9 +157,9 @@ void CIntegration::Space_Integration(CGeometry *geometry, break; } } - + /*--- Strong boundary conditions (Navier-Stokes and Dirichlet type BCs) ---*/ - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) switch (config->GetMarker_All_KindBC(iMarker)) { case ISOTHERMAL: @@ -169,8 +171,8 @@ void CIntegration::Space_Integration(CGeometry *geometry, case CUSTOM_BOUNDARY: solver_container[MainSolver]->BC_Custom(geometry, solver_container, numerics[CONV_BOUND_TERM], numerics[VISC_BOUND_TERM], config, iMarker); break; - case CHT_WALL_INTERFACE: - if ((MainSolver == HEAT_SOL) || (MainSolver == FLOW_SOL && ((config->GetKind_Regime() == COMPRESSIBLE) || config->GetEnergy_Equation()))) { + case CHT_WALL_INTERFACE: + if ((MainSolver == HEAT_SOL) || ((MainSolver == FLOW_SOL) && ((config->GetKind_Regime() == COMPRESSIBLE) || config->GetEnergy_Equation()))) { solver_container[MainSolver]->BC_ConjugateHeat_Interface(geometry, solver_container, numerics[CONV_BOUND_TERM], config, iMarker); } else { @@ -178,328 +180,129 @@ void CIntegration::Space_Integration(CGeometry *geometry, } break; } - + /*--- 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 corectly during the communications. ---*/ - + if (config->GetnMarker_Periodic() > 0) { solver_container[MainSolver]->BC_Periodic(geometry, solver_container, numerics[CONV_BOUND_TERM], config); } - -} - -void CIntegration::Space_Integration_FEM(CGeometry *geometry, - CSolver **solver_container, - CNumerics **numerics, - CConfig *config, - unsigned short RunTime_EqSystem) { - - bool dynamic = config->GetTime_Domain(); - bool first_iter = (config->GetInnerIter() == 0); - bool linear_analysis = (config->GetGeometricConditions() == SMALL_DEFORMATIONS); - bool nonlinear_analysis = (config->GetGeometricConditions() == LARGE_DEFORMATIONS); - unsigned short IterativeScheme = config->GetKind_SpaceIteScheme_FEA(); - - unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); - CSolver* solver = solver_container[MainSolver]; - - /*--- Initial calculation, different logic for restarted simulations. ---*/ - bool initial_calc = false; - if (config->GetRestart()) - initial_calc = (config->GetTimeIter() == config->GetRestart_Iter()) && first_iter; - else - initial_calc = (config->GetTimeIter() == 0) && first_iter; - - /*--- Mass Matrix computed during preprocessing, see notes therein. ---*/ - - /*--- If the analysis is linear, only a the constitutive term of the stiffness matrix has to be computed. ---*/ - /*--- This is done only once, at the beginning of the calculation. From then on, K is constant. ---*/ - /*--- For correct differentiation of dynamic cases the matrix needs to be computed every time. ---*/ - if (linear_analysis && (dynamic || initial_calc)) - solver->Compute_StiffMatrix(geometry, numerics, config); - - if (nonlinear_analysis) { - - /*--- If the analysis is nonlinear the stress terms also need to be computed. ---*/ - /*--- For full Newton-Raphson the stiffness matrix and the nodal term are updated every time. ---*/ - if (IterativeScheme == NEWTON_RAPHSON) { - solver->Compute_StiffMatrix_NodalStressRes(geometry, numerics, config); - } - - /*--- If the method is modified Newton-Raphson, the stiffness matrix is only computed once at the beginning - * of the time step, then only the Nodal Stress Term has to be computed on each iteration. ---*/ - if (IterativeScheme == MODIFIED_NEWTON_RAPHSON) { - if (first_iter) - solver->Compute_StiffMatrix_NodalStressRes(geometry, numerics, config); - else - solver->Compute_NodalStressRes(geometry, numerics, config); - } - - } - - /*--- Apply the NATURAL BOUNDARY CONDITIONS (loads). ---*/ - /*--- If there are FSI loads, they have to be previously applied at other level involving both zones. ---*/ - - for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - switch (config->GetMarker_All_KindBC(iMarker)) { - - /*--- Some external loads are considered constant over the time step ---*/ - case LOAD_DIR_BOUNDARY: - if (first_iter) - solver->BC_Dir_Load(geometry, numerics[FEA_TERM], config, iMarker); - break; - - case LOAD_SINE_BOUNDARY: - if (first_iter) - solver->BC_Sine_Load(geometry, numerics[FEA_TERM], config, iMarker); - break; - - /*--- Others are not, because they depend on the geometry ---*/ - - case LOAD_BOUNDARY: - solver->BC_Normal_Load(geometry, numerics[FEA_TERM], config, iMarker); - break; - - case DAMPER_BOUNDARY: - solver->BC_Damper(geometry, numerics[FEA_TERM], config, iMarker); - break; - } - } + } // end SU2_OMP_MASTER + SU2_OMP_BARRIER } -void CIntegration::Adjoint_Setup(CGeometry ****geometry, CSolver *****solver_container, CConfig **config, - unsigned short RunTime_EqSystem, unsigned long Iteration, unsigned short iZone) { - - unsigned short iMGLevel; - - if ( ( (RunTime_EqSystem == RUNTIME_ADJFLOW_SYS) && (Iteration == 0) ) ) { - for (iMGLevel = 0; iMGLevel <= config[iZone]->GetnMGLevels(); iMGLevel++) { - - /*--- Set the time step in all the MG levels ---*/ - - solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTime_Step(geometry[iZone][INST_0][iMGLevel], solver_container[iZone][INST_0][iMGLevel], config[iZone], iMGLevel, Iteration); - - /*--- Set the force coefficients ---*/ - solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTotal_CD(solver_container[iZone][INST_0][MESH_0][FLOW_SOL]->GetTotal_CD()); - solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTotal_CL(solver_container[iZone][INST_0][MESH_0][FLOW_SOL]->GetTotal_CL()); - solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTotal_CT(solver_container[iZone][INST_0][MESH_0][FLOW_SOL]->GetTotal_CT()); - solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTotal_CQ(solver_container[iZone][INST_0][MESH_0][FLOW_SOL]->GetTotal_CQ()); - - /*--- Restrict solution and gradients to the coarse levels ---*/ - - if (iMGLevel != config[iZone]->GetnMGLevels()) { - SetRestricted_Solution(RUNTIME_FLOW_SYS, solver_container[iZone][INST_0][iMGLevel][FLOW_SOL], solver_container[iZone][INST_0][iMGLevel+1][FLOW_SOL], - geometry[iZone][INST_0][iMGLevel], geometry[iZone][INST_0][iMGLevel+1], config[iZone]); -// ToDo: The flow solvers do not use the conservative variable gradients -// SetRestricted_Gradient(RUNTIME_FLOW_SYS, solver_container[iZone][INST_0][iMGLevel][FLOW_SOL], solver_container[iZone][INST_0][iMGLevel+1][FLOW_SOL], -// geometry[iZone][INST_0][iMGLevel], geometry[iZone][INST_0][iMGLevel+1], config[iZone]); - } - - } - } - -} +void CIntegration::Time_Integration(CGeometry *geometry, CSolver **solver_container, CConfig *config, + unsigned short iRKStep, unsigned short RunTime_EqSystem) { -void CIntegration::Time_Integration(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iRKStep, - unsigned short RunTime_EqSystem) { unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); - unsigned short KindSolver = config->GetKind_Solver(); - - /*--- Perform the time integration ---*/ - - /*--- Fluid time integration schemes ---*/ - if (KindSolver != FEM_ELASTICITY) { - - switch (config->GetKind_TimeIntScheme()) { - case (RUNGE_KUTTA_EXPLICIT): - solver_container[MainSolver]->ExplicitRK_Iteration(geometry, solver_container, config, iRKStep); - break; - case (CLASSICAL_RK4_EXPLICIT): - solver_container[MainSolver]->ClassicalRK4_Iteration(geometry, solver_container, config, iRKStep); - break; - case (EULER_EXPLICIT): - solver_container[MainSolver]->ExplicitEuler_Iteration(geometry, solver_container, config); - break; - case (EULER_IMPLICIT): - solver_container[MainSolver]->ImplicitEuler_Iteration(geometry, solver_container, config); - break; - } - - /*--- Structural time integration schemes ---*/ - - } - else if (KindSolver == FEM_ELASTICITY) { - - switch (config->GetKind_TimeIntScheme_FEA()) { - case (CD_EXPLICIT): + switch (config->GetKind_TimeIntScheme()) { + case (RUNGE_KUTTA_EXPLICIT): solver_container[MainSolver]->ExplicitRK_Iteration(geometry, solver_container, config, iRKStep); break; - case (NEWMARK_IMPLICIT): - solver_container[MainSolver]->ImplicitNewmark_Iteration(geometry, solver_container, config); - break; - case (GENERALIZED_ALPHA): - solver_container[MainSolver]->ImplicitEuler_Iteration(geometry, solver_container, config); - break; - } - } - -} - -void CIntegration::Time_Integration_FEM(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, CConfig *config, - unsigned short RunTime_EqSystem) { - - unsigned short iMarker; - - unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); - - /*--- Set the Jacobian according to the different time integration methods ---*/ - - switch (config->GetKind_TimeIntScheme_FEA()) { - case (CD_EXPLICIT): - solver_container[MainSolver]->ImplicitNewmark_Iteration(geometry, solver_container, config); - break; - case (NEWMARK_IMPLICIT): - solver_container[MainSolver]->ImplicitNewmark_Iteration(geometry, solver_container, config); + case (CLASSICAL_RK4_EXPLICIT): + solver_container[MainSolver]->ClassicalRK4_Iteration(geometry, solver_container, config, iRKStep); break; - case (GENERALIZED_ALPHA): - solver_container[MainSolver]->GeneralizedAlpha_Iteration(geometry, solver_container, config); + case (EULER_EXPLICIT): + solver_container[MainSolver]->ExplicitEuler_Iteration(geometry, solver_container, config); break; - } - - /*--- Apply ESSENTIAL BOUNDARY CONDITIONS ---*/ - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - switch (config->GetMarker_All_KindBC(iMarker)) { - case CLAMPED_BOUNDARY: - solver_container[MainSolver]->BC_Clamped(geometry, numerics[FEA_TERM], config, iMarker); - break; - case DISP_DIR_BOUNDARY: - solver_container[MainSolver]->BC_DispDir(geometry, numerics[FEA_TERM], config, iMarker); - break; - case DISPLACEMENT_BOUNDARY: - solver_container[MainSolver]->BC_Normal_Displacement(geometry, numerics[CONV_BOUND_TERM], config, iMarker); - break; - } - } - - /*--- Solver linearized system ---*/ - - solver_container[MainSolver]->Solve_System(geometry, config); - - /*--- Update solution ---*/ - - switch (config->GetKind_TimeIntScheme_FEA()) { - case (CD_EXPLICIT): - solver_container[MainSolver]->ImplicitNewmark_Update(geometry, solver_container, config); - break; - case (NEWMARK_IMPLICIT): - solver_container[MainSolver]->ImplicitNewmark_Update(geometry, solver_container, config); - break; - case (GENERALIZED_ALPHA): - solver_container[MainSolver]->GeneralizedAlpha_UpdateDisp(geometry, solver_container, config); + case (EULER_IMPLICIT): + solver_container[MainSolver]->ImplicitEuler_Iteration(geometry, solver_container, config); break; } - /*--- Reinforce ESSENTIAL BOUNDARY CONDITIONS: avoids accumulation of numerical error ---*/ - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - switch (config->GetMarker_All_KindBC(iMarker)) { - case CLAMPED_BOUNDARY: - solver_container[MainSolver]->BC_Clamped_Post(geometry, numerics[FEA_TERM], config, iMarker); - break; - } - } - - /*--- Perform the MPI communication of the solution ---*/ - - solver_container[MainSolver]->InitiateComms(geometry, config, SOLUTION_FEA); - solver_container[MainSolver]->CompleteComms(geometry, config, SOLUTION_FEA); - } - void CIntegration::SetDualTime_Solver(CGeometry *geometry, CSolver *solver, CConfig *config, unsigned short iMesh) { + SU2_OMP_PARALLEL + { + unsigned long iPoint; solver->GetNodes()->Set_Solution_time_n1(); solver->GetNodes()->Set_Solution_time_n(); + + SU2_OMP_MASTER solver->ResetCFLAdapt(); + SU2_OMP_BARRIER + SU2_OMP_FOR_STAT(roundUpDiv(geometry->GetnPoint(), omp_get_num_threads())) for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Initialize the underrelaxation ---*/ - + solver->GetNodes()->SetUnderRelaxation(iPoint, 1.0); - + /*--- Initialize the local CFL number ---*/ - + solver->GetNodes()->SetLocalCFL(iPoint, config->GetCFL(iMesh)); - + geometry->node[iPoint]->SetVolume_nM1(); geometry->node[iPoint]->SetVolume_n(); - + /*--- Store old coordinates in case there is grid movement ---*/ - + if (config->GetGrid_Movement()) { geometry->node[iPoint]->SetCoord_n1(); geometry->node[iPoint]->SetCoord_n(); } } - + /*--- Store old aeroelastic solutions ---*/ + SU2_OMP_MASTER if (config->GetGrid_Movement() && config->GetAeroelastic_Simulation() && (iMesh == MESH_0)) { + config->SetAeroelastic_n1(); config->SetAeroelastic_n(); - + /*--- Also communicate plunge and pitch to the master node. Needed for output in case of parallel run ---*/ - + #ifdef HAVE_MPI su2double plunge, pitch, *plunge_all = NULL, *pitch_all = NULL; unsigned short iMarker, iMarker_Monitoring; unsigned long iProcessor, owner, *owner_all = NULL; - + string Marker_Tag, Monitoring_Tag; int nProcessor = size; /*--- Only if master node allocate memory ---*/ - + if (rank == MASTER_NODE) { plunge_all = new su2double[nProcessor]; pitch_all = new su2double[nProcessor]; owner_all = new unsigned long[nProcessor]; } - + /*--- Find marker and give it's plunge and pitch coordinate to the master node ---*/ - + for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - + Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring); Marker_Tag = config->GetMarker_All_TagBound(iMarker); if (Marker_Tag == Monitoring_Tag) { owner = 1; break; } else { owner = 0; } - + } plunge = config->GetAeroelastic_plunge(iMarker_Monitoring); pitch = config->GetAeroelastic_pitch(iMarker_Monitoring); - + /*--- Gather the data on the master node. ---*/ - + SU2_MPI::Gather(&plunge, 1, MPI_DOUBLE, plunge_all, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(&pitch, 1, MPI_DOUBLE, pitch_all, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(&owner, 1, MPI_UNSIGNED_LONG, owner_all, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); - + /*--- Set plunge and pitch on the master node ---*/ - + if (rank == MASTER_NODE) { for (iProcessor = 0; iProcessor < (unsigned long)nProcessor; iProcessor++) { if (owner_all[iProcessor] == 1) { @@ -509,9 +312,9 @@ void CIntegration::SetDualTime_Solver(CGeometry *geometry, CSolver *solver, CCon } } } - + } - + if (rank == MASTER_NODE) { delete [] plunge_all; delete [] pitch_all; @@ -519,35 +322,18 @@ void CIntegration::SetDualTime_Solver(CGeometry *geometry, CSolver *solver, CCon } #endif } - -} + SU2_OMP_BARRIER -void CIntegration::SetStructural_Solver(CGeometry *geometry, CSolver *solver, CConfig *config, unsigned short iMesh) { + } // end SU2_OMP_PARALLEL - solver->GetNodes()->Set_Solution_time_n(); - solver->GetNodes()->SetSolution_Vel_time_n(); - solver->GetNodes()->SetSolution_Accel_time_n(); - - bool fsi = config->GetFSI_Simulation(); - - /*--- If FSI problem, save the last Aitken relaxation parameter of the previous time step ---*/ - - if (fsi) { - - su2double WAitk=0.0; - - WAitk = solver->GetWAitken_Dyn(); - solver->SetWAitken_Dyn_tn1(WAitk); - - } } -void CIntegration::SetFEM_StructuralSolver(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh) { +void CIntegration::SetStructural_Solver(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh) { bool fsi = config->GetFSI_Simulation(); - + /*--- Update the solution according to the integration scheme used ---*/ - + switch (config->GetKind_TimeIntScheme_FEA()) { case (CD_EXPLICIT): break; diff --git a/SU2_CFD/src/integration/CMultiGridIntegration.cpp b/SU2_CFD/src/integration/CMultiGridIntegration.cpp new file mode 100644 index 000000000000..978d50240930 --- /dev/null +++ b/SU2_CFD/src/integration/CMultiGridIntegration.cpp @@ -0,0 +1,763 @@ +/*! + * \file CMultiGridIntegration.cpp + * \brief Implementation of the multigrid integration class. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../include/integration/CMultiGridIntegration.hpp" +#include "../../../Common/include/omp_structure.hpp" + + +CMultiGridIntegration::CMultiGridIntegration(CConfig *config) : CIntegration(config) { } + +void CMultiGridIntegration::MultiGrid_Iteration(CGeometry ****geometry, + CSolver *****solver_container, + CNumerics ******numerics_container, + CConfig **config, + unsigned short RunTime_EqSystem, + unsigned short iZone, + unsigned short iInst) { + + bool direct; + switch (config[iZone]->GetKind_Solver()) { + case EULER: + case NAVIER_STOKES: + case RANS: + case FEM_EULER: + case FEM_NAVIER_STOKES: + case FEM_RANS: + case FEM_LES: + case DISC_ADJ_EULER: + case DISC_ADJ_NAVIER_STOKES: + case DISC_ADJ_FEM_EULER: + case DISC_ADJ_FEM_NS: + case DISC_ADJ_RANS: + direct = true; + break; + default: + direct = false; + break; + } + + const unsigned short Solver_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); + + /*--- Start an OpenMP parallel region covering the entire MG iteration, if the solver supports it. ---*/ + + SU2_OMP_PARALLEL_(if(solver_container[iZone][iInst][MESH_0][Solver_Position]->GetHasHybridParallel())) + { + + su2double monitor = 1.0; + bool FullMG = false; + + unsigned short RecursiveParam = config[iZone]->GetMGCycle(); + + if (config[iZone]->GetMGCycle() == FULLMG_CYCLE) { + RecursiveParam = V_CYCLE; + FullMG = true; + } + + /*--- Full multigrid strategy and start up with fine grid only works with the direct problem ---*/ + + unsigned short FinestMesh = config[iZone]->GetFinestMesh(); + + if (!config[iZone]->GetRestart() && FullMG && direct && ( Convergence_FullMG && (FinestMesh != MESH_0 ))) { + + SetProlongated_Solution(RunTime_EqSystem, + solver_container[iZone][iInst][FinestMesh-1][Solver_Position], + solver_container[iZone][iInst][FinestMesh][Solver_Position], + geometry[iZone][iInst][FinestMesh-1], + geometry[iZone][iInst][FinestMesh], + config[iZone]); + + SU2_OMP_MASTER + config[iZone]->SubtractFinestMesh(); + SU2_OMP_BARRIER + } + + /*--- Set the current finest grid (full multigrid strategy) ---*/ + + FinestMesh = config[iZone]->GetFinestMesh(); + + /*--- Perform the Full Approximation Scheme multigrid ---*/ + + MultiGrid_Cycle(geometry, solver_container, numerics_container, config, + FinestMesh, RecursiveParam, RunTime_EqSystem, iZone, iInst); + + /*--- Computes primitive variables and gradients in the finest mesh (useful for the next solver (turbulence) and output ---*/ + + solver_container[iZone][iInst][MESH_0][Solver_Position]->Preprocessing(geometry[iZone][iInst][MESH_0], + solver_container[iZone][iInst][MESH_0], + config[iZone], MESH_0, NO_RK_ITER, + RunTime_EqSystem, true); + + /*--- Compute non-dimensional parameters and the convergence monitor ---*/ + + NonDimensional_Parameters(geometry[iZone][iInst], solver_container[iZone][iInst], + numerics_container[iZone][iInst], config[iZone], + FinestMesh, RunTime_EqSystem, &monitor); + + } // end SU2_OMP_PARALLEL + +} + +void CMultiGridIntegration::MultiGrid_Cycle(CGeometry ****geometry, + CSolver *****solver_container, + CNumerics ******numerics_container, + CConfig **config_container, + unsigned short iMesh, + unsigned short RecursiveParam, + unsigned short RunTime_EqSystem, + unsigned short iZone, + unsigned short iInst) { + + CConfig* config = config_container[iZone]; + + const unsigned short Solver_Position = config->GetContainerPosition(RunTime_EqSystem); + const bool classical_rk4 = (config->GetKind_TimeIntScheme() == CLASSICAL_RK4_EXPLICIT); + + /*--- Shorter names to refer to fine grid entities. ---*/ + + CGeometry* geometry_fine = geometry[iZone][iInst][iMesh]; + CSolver** solver_container_fine = solver_container[iZone][iInst][iMesh]; + CSolver* solver_fine = solver_container_fine[Solver_Position]; + CNumerics** numerics_fine = numerics_container[iZone][iInst][iMesh][Solver_Position]; + + /*--- Number of RK steps. ---*/ + + unsigned short iRKLimit = 1; + + switch (config->GetKind_TimeIntScheme()) { + case RUNGE_KUTTA_EXPLICIT: + iRKLimit = config->GetnRKStep(); + break; + case CLASSICAL_RK4_EXPLICIT: + iRKLimit = 4; + break; + case EULER_EXPLICIT: + case EULER_IMPLICIT: + iRKLimit = 1; + break; + } + + /*--- Do a presmoothing on the grid iMesh to be restricted to the grid iMesh+1 ---*/ + + for (unsigned short iPreSmooth = 0; iPreSmooth < config->GetMG_PreSmooth(iMesh); iPreSmooth++) { + + /*--- Time and space integration ---*/ + + for (unsigned short iRKStep = 0; iRKStep < iRKLimit; iRKStep++) { + + /*--- Send-Receive boundary conditions, and preprocessing ---*/ + + solver_fine->Preprocessing(geometry_fine, solver_container_fine, config, iMesh, iRKStep, RunTime_EqSystem, false); + + if (iRKStep == 0) { + + /*--- Set the old solution ---*/ + + solver_fine->Set_OldSolution(geometry_fine); + + if (classical_rk4) + solver_fine->Set_NewSolution(geometry_fine); + + /*--- Compute time step, max eigenvalue, and integration scheme (steady and unsteady problems) ---*/ + + solver_fine->SetTime_Step(geometry_fine, solver_container_fine, config, iMesh, config->GetTimeIter()); + + /*--- Restrict the solution and gradient for the adjoint problem ---*/ + + Adjoint_Setup(geometry, solver_container, config_container, RunTime_EqSystem, config->GetTimeIter(), iZone); + + } + + /*--- Space integration ---*/ + + Space_Integration(geometry_fine, solver_container_fine, numerics_fine, config, iMesh, iRKStep, RunTime_EqSystem); + + /*--- Time integration, update solution using the old solution plus the solution increment ---*/ + + Time_Integration(geometry_fine, solver_container_fine, config, iRKStep, RunTime_EqSystem); + + /*--- Send-Receive boundary conditions, and postprocessing ---*/ + + solver_fine->Postprocessing(geometry_fine, solver_container_fine, config, iMesh); + + } + + } + + /*--- Compute Forcing Term $P_(k+1) = I^(k+1)_k(P_k+F_k(u_k))-F_(k+1)(I^(k+1)_k u_k)$ and update solution for multigrid ---*/ + + if ( iMesh < config->GetnMGLevels() ) { + + /*--- Shorter names to refer to coarse grid entities. ---*/ + + CGeometry* geometry_coarse = geometry[iZone][iInst][iMesh+1]; + CSolver** solver_container_coarse = solver_container[iZone][iInst][iMesh+1]; + CSolver* solver_coarse = solver_container_coarse[Solver_Position]; + CNumerics** numerics_coarse = numerics_container[iZone][iInst][iMesh+1][Solver_Position]; + + /*--- Compute $r_k = P_k + F_k(u_k)$ ---*/ + + solver_fine->Preprocessing(geometry_fine, solver_container_fine, config, iMesh, NO_RK_ITER, RunTime_EqSystem, false); + + /// TODO: For implicit schemes, this call to Space_Integration can skip building the system matrix. + Space_Integration(geometry_fine, solver_container_fine, numerics_fine, config, iMesh, NO_RK_ITER, RunTime_EqSystem); + + SetResidual_Term(geometry_fine, solver_fine); + + /*--- Compute $r_(k+1) = F_(k+1)(I^(k+1)_k u_k)$ ---*/ + + SetRestricted_Solution(RunTime_EqSystem, solver_fine, solver_coarse, geometry_fine, geometry_coarse, config); + + solver_coarse->Preprocessing(geometry_coarse, solver_container_coarse, config, iMesh+1, NO_RK_ITER, RunTime_EqSystem, false); + + Space_Integration(geometry_coarse, solver_container_coarse, numerics_coarse, config, iMesh+1, NO_RK_ITER, RunTime_EqSystem); + + /*--- Compute $P_(k+1) = I^(k+1)_k(r_k) - r_(k+1) ---*/ + + SetForcing_Term(solver_fine, solver_coarse, geometry_fine, geometry_coarse, config, iMesh+1); + + /*--- Recursive call to MultiGrid_Cycle (this routine). ---*/ + + for (unsigned short imu = 0; imu <= RecursiveParam; imu++) { + + unsigned short nextRecurseParam = RecursiveParam; + if (iMesh == config->GetnMGLevels()-2) + nextRecurseParam = 0; + + MultiGrid_Cycle(geometry, solver_container, numerics_container, config_container, + iMesh+1, nextRecurseParam, RunTime_EqSystem, iZone, iInst); + } + + /*--- Compute prolongated solution, and smooth the correction $u^(new)_k = u_k + Smooth(I^k_(k+1)(u_(k+1)-I^(k+1)_k u_k))$ ---*/ + + GetProlongated_Correction(RunTime_EqSystem, solver_fine, solver_coarse, geometry_fine, geometry_coarse, config); + + SmoothProlongated_Correction(RunTime_EqSystem, solver_fine, geometry_fine, config->GetMG_CorrecSmooth(iMesh), 1.25, config); + + SetProlongated_Correction(solver_fine, geometry_fine, config, iMesh); + + + /*--- Solution post-smoothing in the prolongated grid. ---*/ + + for (unsigned short iPostSmooth = 0; iPostSmooth < config->GetMG_PostSmooth(iMesh); iPostSmooth++) { + + for (unsigned short iRKStep = 0; iRKStep < iRKLimit; iRKStep++) { + + solver_fine->Preprocessing(geometry_fine, solver_container_fine, config, iMesh, iRKStep, RunTime_EqSystem, false); + + if (iRKStep == 0) { + solver_fine->Set_OldSolution(geometry_fine); + + if (classical_rk4) solver_fine->Set_NewSolution(geometry_fine); + + solver_fine->SetTime_Step(geometry_fine, solver_container_fine, config, iMesh, config->GetTimeIter()); + } + + Space_Integration(geometry_fine, solver_container_fine, numerics_fine, config, iMesh, iRKStep, RunTime_EqSystem); + + Time_Integration(geometry_fine, solver_container_fine, config, iRKStep, RunTime_EqSystem); + + solver_fine->Postprocessing(geometry_fine, solver_container_fine, config, iMesh); + + } + } + } + +} + +void CMultiGridIntegration::GetProlongated_Correction(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { + unsigned long Point_Fine, Point_Coarse, iVertex; + unsigned short Boundary, iMarker, iChildren, iVar; + su2double Area_Parent, Area_Children; + const su2double *Solution_Fine = nullptr, *Solution_Coarse = nullptr; + + const unsigned short nVar = sol_coarse->GetnVar(); + + su2double *Solution = new su2double[nVar]; + + SU2_OMP_FOR_STAT(roundUpDiv(geo_coarse->GetnPointDomain(), omp_get_num_threads())) + for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { + + Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); + + for (iVar = 0; iVar < nVar; iVar++) Solution[iVar] = 0.0; + + for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { + Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); + Area_Children = geo_fine->node[Point_Fine]->GetVolume(); + Solution_Fine = sol_fine->GetNodes()->GetSolution(Point_Fine); + for (iVar = 0; iVar < nVar; iVar++) + Solution[iVar] -= Solution_Fine[iVar]*Area_Children/Area_Parent; + } + + Solution_Coarse = sol_coarse->GetNodes()->GetSolution(Point_Coarse); + + for (iVar = 0; iVar < nVar; iVar++) + Solution[iVar] += Solution_Coarse[iVar]; + + for (iVar = 0; iVar < nVar; iVar++) + sol_coarse->GetNodes()->SetSolution_Old(Point_Coarse,Solution); + } + + delete [] Solution; + + /*--- Remove any contributions from no-slip walls. ---*/ + + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + Boundary = config->GetMarker_All_KindBC(iMarker); + if ((Boundary == HEAT_FLUX) || + (Boundary == ISOTHERMAL) || + (Boundary == CHT_WALL_INTERFACE)) { + + SU2_OMP_FOR_STAT(32) + for (iVertex = 0; iVertex < geo_coarse->nVertex[iMarker]; iVertex++) { + + Point_Coarse = geo_coarse->vertex[iMarker][iVertex]->GetNode(); + + /*--- For dirichlet boundary condtions, set the correction to zero. + Note that Solution_Old stores the correction not the actual value ---*/ + + sol_coarse->GetNodes()->SetVelSolutionOldZero(Point_Coarse); + + } + } + } + + /*--- MPI the set solution old ---*/ + + SU2_OMP_MASTER + { + sol_coarse->InitiateComms(geo_coarse, config, SOLUTION_OLD); + sol_coarse->CompleteComms(geo_coarse, config, SOLUTION_OLD); + } + SU2_OMP_BARRIER + + /// TODO: Need to check for possible race condition here (multiple coarse points setting the same fine). + + SU2_OMP_FOR_STAT(roundUpDiv(geo_coarse->GetnPointDomain(), omp_get_num_threads())) + for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { + for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { + Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); + sol_fine->LinSysRes.SetBlock(Point_Fine, sol_coarse->GetNodes()->GetSolution_Old(Point_Coarse)); + } + } + +} + +void CMultiGridIntegration::SmoothProlongated_Correction(unsigned short RunTime_EqSystem, CSolver *solver, CGeometry *geometry, + unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config) { + + /*--- Check if there is work to do. ---*/ + if (val_nSmooth == 0) return; + + const su2double *Residual_Old, *Residual_Sum, *Residual_j; + unsigned short iVar, iSmooth, iMarker, iNeigh; + unsigned long iPoint, jPoint, iVertex; + + const unsigned short nVar = solver->GetnVar(); + + SU2_OMP_FOR_STAT(roundUpDiv(geometry->GetnPoint(), omp_get_num_threads())) + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { + Residual_Old = solver->LinSysRes.GetBlock(iPoint); + solver->GetNodes()->SetResidual_Old(iPoint,Residual_Old); + } + + /*--- Jacobi iterations. ---*/ + + for (iSmooth = 0; iSmooth < val_nSmooth; iSmooth++) { + + /*--- Loop over all mesh points (sum the residuals of direct neighbors). ---*/ + + SU2_OMP_FOR_STAT(roundUpDiv(geometry->GetnPoint(), omp_get_num_threads())) + for (iPoint = 0; iPoint < geometry->GetnPoint(); ++iPoint) { + + solver->GetNodes()->SetResidualSumZero(iPoint); + + for (iNeigh = 0; iNeigh < geometry->node[iPoint]->GetnPoint(); ++iNeigh) { + jPoint = geometry->node[iPoint]->GetPoint(iNeigh); + Residual_j = solver->LinSysRes.GetBlock(jPoint); + solver->GetNodes()->AddResidual_Sum(iPoint, Residual_j); + } + + } + + /*--- Loop over all mesh points (update residuals with the neighbor averages). ---*/ + + SU2_OMP_FOR_STAT(roundUpDiv(geometry->GetnPoint(), omp_get_num_threads())) + for (iPoint = 0; iPoint < geometry->GetnPoint(); ++iPoint) { + + su2double factor = 1.0/(1.0+val_smooth_coeff*su2double(geometry->node[iPoint]->GetnPoint())); + + Residual_Sum = solver->GetNodes()->GetResidual_Sum(iPoint); + Residual_Old = solver->GetNodes()->GetResidual_Old(iPoint); + + for (iVar = 0; iVar < nVar; iVar++) + solver->LinSysRes(iPoint,iVar) = (Residual_Old[iVar] + val_smooth_coeff*Residual_Sum[iVar])*factor; + } + + /*--- Restore original residuals (without average) at boundary points. ---*/ + + for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) { + if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && + (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) { + + SU2_OMP_FOR_STAT(32) + for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + Residual_Old = solver->GetNodes()->GetResidual_Old(iPoint); + solver->LinSysRes.SetBlock(iPoint, Residual_Old); + } + } + } + + } + +} + +void CMultiGridIntegration::SetProlongated_Correction(CSolver *sol_fine, CGeometry *geo_fine, + CConfig *config, unsigned short iMesh) { + unsigned long Point_Fine; + unsigned short iVar; + su2double *Solution_Fine, *Residual_Fine; + + const unsigned short nVar = sol_fine->GetnVar(); + const su2double factor = config->GetDamp_Correc_Prolong(); //pow(config->GetDamp_Correc_Prolong(), iMesh+1); + + SU2_OMP_FOR_STAT(roundUpDiv(geo_fine->GetnPointDomain(), omp_get_num_threads())) + for (Point_Fine = 0; Point_Fine < geo_fine->GetnPointDomain(); Point_Fine++) { + Residual_Fine = sol_fine->LinSysRes.GetBlock(Point_Fine); + Solution_Fine = sol_fine->GetNodes()->GetSolution(Point_Fine); + for (iVar = 0; iVar < nVar; iVar++) { + /*--- Prevent a fine grid divergence due to a coarse grid divergence ---*/ + if (Residual_Fine[iVar] != Residual_Fine[iVar]) + Residual_Fine[iVar] = 0.0; + Solution_Fine[iVar] += factor*Residual_Fine[iVar]; + } + } + + /*--- MPI the new interpolated solution ---*/ + + SU2_OMP_MASTER + { + sol_fine->InitiateComms(geo_fine, config, SOLUTION); + sol_fine->CompleteComms(geo_fine, config, SOLUTION); + } + SU2_OMP_BARRIER + +} + +void CMultiGridIntegration::SetProlongated_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { + unsigned long Point_Fine, Point_Coarse; + unsigned short iChildren; + + /// TODO: Need to check for possible race condition here (multiple coarse points setting the same fine). + + SU2_OMP_FOR_STAT(roundUpDiv(geo_coarse->GetnPointDomain(), omp_get_num_threads())) + for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { + for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { + Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); + sol_fine->GetNodes()->SetSolution(Point_Fine, sol_coarse->GetNodes()->GetSolution(Point_Coarse)); + } + } +} + +void CMultiGridIntegration::SetForcing_Term(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, + CGeometry *geo_coarse, CConfig *config, unsigned short iMesh) { + + unsigned long Point_Fine, Point_Coarse, iVertex; + unsigned short iMarker, iVar, iChildren; + const su2double *Residual_Fine; + + const unsigned short nVar = sol_coarse->GetnVar(); + su2double factor = config->GetDamp_Res_Restric(); //pow(config->GetDamp_Res_Restric(), iMesh); + + su2double *Residual = new su2double[nVar]; + + SU2_OMP_FOR_STAT(roundUpDiv(geo_coarse->GetnPointDomain(), omp_get_num_threads())) + for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { + + sol_coarse->GetNodes()->SetRes_TruncErrorZero(Point_Coarse); + + for (iVar = 0; iVar < nVar; iVar++) Residual[iVar] = 0.0; + + for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { + Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); + Residual_Fine = sol_fine->LinSysRes.GetBlock(Point_Fine); + for (iVar = 0; iVar < nVar; iVar++) + Residual[iVar] += factor*Residual_Fine[iVar]; + } + sol_coarse->GetNodes()->AddRes_TruncError(Point_Coarse, Residual); + } + + delete [] Residual; + + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + if ((config->GetMarker_All_KindBC(iMarker) == HEAT_FLUX) || + (config->GetMarker_All_KindBC(iMarker) == ISOTHERMAL) || + (config->GetMarker_All_KindBC(iMarker) == CHT_WALL_INTERFACE)) { + + SU2_OMP_FOR_STAT(32) + for (iVertex = 0; iVertex < geo_coarse->nVertex[iMarker]; iVertex++) { + Point_Coarse = geo_coarse->vertex[iMarker][iVertex]->GetNode(); + sol_coarse->GetNodes()->SetVel_ResTruncError_Zero(Point_Coarse); + } + } + } + + SU2_OMP_FOR_STAT(roundUpDiv(geo_coarse->GetnPointDomain(), omp_get_num_threads())) + for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { + sol_coarse->GetNodes()->SubtractRes_TruncError(Point_Coarse, sol_coarse->LinSysRes.GetBlock(Point_Coarse)); + } + +} + +void CMultiGridIntegration::SetResidual_Term(CGeometry *geometry, CSolver *solver) { + + SU2_OMP_FOR_STAT(roundUpDiv(geometry->GetnPointDomain(), omp_get_num_threads())) + for (unsigned long iPoint = 0; iPoint < geometry->GetnPointDomain(); iPoint++) + solver->LinSysRes.AddBlock(iPoint, solver->GetNodes()->GetResTruncError(iPoint)); + +} + +void CMultiGridIntegration::SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { + + unsigned long iVertex, Point_Fine, Point_Coarse; + unsigned short iMarker, iVar, iChildren, iDim; + su2double Area_Parent, Area_Children, Vector[3] = {0.0}; + const su2double *Solution_Fine = nullptr, *Grid_Vel = nullptr; + + const unsigned short Solver_Position = config->GetContainerPosition(RunTime_EqSystem); + const unsigned short nVar = sol_coarse->GetnVar(); + const unsigned short nDim = geo_fine->GetnDim(); + const bool grid_movement = config->GetGrid_Movement(); + + su2double *Solution = new su2double[nVar]; + + /*--- Compute coarse solution from fine solution ---*/ + + SU2_OMP_FOR_STAT(roundUpDiv(geo_coarse->GetnPointDomain(), omp_get_num_threads())) + for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { + + Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); + + for (iVar = 0; iVar < nVar; iVar++) Solution[iVar] = 0.0; + + for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { + + Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); + Area_Children = geo_fine->node[Point_Fine]->GetVolume(); + Solution_Fine = sol_fine->GetNodes()->GetSolution(Point_Fine); + for (iVar = 0; iVar < nVar; iVar++) { + Solution[iVar] += Solution_Fine[iVar]*Area_Children/Area_Parent; + } + } + + sol_coarse->GetNodes()->SetSolution(Point_Coarse, Solution); + + } + + delete [] Solution; + + /*--- Update the solution at the no-slip walls ---*/ + + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + if ((config->GetMarker_All_KindBC(iMarker) == HEAT_FLUX) || + (config->GetMarker_All_KindBC(iMarker) == ISOTHERMAL) || + (config->GetMarker_All_KindBC(iMarker) == CHT_WALL_INTERFACE)) { + + SU2_OMP_FOR_STAT(32) + for (iVertex = 0; iVertex < geo_coarse->nVertex[iMarker]; iVertex++) { + + Point_Coarse = geo_coarse->vertex[iMarker][iVertex]->GetNode(); + + if (Solver_Position == FLOW_SOL) { + + /*--- At moving walls, set the solution based on the new density and wall velocity ---*/ + + if (grid_movement) { + Grid_Vel = geo_coarse->node[Point_Coarse]->GetGridVel(); + for (iDim = 0; iDim < nDim; iDim++) + Vector[iDim] = sol_coarse->GetNodes()->GetSolution(Point_Coarse,0)*Grid_Vel[iDim]; + sol_coarse->GetNodes()->SetVelSolutionVector(Point_Coarse, Vector); + } + else { + /*--- For stationary no-slip walls, set the velocity to zero. ---*/ + + sol_coarse->GetNodes()->SetVelSolutionZero(Point_Coarse); + } + + } + + if (Solver_Position == ADJFLOW_SOL) { + sol_coarse->GetNodes()->SetVelSolutionDVector(Point_Coarse); + } + + } + } + } + + /*--- MPI the new interpolated solution ---*/ + + SU2_OMP_MASTER + { + sol_coarse->InitiateComms(geo_coarse, config, SOLUTION); + sol_coarse->CompleteComms(geo_coarse, config, SOLUTION); + } + SU2_OMP_BARRIER + +} + +void CMultiGridIntegration::SetRestricted_Gradient(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { + unsigned long Point_Fine, Point_Coarse; + unsigned short iVar, iDim, iChildren; + su2double Area_Parent, Area_Children; + const su2double* const* Gradient_fine = nullptr; + + const unsigned short nDim = geo_coarse->GetnDim(); + const unsigned short nVar = sol_coarse->GetnVar(); + + su2double **Gradient = new su2double* [nVar]; + for (iVar = 0; iVar < nVar; iVar++) + Gradient[iVar] = new su2double [nDim]; + + SU2_OMP_FOR_STAT(roundUpDiv(geo_coarse->GetnPoint(), omp_get_num_threads())) + for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPoint(); Point_Coarse++) { + Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); + + for (iVar = 0; iVar < nVar; iVar++) + for (iDim = 0; iDim < nDim; iDim++) + Gradient[iVar][iDim] = 0.0; + + for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { + Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); + Area_Children = geo_fine->node[Point_Fine]->GetVolume(); + Gradient_fine = sol_fine->GetNodes()->GetGradient(Point_Fine); + + for (iVar = 0; iVar < nVar; iVar++) + for (iDim = 0; iDim < nDim; iDim++) + Gradient[iVar][iDim] += Gradient_fine[iVar][iDim]*Area_Children/Area_Parent; + } + sol_coarse->GetNodes()->SetGradient(Point_Coarse,Gradient); + } + + for (iVar = 0; iVar < nVar; iVar++) + delete [] Gradient[iVar]; + delete [] Gradient; + +} + +void CMultiGridIntegration::NonDimensional_Parameters(CGeometry **geometry, CSolver ***solver_container, + CNumerics ****numerics_container, CConfig *config, + unsigned short FinestMesh, unsigned short RunTime_EqSystem, + su2double *monitor) { + SU2_OMP_MASTER + switch (RunTime_EqSystem) { + + case RUNTIME_FLOW_SYS: + + /*--- Calculate the inviscid and viscous forces ---*/ + + solver_container[FinestMesh][FLOW_SOL]->Pressure_Forces(geometry[FinestMesh], config); + solver_container[FinestMesh][FLOW_SOL]->Momentum_Forces(geometry[FinestMesh], config); + solver_container[FinestMesh][FLOW_SOL]->Friction_Forces(geometry[FinestMesh], config); + + /*--- Evaluate the buffet metric if requested ---*/ + + if(config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR){ + solver_container[FinestMesh][FLOW_SOL]->Buffet_Monitoring(geometry[FinestMesh], config); + } + + break; + + case RUNTIME_ADJFLOW_SYS: + + /*--- Calculate the inviscid and viscous sensitivities ---*/ + + solver_container[FinestMesh][ADJFLOW_SOL]->Inviscid_Sensitivity(geometry[FinestMesh], solver_container[FinestMesh], + numerics_container[FinestMesh][ADJFLOW_SOL][CONV_BOUND_TERM], config); + + solver_container[FinestMesh][ADJFLOW_SOL]->Viscous_Sensitivity(geometry[FinestMesh], solver_container[FinestMesh], + numerics_container[FinestMesh][ADJFLOW_SOL][CONV_BOUND_TERM], config); + + /*--- Smooth the inviscid and viscous sensitivities ---*/ + + if (config->GetKind_SensSmooth() != NONE) + solver_container[FinestMesh][ADJFLOW_SOL]->Smooth_Sensitivity(geometry[FinestMesh], solver_container[FinestMesh], + numerics_container[FinestMesh][ADJFLOW_SOL][CONV_BOUND_TERM], config); + break; + } + SU2_OMP_BARRIER + +} + +void CMultiGridIntegration::Adjoint_Setup(CGeometry ****geometry, CSolver *****solver_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned long Iteration, unsigned short iZone) { + + if ((RunTime_EqSystem != RUNTIME_ADJFLOW_SYS) || (Iteration != 0)) return; + + for (unsigned short iMGLevel = 0; iMGLevel <= config[iZone]->GetnMGLevels(); iMGLevel++) { + + /*--- Set the time step in all the MG levels ---*/ + + solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTime_Step(geometry[iZone][INST_0][iMGLevel], + solver_container[iZone][INST_0][iMGLevel], + config[iZone], iMGLevel, Iteration); + + /*--- Set the force coefficients ---*/ + + SU2_OMP_MASTER + { + solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTotal_CD(solver_container[iZone][INST_0][MESH_0][FLOW_SOL]->GetTotal_CD()); + solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTotal_CL(solver_container[iZone][INST_0][MESH_0][FLOW_SOL]->GetTotal_CL()); + solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTotal_CT(solver_container[iZone][INST_0][MESH_0][FLOW_SOL]->GetTotal_CT()); + solver_container[iZone][INST_0][iMGLevel][FLOW_SOL]->SetTotal_CQ(solver_container[iZone][INST_0][MESH_0][FLOW_SOL]->GetTotal_CQ()); + } + SU2_OMP_BARRIER + + /*--- Restrict solution and gradients to the coarse levels ---*/ + + if (iMGLevel != config[iZone]->GetnMGLevels()) { + SetRestricted_Solution(RUNTIME_FLOW_SYS, + solver_container[iZone][INST_0][iMGLevel][FLOW_SOL], + solver_container[iZone][INST_0][iMGLevel+1][FLOW_SOL], + geometry[iZone][INST_0][iMGLevel], + geometry[iZone][INST_0][iMGLevel+1], + config[iZone]); +// ToDo: The flow solvers do not use the conservative variable gradients +// SetRestricted_Gradient(RUNTIME_FLOW_SYS, solver_container[iZone][INST_0][iMGLevel][FLOW_SOL], +// solver_container[iZone][INST_0][iMGLevel+1][FLOW_SOL], +// geometry[iZone][INST_0][iMGLevel], +// geometry[iZone][INST_0][iMGLevel+1], +// config[iZone]); + } + + } + +} diff --git a/SU2_CFD/src/integration/CSingleGridIntegration.cpp b/SU2_CFD/src/integration/CSingleGridIntegration.cpp new file mode 100644 index 000000000000..85745ebf2881 --- /dev/null +++ b/SU2_CFD/src/integration/CSingleGridIntegration.cpp @@ -0,0 +1,211 @@ +/*! + * \file CSingleGridIntegration.cpp + * \brief Single (fine) grid integration class implementation. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../include/integration/CSingleGridIntegration.hpp" +#include "../../../Common/include/omp_structure.hpp" + + +CSingleGridIntegration::CSingleGridIntegration(CConfig *config) : CIntegration(config) { } + +void CSingleGridIntegration::SingleGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned short iZone, + unsigned short iInst) { + + const unsigned short Solver_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); + + /*--- Start an OpenMP parallel region covering the entire iteration. ---*/ + + SU2_OMP_PARALLEL_(if(solver_container[iZone][iInst][MESH_0][Solver_Position]->GetHasHybridParallel())) + { + + unsigned short FinestMesh = config[iZone]->GetFinestMesh(); + + CGeometry* geometry_fine = geometry[iZone][iInst][FinestMesh]; + CSolver** solvers_fine = solver_container[iZone][iInst][FinestMesh]; + + /*--- Preprocessing ---*/ + + solvers_fine[Solver_Position]->Preprocessing(geometry_fine, solvers_fine, config[iZone], + FinestMesh, 0, RunTime_EqSystem, false); + + /*--- Set the old solution ---*/ + + solvers_fine[Solver_Position]->Set_OldSolution(geometry_fine); + + /*--- Time step evaluation ---*/ + + solvers_fine[Solver_Position]->SetTime_Step(geometry_fine, solvers_fine, config[iZone], + FinestMesh, config[iZone]->GetTimeIter()); + + /*--- Space integration ---*/ + + Space_Integration(geometry_fine, solvers_fine, + numerics_container[iZone][iInst][FinestMesh][Solver_Position], + config[iZone], FinestMesh, NO_RK_ITER, RunTime_EqSystem); + + /*--- Time integration ---*/ + + Time_Integration(geometry_fine, solvers_fine, config[iZone], NO_RK_ITER, RunTime_EqSystem); + + /*--- Postprocessing ---*/ + + solvers_fine[Solver_Position]->Postprocessing(geometry_fine, solvers_fine, config[iZone], FinestMesh); + + if (RunTime_EqSystem == RUNTIME_HEAT_SYS) { + SU2_OMP_MASTER + solvers_fine[HEAT_SOL]->Heat_Fluxes(geometry_fine, solvers_fine, config[iZone]); + SU2_OMP_BARRIER + } + + /*--- If turbulence model, copy the turbulence variables to the coarse levels ---*/ + + if (RunTime_EqSystem == RUNTIME_TURB_SYS) { + + for (unsigned short iMesh = FinestMesh; iMesh < config[iZone]->GetnMGLevels(); iMesh++) { + + SetRestricted_Solution(RunTime_EqSystem, + solver_container[iZone][iInst][iMesh][Solver_Position], + solver_container[iZone][iInst][iMesh+1][Solver_Position], + geometry[iZone][iInst][iMesh], + geometry[iZone][iInst][iMesh+1], + config[iZone]); + + SetRestricted_EddyVisc(RunTime_EqSystem, + solver_container[iZone][iInst][iMesh][Solver_Position], + solver_container[iZone][iInst][iMesh+1][Solver_Position], + geometry[iZone][iInst][iMesh], + geometry[iZone][iInst][iMesh+1], + config[iZone]); + } + + } + + } // end SU2_OMP_PARALLEL + +} + +void CSingleGridIntegration::SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { + unsigned long Point_Fine, Point_Coarse; + unsigned short iVar, iChildren; + su2double Area_Parent, Area_Children; + const su2double *Solution_Fine; + + unsigned short nVar = sol_coarse->GetnVar(); + + su2double *Solution = new su2double[nVar]; + + /*--- Compute coarse solution from fine solution ---*/ + + SU2_OMP_FOR_STAT(roundUpDiv(geo_coarse->GetnPointDomain(), omp_get_num_threads())) + for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { + + Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); + + for (iVar = 0; iVar < nVar; iVar++) Solution[iVar] = 0.0; + + for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { + + Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); + Area_Children = geo_fine->node[Point_Fine]->GetVolume(); + Solution_Fine = sol_fine->GetNodes()->GetSolution(Point_Fine); + for (iVar = 0; iVar < nVar; iVar++) + Solution[iVar] += Solution_Fine[iVar]*Area_Children/Area_Parent; + } + + sol_coarse->GetNodes()->SetSolution(Point_Coarse,Solution); + + } + + delete [] Solution; + + /*--- MPI the new interpolated solution ---*/ + + SU2_OMP_MASTER + { + sol_coarse->InitiateComms(geo_coarse, config, SOLUTION); + sol_coarse->CompleteComms(geo_coarse, config, SOLUTION); + } + SU2_OMP_BARRIER + +} + +void CSingleGridIntegration::SetRestricted_EddyVisc(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, + CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { + + unsigned long iVertex, Point_Fine, Point_Coarse; + unsigned short iMarker, iChildren; + su2double Area_Parent, Area_Children, EddyVisc_Fine, EddyVisc; + + /*--- Compute coarse Eddy Viscosity from fine solution ---*/ + + SU2_OMP_FOR_STAT(roundUpDiv(geo_coarse->GetnPointDomain(), omp_get_num_threads())) + for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { + + Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); + + EddyVisc = 0.0; + + for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { + Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); + Area_Children = geo_fine->node[Point_Fine]->GetVolume(); + EddyVisc_Fine = sol_fine->GetNodes()->GetmuT(Point_Fine); + EddyVisc += EddyVisc_Fine*Area_Children/Area_Parent; + } + + sol_coarse->GetNodes()->SetmuT(Point_Coarse,EddyVisc); + + } + + /*--- Update solution at the no slip wall boundary, only the first + variable (nu_tilde -in SA and SA_NEG- and k -in SST-), to guarantee that the eddy viscoisty + is zero on the surface ---*/ + + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + if ((config->GetMarker_All_KindBC(iMarker) == HEAT_FLUX) || + (config->GetMarker_All_KindBC(iMarker) == ISOTHERMAL) || + (config->GetMarker_All_KindBC(iMarker) == CHT_WALL_INTERFACE)) { + + SU2_OMP_FOR_STAT(32) + for (iVertex = 0; iVertex < geo_coarse->nVertex[iMarker]; iVertex++) { + Point_Coarse = geo_coarse->vertex[iMarker][iVertex]->GetNode(); + sol_coarse->GetNodes()->SetmuT(Point_Coarse,0.0); + } + } + } + + /*--- MPI the new interpolated solution (this also includes the eddy viscosity) ---*/ + + SU2_OMP_MASTER + { + sol_coarse->InitiateComms(geo_coarse, config, SOLUTION_EDDY); + sol_coarse->CompleteComms(geo_coarse, config, SOLUTION_EDDY); + } + SU2_OMP_BARRIER + +} diff --git a/SU2_CFD/src/integration/CStructuralIntegration.cpp b/SU2_CFD/src/integration/CStructuralIntegration.cpp new file mode 100644 index 000000000000..1c3a7eb8af04 --- /dev/null +++ b/SU2_CFD/src/integration/CStructuralIntegration.cpp @@ -0,0 +1,212 @@ +/*! + * \file CStructuralIntegration.cpp + * \brief Space and time integration for structural problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../include/integration/CStructuralIntegration.hpp" + + +CStructuralIntegration::CStructuralIntegration(CConfig *config) : CIntegration(config) { } + +void CStructuralIntegration::Structural_Iteration(CGeometry ****geometry, CSolver *****solver_container, + CNumerics ******numerics_container, CConfig **config, + unsigned short RunTime_EqSystem, unsigned short iZone, + unsigned short iInst) { + + unsigned short SolContainer_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); + + CSolver* solver = solver_container[iZone][iInst][MESH_0][SolContainer_Position]; + + + solver->Preprocessing(geometry[iZone][iInst][MESH_0], + solver_container[iZone][iInst][MESH_0], + config[iZone], + numerics_container[iZone][iInst][MESH_0][SolContainer_Position], + MESH_0, + NO_RK_ITER, + RunTime_EqSystem, + false); + + Space_Integration_FEM(geometry[iZone][iInst][MESH_0], + solver_container[iZone][iInst][MESH_0], + numerics_container[iZone][iInst][MESH_0][SolContainer_Position], + config[iZone], + RunTime_EqSystem); + + Time_Integration_FEM(geometry[iZone][iInst][MESH_0], + solver_container[iZone][iInst][MESH_0], + numerics_container[iZone][iInst][MESH_0][SolContainer_Position], + config[iZone], + RunTime_EqSystem); + + solver->Postprocessing(geometry[iZone][iInst][MESH_0], + solver_container[iZone][iInst][MESH_0], + config[iZone], + numerics_container[iZone][iInst][MESH_0][SolContainer_Position], + MESH_0); +} + +void CStructuralIntegration::Space_Integration_FEM(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics, CConfig *config, + unsigned short RunTime_EqSystem) { + bool dynamic = config->GetTime_Domain(); + bool first_iter = (config->GetInnerIter() == 0); + bool linear_analysis = (config->GetGeometricConditions() == SMALL_DEFORMATIONS); + bool nonlinear_analysis = (config->GetGeometricConditions() == LARGE_DEFORMATIONS); + unsigned short IterativeScheme = config->GetKind_SpaceIteScheme_FEA(); + + unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); + CSolver* solver = solver_container[MainSolver]; + + /*--- Initial calculation, different logic for restarted simulations. ---*/ + bool initial_calc = false; + if (config->GetRestart()) + initial_calc = (config->GetTimeIter() == config->GetRestart_Iter()) && first_iter; + else + initial_calc = (config->GetTimeIter() == 0) && first_iter; + + /*--- Mass Matrix computed during preprocessing, see notes therein. ---*/ + + /*--- If the analysis is linear, only a the constitutive term of the stiffness matrix has to be computed. ---*/ + /*--- This is done only once, at the beginning of the calculation. From then on, K is constant. ---*/ + /*--- For correct differentiation of dynamic cases the matrix needs to be computed every time. ---*/ + if (linear_analysis && (dynamic || initial_calc)) + solver->Compute_StiffMatrix(geometry, numerics, config); + + if (nonlinear_analysis) { + + /*--- If the analysis is nonlinear the stress terms also need to be computed. ---*/ + /*--- For full Newton-Raphson the stiffness matrix and the nodal term are updated every time. ---*/ + if (IterativeScheme == NEWTON_RAPHSON) { + solver->Compute_StiffMatrix_NodalStressRes(geometry, numerics, config); + } + + /*--- If the method is modified Newton-Raphson, the stiffness matrix is only computed once at the beginning + * of the time step, then only the Nodal Stress Term has to be computed on each iteration. ---*/ + if (IterativeScheme == MODIFIED_NEWTON_RAPHSON) { + if (first_iter) + solver->Compute_StiffMatrix_NodalStressRes(geometry, numerics, config); + else + solver->Compute_NodalStressRes(geometry, numerics, config); + } + + } + + /*--- Apply the NATURAL BOUNDARY CONDITIONS (loads). ---*/ + /*--- If there are FSI loads, they have to be previously applied at other level involving both zones. ---*/ + + for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + switch (config->GetMarker_All_KindBC(iMarker)) { + + case LOAD_DIR_BOUNDARY: + solver->BC_Dir_Load(geometry, numerics[FEA_TERM], config, iMarker); + break; + + case LOAD_SINE_BOUNDARY: + solver->BC_Sine_Load(geometry, numerics[FEA_TERM], config, iMarker); + break; + + case LOAD_BOUNDARY: + solver->BC_Normal_Load(geometry, numerics[FEA_TERM], config, iMarker); + break; + + case DAMPER_BOUNDARY: + solver->BC_Damper(geometry, numerics[FEA_TERM], config, iMarker); + break; + } + } + +} + +void CStructuralIntegration::Time_Integration_FEM(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics, + CConfig *config, unsigned short RunTime_EqSystem) { + unsigned short iMarker; + + unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); + + /*--- Set the Jacobian according to the different time integration methods ---*/ + + switch (config->GetKind_TimeIntScheme_FEA()) { + case (CD_EXPLICIT): + solver_container[MainSolver]->ImplicitNewmark_Iteration(geometry, solver_container, config); + break; + case (NEWMARK_IMPLICIT): + solver_container[MainSolver]->ImplicitNewmark_Iteration(geometry, solver_container, config); + break; + case (GENERALIZED_ALPHA): + solver_container[MainSolver]->GeneralizedAlpha_Iteration(geometry, solver_container, config); + break; + } + + /*--- Apply ESSENTIAL BOUNDARY CONDITIONS ---*/ + + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + switch (config->GetMarker_All_KindBC(iMarker)) { + case CLAMPED_BOUNDARY: + solver_container[MainSolver]->BC_Clamped(geometry, numerics[FEA_TERM], config, iMarker); + break; + case DISP_DIR_BOUNDARY: + solver_container[MainSolver]->BC_DispDir(geometry, numerics[FEA_TERM], config, iMarker); + break; + case DISPLACEMENT_BOUNDARY: + solver_container[MainSolver]->BC_Normal_Displacement(geometry, numerics[CONV_BOUND_TERM], config, iMarker); + break; + } + } + + /*--- Solver linearized system ---*/ + + solver_container[MainSolver]->Solve_System(geometry, config); + + /*--- Update solution ---*/ + + switch (config->GetKind_TimeIntScheme_FEA()) { + case (CD_EXPLICIT): + solver_container[MainSolver]->ImplicitNewmark_Update(geometry, solver_container, config); + break; + case (NEWMARK_IMPLICIT): + solver_container[MainSolver]->ImplicitNewmark_Update(geometry, solver_container, config); + break; + case (GENERALIZED_ALPHA): + solver_container[MainSolver]->GeneralizedAlpha_UpdateDisp(geometry, solver_container, config); + break; + } + + /*--- Reinforce ESSENTIAL BOUNDARY CONDITIONS: avoids accumulation of numerical error ---*/ + + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + switch (config->GetMarker_All_KindBC(iMarker)) { + case CLAMPED_BOUNDARY: + solver_container[MainSolver]->BC_Clamped_Post(geometry, numerics[FEA_TERM], config, iMarker); + break; + } + } + + /*--- Perform the MPI communication of the solution ---*/ + + solver_container[MainSolver]->InitiateComms(geometry, config, SOLUTION_FEA); + solver_container[MainSolver]->CompleteComms(geometry, config, SOLUTION_FEA); + +} diff --git a/SU2_CFD/src/integration_time.cpp b/SU2_CFD/src/integration_time.cpp deleted file mode 100644 index 40058283a689..000000000000 --- a/SU2_CFD/src/integration_time.cpp +++ /dev/null @@ -1,1044 +0,0 @@ -/*! - * \file integration_time.cpp - * \brief Time dependent numerical methods - * \author F. Palacios, T. Economon - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - - -#include "../include/integration_structure.hpp" - -CMultiGridIntegration::CMultiGridIntegration(CConfig *config) : CIntegration(config) {} - -CMultiGridIntegration::~CMultiGridIntegration(void) { } - -void CMultiGridIntegration::MultiGrid_Iteration(CGeometry ****geometry, - CSolver *****solver_container, - CNumerics ******numerics_container, - CConfig **config, - unsigned short RunTime_EqSystem, - unsigned short iZone, - unsigned short iInst) { - unsigned short FinestMesh; - su2double monitor = 1.0; - bool FullMG = false; - - const bool direct = ((config[iZone]->GetKind_Solver() == EULER) || - (config[iZone]->GetKind_Solver() == NAVIER_STOKES) || - (config[iZone]->GetKind_Solver() == RANS) || - (config[iZone]->GetKind_Solver() == FEM_EULER) || - (config[iZone]->GetKind_Solver() == FEM_NAVIER_STOKES) || - (config[iZone]->GetKind_Solver() == FEM_RANS) || - (config[iZone]->GetKind_Solver() == FEM_LES) || - (config[iZone]->GetKind_Solver() == DISC_ADJ_EULER) || - (config[iZone]->GetKind_Solver() == DISC_ADJ_NAVIER_STOKES) || - (config[iZone]->GetKind_Solver() == DISC_ADJ_FEM_EULER) || - (config[iZone]->GetKind_Solver() == DISC_ADJ_FEM_NS) || - (config[iZone]->GetKind_Solver() == DISC_ADJ_RANS)); - const unsigned short SolContainer_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); - unsigned short RecursiveParam = config[iZone]->GetMGCycle(); - - if (config[iZone]->GetMGCycle() == FULLMG_CYCLE) { - RecursiveParam = V_CYCLE; - FullMG = true; - } - - /*--- Full multigrid strategy and start up with fine grid only works with the direct problem ---*/ - - if (!config[iZone]->GetRestart() && FullMG && direct && ( Convergence_FullMG && (config[iZone]->GetFinestMesh() != MESH_0 ))) { - SetProlongated_Solution(RunTime_EqSystem, solver_container[iZone][iInst][config[iZone]->GetFinestMesh()-1][SolContainer_Position], - solver_container[iZone][iInst][config[iZone]->GetFinestMesh()][SolContainer_Position], - geometry[iZone][iInst][config[iZone]->GetFinestMesh()-1], geometry[iZone][iInst][config[iZone]->GetFinestMesh()], - config[iZone]); - config[iZone]->SubtractFinestMesh(); - } - - /*--- Set the current finest grid (full multigrid strategy) ---*/ - - FinestMesh = config[iZone]->GetFinestMesh(); - - /*--- Perform the Full Approximation Scheme multigrid ---*/ - - MultiGrid_Cycle(geometry, solver_container, numerics_container, config, - FinestMesh, RecursiveParam, RunTime_EqSystem, - iZone, iInst); - - /*--- Computes primitive variables and gradients in the finest mesh (useful for the next solver (turbulence) and output ---*/ - - solver_container[iZone][iInst][MESH_0][SolContainer_Position]->Preprocessing(geometry[iZone][iInst][MESH_0], - solver_container[iZone][iInst][MESH_0], config[iZone], - MESH_0, NO_RK_ITER, RunTime_EqSystem, true); - - /*--- Compute non-dimensional parameters and the convergence monitor ---*/ - - NonDimensional_Parameters(geometry[iZone][iInst], solver_container[iZone][iInst], - numerics_container[iZone][iInst], config[iZone], - FinestMesh, RunTime_EqSystem, &monitor); - -} - -void CMultiGridIntegration::MultiGrid_Cycle(CGeometry ****geometry, - CSolver *****solver_container, - CNumerics ******numerics_container, - CConfig **config, - unsigned short iMesh, - unsigned short RecursiveParam, - unsigned short RunTime_EqSystem, - unsigned short iZone, - unsigned short iInst) { - - unsigned short iPreSmooth, iPostSmooth, iRKStep, iRKLimit = 1; - unsigned short SolContainer_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); - - /*--- Do a presmoothing on the grid iMesh to be restricted to the grid iMesh+1 ---*/ - - for (iPreSmooth = 0; iPreSmooth < config[iZone]->GetMG_PreSmooth(iMesh); iPreSmooth++) { - - switch (config[iZone]->GetKind_TimeIntScheme()) { - case RUNGE_KUTTA_EXPLICIT: iRKLimit = config[iZone]->GetnRKStep(); break; - case CLASSICAL_RK4_EXPLICIT: iRKLimit = 4; break; - case EULER_EXPLICIT: case EULER_IMPLICIT: iRKLimit = 1; break; } - - /*--- Time and space integration ---*/ - - for (iRKStep = 0; iRKStep < iRKLimit; iRKStep++) { - - /*--- Send-Receive boundary conditions, and preprocessing ---*/ - - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Preprocessing(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], config[iZone], iMesh, iRKStep, RunTime_EqSystem, false); - - if (iRKStep == 0) { - - /*--- Set the old solution ---*/ - - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Set_OldSolution(geometry[iZone][iInst][iMesh]); - - if (config[iZone]->GetKind_TimeIntScheme() == CLASSICAL_RK4_EXPLICIT) - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Set_NewSolution(geometry[iZone][iInst][iMesh]); - - /*--- Compute time step, max eigenvalue, and integration scheme (steady and unsteady problems) ---*/ - - solver_container[iZone][iInst][iMesh][SolContainer_Position]->SetTime_Step(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], config[iZone], iMesh, config[iZone]->GetTimeIter()); - - /*--- Restrict the solution and gradient for the adjoint problem ---*/ - - Adjoint_Setup(geometry, solver_container, config, RunTime_EqSystem, config[iZone]->GetTimeIter(), iZone); - - } - - /*--- Space integration ---*/ - - Space_Integration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], numerics_container[iZone][iInst][iMesh][SolContainer_Position], config[iZone], iMesh, iRKStep, RunTime_EqSystem); - - /*--- Time integration, update solution using the old solution plus the solution increment ---*/ - - Time_Integration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], config[iZone], iRKStep, RunTime_EqSystem); - - /*--- Send-Receive boundary conditions, and postprocessing ---*/ - - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Postprocessing(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], config[iZone], iMesh); - - } - - } - - /*--- Compute Forcing Term $P_(k+1) = I^(k+1)_k(P_k+F_k(u_k))-F_(k+1)(I^(k+1)_k u_k)$ and update solution for multigrid ---*/ - if ( iMesh < config[iZone]->GetnMGLevels() ) { - /*--- Compute $r_k = P_k + F_k(u_k)$ ---*/ - - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Preprocessing(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], config[iZone], iMesh, NO_RK_ITER, RunTime_EqSystem, false); - Space_Integration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], numerics_container[iZone][iInst][iMesh][SolContainer_Position], config[iZone], iMesh, NO_RK_ITER, RunTime_EqSystem); - SetResidual_Term(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh][SolContainer_Position]); - - /*--- Compute $r_(k+1) = F_(k+1)(I^(k+1)_k u_k)$ ---*/ - - SetRestricted_Solution(RunTime_EqSystem, solver_container[iZone][iInst][iMesh][SolContainer_Position], solver_container[iZone][iInst][iMesh+1][SolContainer_Position], geometry[iZone][iInst][iMesh], geometry[iZone][iInst][iMesh+1], config[iZone]); - solver_container[iZone][iInst][iMesh+1][SolContainer_Position]->Preprocessing(geometry[iZone][iInst][iMesh+1], solver_container[iZone][iInst][iMesh+1], config[iZone], iMesh+1, NO_RK_ITER, RunTime_EqSystem, false); - Space_Integration(geometry[iZone][iInst][iMesh+1], solver_container[iZone][iInst][iMesh+1], numerics_container[iZone][iInst][iMesh+1][SolContainer_Position], config[iZone], iMesh+1, NO_RK_ITER, RunTime_EqSystem); - - /*--- Compute $P_(k+1) = I^(k+1)_k(r_k) - r_(k+1) ---*/ - - SetForcing_Term(solver_container[iZone][iInst][iMesh][SolContainer_Position], solver_container[iZone][iInst][iMesh+1][SolContainer_Position], geometry[iZone][iInst][iMesh], geometry[iZone][iInst][iMesh+1], config[iZone], iMesh+1); - - /*--- Recursive call to MultiGrid_Cycle ---*/ - - for (unsigned short imu = 0; imu <= RecursiveParam; imu++) { - if (iMesh == config[iZone]->GetnMGLevels()-2) MultiGrid_Cycle(geometry, solver_container, numerics_container, config, iMesh+1, 0, RunTime_EqSystem, iZone, iInst); - else MultiGrid_Cycle(geometry, solver_container, numerics_container, config, iMesh+1, RecursiveParam, RunTime_EqSystem, iZone, iInst); - } - - /*--- Compute prolongated solution, and smooth the correction $u^(new)_k = u_k + Smooth(I^k_(k+1)(u_(k+1)-I^(k+1)_k u_k))$ ---*/ - - GetProlongated_Correction(RunTime_EqSystem, solver_container[iZone][iInst][iMesh][SolContainer_Position], solver_container[iZone][iInst][iMesh+1][SolContainer_Position], - geometry[iZone][iInst][iMesh], geometry[iZone][iInst][iMesh+1], config[iZone]); - SmoothProlongated_Correction(RunTime_EqSystem, solver_container[iZone][iInst][iMesh][SolContainer_Position], geometry[iZone][iInst][iMesh], - config[iZone]->GetMG_CorrecSmooth(iMesh), 1.25, config[iZone]); - SetProlongated_Correction(solver_container[iZone][iInst][iMesh][SolContainer_Position], geometry[iZone][iInst][iMesh], config[iZone], iMesh); - - /*--- Solution postsmoothing in the prolongated grid ---*/ - - for (iPostSmooth = 0; iPostSmooth < config[iZone]->GetMG_PostSmooth(iMesh); iPostSmooth++) { - - switch (config[iZone]->GetKind_TimeIntScheme()) { - case RUNGE_KUTTA_EXPLICIT: iRKLimit = config[iZone]->GetnRKStep(); break; - case CLASSICAL_RK4_EXPLICIT: iRKLimit = 4; break; - case EULER_EXPLICIT: case EULER_IMPLICIT: iRKLimit = 1; break; } - - for (iRKStep = 0; iRKStep < iRKLimit; iRKStep++) { - - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Preprocessing(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], config[iZone], iMesh, iRKStep, RunTime_EqSystem, false); - - if (iRKStep == 0) { - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Set_OldSolution(geometry[iZone][iInst][iMesh]); - if (config[iZone]->GetKind_TimeIntScheme() == CLASSICAL_RK4_EXPLICIT) - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Set_NewSolution(geometry[iZone][iInst][iMesh]); - solver_container[iZone][iInst][iMesh][SolContainer_Position]->SetTime_Step(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], config[iZone], iMesh, config[iZone]->GetTimeIter()); - } - - Space_Integration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], numerics_container[iZone][iInst][iMesh][SolContainer_Position], config[iZone], iMesh, iRKStep, RunTime_EqSystem); - Time_Integration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], config[iZone], iRKStep, RunTime_EqSystem); - - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Postprocessing(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], config[iZone], iMesh); - - } - } - } - -} - -void CMultiGridIntegration::GetProlongated_Correction(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, - CGeometry *geo_coarse, CConfig *config) { - unsigned long Point_Fine, Point_Coarse, iVertex; - unsigned short Boundary, iMarker, iChildren, iVar; - su2double Area_Parent, Area_Children, *Solution_Fine, *Solution_Coarse; - - const unsigned short nVar = sol_coarse->GetnVar(); - - su2double *Solution = new su2double[nVar]; - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { - - Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); - - for (iVar = 0; iVar < nVar; iVar++) Solution[iVar] = 0.0; - - for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { - Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); - Area_Children = geo_fine->node[Point_Fine]->GetVolume(); - Solution_Fine = sol_fine->GetNodes()->GetSolution(Point_Fine); - for (iVar = 0; iVar < nVar; iVar++) - Solution[iVar] -= Solution_Fine[iVar]*Area_Children/Area_Parent; - } - - Solution_Coarse = sol_coarse->GetNodes()->GetSolution(Point_Coarse); - - for (iVar = 0; iVar < nVar; iVar++) - Solution[iVar] += Solution_Coarse[iVar]; - - for (iVar = 0; iVar < nVar; iVar++) - sol_coarse->GetNodes()->SetSolution_Old(Point_Coarse,Solution); - - } - - /*--- Remove any contributions from no-slip walls. ---*/ - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - Boundary = config->GetMarker_All_KindBC(iMarker); - if ((Boundary == HEAT_FLUX ) || - (Boundary == ISOTHERMAL ) || - (Boundary == CHT_WALL_INTERFACE )) { - - for (iVertex = 0; iVertex < geo_coarse->nVertex[iMarker]; iVertex++) { - - Point_Coarse = geo_coarse->vertex[iMarker][iVertex]->GetNode(); - - /*--- For dirichlet boundary condtions, set the correction to zero. - Note that Solution_Old stores the correction not the actual value ---*/ - - sol_coarse->GetNodes()->SetVelSolutionOldZero(Point_Coarse); - - } - - } - } - - /*--- MPI the set solution old ---*/ - - sol_coarse->InitiateComms(geo_coarse, config, SOLUTION_OLD); - sol_coarse->CompleteComms(geo_coarse, config, SOLUTION_OLD); - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { - for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { - Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); - sol_fine->LinSysRes.SetBlock(Point_Fine, sol_coarse->GetNodes()->GetSolution_Old(Point_Coarse)); - } - } - - delete [] Solution; - -} - -void CMultiGridIntegration::SmoothProlongated_Correction (unsigned short RunTime_EqSystem, CSolver *solver, CGeometry *geometry, - unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config) { - su2double *Residual_Old, *Residual_Sum, *Residual, *Residual_i, *Residual_j; - unsigned short iVar, iSmooth, iMarker, nneigh; - unsigned long iEdge, iPoint, jPoint, iVertex; - - const unsigned short nVar = solver->GetnVar(); - - if (val_nSmooth > 0) { - - Residual = new su2double [nVar]; - - for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - Residual_Old = solver->LinSysRes.GetBlock(iPoint); - solver->GetNodes()->SetResidual_Old(iPoint,Residual_Old); - } - - /*--- Jacobi iterations ---*/ - - for (iSmooth = 0; iSmooth < val_nSmooth; iSmooth++) { - solver->GetNodes()->SetResidualSumZero(); - - /*--- Loop over Interior edges ---*/ - - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); - - Residual_i = solver->LinSysRes.GetBlock(iPoint); - Residual_j = solver->LinSysRes.GetBlock(jPoint); - - /*--- Accumulate nearest neighbor Residual to Res_sum for each variable ---*/ - - solver->GetNodes()->AddResidual_Sum(iPoint,Residual_j); - solver->GetNodes()->AddResidual_Sum(jPoint,Residual_i); - } - - /*--- Loop over all mesh points (Update Residuals with averaged sum) ---*/ - - for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - nneigh = geometry->node[iPoint]->GetnPoint(); - Residual_Sum = solver->GetNodes()->GetResidual_Sum(iPoint); - Residual_Old = solver->GetNodes()->GetResidual_Old(iPoint); - for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] =(Residual_Old[iVar] + val_smooth_coeff*Residual_Sum[iVar]) - /(1.0 + val_smooth_coeff*su2double(nneigh)); - } - solver->LinSysRes.SetBlock(iPoint, Residual); - } - - /*--- Copy boundary values ---*/ - - for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) - if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && - (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) { - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - Residual_Old = solver->GetNodes()->GetResidual_Old(iPoint); - solver->LinSysRes.SetBlock(iPoint, Residual_Old); - } - } - } - - delete [] Residual; - - } -} - -void CMultiGridIntegration::Smooth_Solution(unsigned short RunTime_EqSystem, CSolver *solver, CGeometry *geometry, - unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config) { - su2double *Solution_Old, *Solution_Sum, *Solution, *Solution_i, *Solution_j; - unsigned short iVar, iSmooth, iMarker, nneigh; - unsigned long iEdge, iPoint, jPoint, iVertex; - - const unsigned short nVar = solver->GetnVar(); - - if (val_nSmooth > 0) { - - Solution = new su2double [nVar]; - - for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - Solution_Old = solver->GetNodes()->GetSolution(iPoint); - solver->GetNodes()->SetResidual_Old(iPoint,Solution_Old); - } - - /*--- Jacobi iterations ---*/ - - for (iSmooth = 0; iSmooth < val_nSmooth; iSmooth++) { - solver->GetNodes()->SetResidualSumZero(); - - /*--- Loop over Interior edges ---*/ - - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); - - Solution_i = solver->GetNodes()->GetSolution(iPoint); - Solution_j = solver->GetNodes()->GetSolution(jPoint); - - /*--- Accumulate nearest neighbor Residual to Res_sum for each variable ---*/ - - solver->GetNodes()->AddResidual_Sum(iPoint,Solution_j); - solver->GetNodes()->AddResidual_Sum(jPoint,Solution_i); - } - - /*--- Loop over all mesh points (Update Residuals with averaged sum) ---*/ - - for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - nneigh = geometry->node[iPoint]->GetnPoint(); - Solution_Sum = solver->GetNodes()->GetResidual_Sum(iPoint); - Solution_Old = solver->GetNodes()->GetResidual_Old(iPoint); - for (iVar = 0; iVar < nVar; iVar++) { - Solution[iVar] =(Solution_Old[iVar] + val_smooth_coeff*Solution_Sum[iVar]) - /(1.0 + val_smooth_coeff*su2double(nneigh)); - } - solver->GetNodes()->SetSolution(iPoint,Solution); - } - - /*--- Copy boundary values ---*/ - - for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) - if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && - (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) { - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - Solution_Old = solver->GetNodes()->GetResidual_Old(iPoint); - solver->GetNodes()->SetSolution(iPoint,Solution_Old); - } - } - } - - delete [] Solution; - - } - -} - -void CMultiGridIntegration::SetProlongated_Correction(CSolver *sol_fine, CGeometry *geo_fine, CConfig *config, unsigned short iMesh) { - unsigned long Point_Fine; - unsigned short iVar; - su2double *Solution_Fine, *Residual_Fine; - - const unsigned short nVar = sol_fine->GetnVar(); - su2double factor = config->GetDamp_Correc_Prolong(); //pow(config->GetDamp_Correc_Prolong(), iMesh+1); - - su2double *Solution = new su2double [nVar]; - - for (Point_Fine = 0; Point_Fine < geo_fine->GetnPointDomain(); Point_Fine++) { - Residual_Fine = sol_fine->LinSysRes.GetBlock(Point_Fine); - Solution_Fine = sol_fine->GetNodes()->GetSolution(Point_Fine); - for (iVar = 0; iVar < nVar; iVar++) { - /*--- Prevent a fine grid divergence due to a coarse grid divergence ---*/ - if (Residual_Fine[iVar] != Residual_Fine[iVar]) Residual_Fine[iVar] = 0.0; - Solution[iVar] = Solution_Fine[iVar]+factor*Residual_Fine[iVar]; - } - sol_fine->GetNodes()->SetSolution(Point_Fine,Solution); - } - - /*--- MPI the new interpolated solution ---*/ - - sol_fine->InitiateComms(geo_fine, config, SOLUTION); - sol_fine->CompleteComms(geo_fine, config, SOLUTION); - - delete [] Solution; -} - - -void CMultiGridIntegration::SetProlongated_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { - unsigned long Point_Fine, Point_Coarse; - unsigned short iChildren; - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { - for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { - Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); - sol_fine->GetNodes()->SetSolution(Point_Fine, sol_coarse->GetNodes()->GetSolution(Point_Coarse)); - } - } -} - -void CMultiGridIntegration::SetForcing_Term(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config, unsigned short iMesh) { - unsigned long Point_Fine, Point_Coarse, iVertex; - unsigned short iMarker, iVar, iChildren; - su2double *Residual_Fine; - - const unsigned short nVar = sol_coarse->GetnVar(); - su2double factor = config->GetDamp_Res_Restric(); //pow(config->GetDamp_Res_Restric(), iMesh); - - su2double *Residual = new su2double[nVar]; - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { - sol_coarse->GetNodes()->SetRes_TruncErrorZero(Point_Coarse); - - for (iVar = 0; iVar < nVar; iVar++) Residual[iVar] = 0.0; - for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { - Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); - Residual_Fine = sol_fine->LinSysRes.GetBlock(Point_Fine); - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] += factor*Residual_Fine[iVar]; - } - sol_coarse->GetNodes()->AddRes_TruncError(Point_Coarse,Residual); - } - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - if ((config->GetMarker_All_KindBC(iMarker) == HEAT_FLUX ) || - (config->GetMarker_All_KindBC(iMarker) == ISOTHERMAL ) || - (config->GetMarker_All_KindBC(iMarker) == CHT_WALL_INTERFACE )) { - for (iVertex = 0; iVertex < geo_coarse->nVertex[iMarker]; iVertex++) { - Point_Coarse = geo_coarse->vertex[iMarker][iVertex]->GetNode(); - sol_coarse->GetNodes()->SetVel_ResTruncError_Zero(Point_Coarse); - } - } - } - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { - sol_coarse->GetNodes()->SubtractRes_TruncError(Point_Coarse, sol_coarse->LinSysRes.GetBlock(Point_Coarse)); - } - - delete [] Residual; -} - -void CMultiGridIntegration::SetResidual_Term(CGeometry *geometry, CSolver *solver) { - unsigned long iPoint; - - for (iPoint = 0; iPoint < geometry->GetnPointDomain(); iPoint++) - solver->LinSysRes.AddBlock(iPoint, solver->GetNodes()->GetResTruncError(iPoint)); - -} - -void CMultiGridIntegration::SetRestricted_Residual(CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { - unsigned long iVertex, Point_Fine, Point_Coarse; - unsigned short iMarker, iVar, iChildren; - su2double *Residual_Fine; - - const unsigned short nVar = sol_coarse->GetnVar(); - - su2double *Residual = new su2double[nVar]; - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { - sol_coarse->GetNodes()->SetRes_TruncErrorZero(Point_Coarse); - - for (iVar = 0; iVar < nVar; iVar++) Residual[iVar] = 0.0; - for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { - Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); - Residual_Fine = sol_fine->LinSysRes.GetBlock(Point_Fine); - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] += Residual_Fine[iVar]; - } - sol_coarse->GetNodes()->AddRes_TruncError(Point_Coarse,Residual); - } - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - if ((config->GetMarker_All_KindBC(iMarker) == HEAT_FLUX ) || - (config->GetMarker_All_KindBC(iMarker) == ISOTHERMAL ) || - (config->GetMarker_All_KindBC(iMarker) == CHT_WALL_INTERFACE )) { - for (iVertex = 0; iVertexnVertex[iMarker]; iVertex++) { - Point_Coarse = geo_coarse->vertex[iMarker][iVertex]->GetNode(); - sol_coarse->GetNodes()->SetVel_ResTruncError_Zero(Point_Coarse); - } - } - } - - delete [] Residual; -} - -void CMultiGridIntegration::SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { - unsigned long iVertex, Point_Fine, Point_Coarse; - unsigned short iMarker, iVar, iChildren, iDim; - su2double Area_Parent, Area_Children, *Solution_Fine, *Grid_Vel, Vector[3]; - - const unsigned short SolContainer_Position = config->GetContainerPosition(RunTime_EqSystem); - const unsigned short nVar = sol_coarse->GetnVar(); - const unsigned short nDim = geo_fine->GetnDim(); - const bool grid_movement = config->GetGrid_Movement(); - - su2double *Solution = new su2double[nVar]; - - /*--- Compute coarse solution from fine solution ---*/ - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { - Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); - - for (iVar = 0; iVar < nVar; iVar++) Solution[iVar] = 0.0; - - for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { - - Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); - Area_Children = geo_fine->node[Point_Fine]->GetVolume(); - Solution_Fine = sol_fine->GetNodes()->GetSolution(Point_Fine); - for (iVar = 0; iVar < nVar; iVar++) { - Solution[iVar] += Solution_Fine[iVar]*Area_Children/Area_Parent; - } - } - - sol_coarse->GetNodes()->SetSolution(Point_Coarse,Solution); - - } - - /*--- Update the solution at the no-slip walls ---*/ - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - if ((config->GetMarker_All_KindBC(iMarker) == HEAT_FLUX ) || - (config->GetMarker_All_KindBC(iMarker) == ISOTHERMAL ) || - (config->GetMarker_All_KindBC(iMarker) == CHT_WALL_INTERFACE )) { - - for (iVertex = 0; iVertex < geo_coarse->nVertex[iMarker]; iVertex++) { - Point_Coarse = geo_coarse->vertex[iMarker][iVertex]->GetNode(); - - if (SolContainer_Position == FLOW_SOL) { - - /*--- At moving walls, set the solution based on the new density and wall velocity ---*/ - - if (grid_movement) { - Grid_Vel = geo_coarse->node[Point_Coarse]->GetGridVel(); - for (iDim = 0; iDim < nDim; iDim++) - Vector[iDim] = sol_coarse->GetNodes()->GetSolution(Point_Coarse,0)*Grid_Vel[iDim]; - sol_coarse->GetNodes()->SetVelSolutionVector(Point_Coarse,Vector); - } else { - - /*--- For stationary no-slip walls, set the velocity to zero. ---*/ - - sol_coarse->GetNodes()->SetVelSolutionZero(Point_Coarse); - } - - } - - if (SolContainer_Position == ADJFLOW_SOL) { - sol_coarse->GetNodes()->SetVelSolutionDVector(Point_Coarse); - } - - } - } - } - - /*--- MPI the new interpolated solution ---*/ - - sol_coarse->InitiateComms(geo_coarse, config, SOLUTION); - sol_coarse->CompleteComms(geo_coarse, config, SOLUTION); - - delete [] Solution; - -} - -void CMultiGridIntegration::SetRestricted_Gradient(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, - CGeometry *geo_coarse, CConfig *config) { - unsigned long Point_Fine, Point_Coarse; - unsigned short iVar, iDim, iChildren; - su2double Area_Parent, Area_Children, **Gradient_fine; - - const unsigned short nDim = geo_coarse->GetnDim(); - const unsigned short nVar = sol_coarse->GetnVar(); - - su2double **Gradient = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar++) - Gradient[iVar] = new su2double [nDim]; - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPoint(); Point_Coarse++) { - Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); - - for (iVar = 0; iVar < nVar; iVar++) - for (iDim = 0; iDim < nDim; iDim++) - Gradient[iVar][iDim] = 0.0; - - for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { - Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); - Area_Children = geo_fine->node[Point_Fine]->GetVolume(); - Gradient_fine = sol_fine->GetNodes()->GetGradient(Point_Fine); - - for (iVar = 0; iVar < nVar; iVar++) - for (iDim = 0; iDim < nDim; iDim++) - Gradient[iVar][iDim] += Gradient_fine[iVar][iDim]*Area_Children/Area_Parent; - } - sol_coarse->GetNodes()->SetGradient(Point_Coarse,Gradient); - } - - for (iVar = 0; iVar < nVar; iVar++) - delete [] Gradient[iVar]; - delete [] Gradient; - -} - -void CMultiGridIntegration::NonDimensional_Parameters(CGeometry **geometry, CSolver ***solver_container, CNumerics ****numerics_container, - CConfig *config, unsigned short FinestMesh, unsigned short RunTime_EqSystem, - su2double *monitor) { - - switch (RunTime_EqSystem) { - - case RUNTIME_FLOW_SYS: - - /*--- Calculate the inviscid and viscous forces ---*/ - - solver_container[FinestMesh][FLOW_SOL]->Pressure_Forces(geometry[FinestMesh], config); - solver_container[FinestMesh][FLOW_SOL]->Momentum_Forces(geometry[FinestMesh], config); - solver_container[FinestMesh][FLOW_SOL]->Friction_Forces(geometry[FinestMesh], config); - - /*--- Evaluate the buffet metric if requested ---*/ - - if(config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR){ - solver_container[FinestMesh][FLOW_SOL]->Buffet_Monitoring(geometry[FinestMesh], config); - } - - break; - - case RUNTIME_ADJFLOW_SYS: - - /*--- Calculate the inviscid and viscous sensitivities ---*/ - - solver_container[FinestMesh][ADJFLOW_SOL]->Inviscid_Sensitivity(geometry[FinestMesh], solver_container[FinestMesh], numerics_container[FinestMesh][ADJFLOW_SOL][CONV_BOUND_TERM], config); - solver_container[FinestMesh][ADJFLOW_SOL]->Viscous_Sensitivity(geometry[FinestMesh], solver_container[FinestMesh], numerics_container[FinestMesh][ADJFLOW_SOL][CONV_BOUND_TERM], config); - - /*--- Smooth the inviscid and viscous sensitivities ---*/ - - if (config->GetKind_SensSmooth() != NONE) solver_container[FinestMesh][ADJFLOW_SOL]->Smooth_Sensitivity(geometry[FinestMesh], solver_container[FinestMesh], numerics_container[FinestMesh][ADJFLOW_SOL][CONV_BOUND_TERM], config); - - break; - - } - -} - -CSingleGridIntegration::CSingleGridIntegration(CConfig *config) : CIntegration(config) { } - -CSingleGridIntegration::~CSingleGridIntegration(void) { } - -void CSingleGridIntegration::SingleGrid_Iteration(CGeometry ****geometry, CSolver *****solver_container, - CNumerics ******numerics_container, CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) { - unsigned short iMesh; - - unsigned short SolContainer_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); - - unsigned short FinestMesh = config[iZone]->GetFinestMesh(); - - /*--- Preprocessing ---*/ - - solver_container[iZone][iInst][FinestMesh][SolContainer_Position]->Preprocessing(geometry[iZone][iInst][FinestMesh], solver_container[iZone][iInst][FinestMesh], config[iZone], FinestMesh, 0, RunTime_EqSystem, false); - - /*--- Set the old solution ---*/ - - solver_container[iZone][iInst][FinestMesh][SolContainer_Position]->Set_OldSolution(geometry[iZone][iInst][FinestMesh]); - - /*--- Time step evaluation ---*/ - - solver_container[iZone][iInst][FinestMesh][SolContainer_Position]->SetTime_Step(geometry[iZone][iInst][FinestMesh], solver_container[iZone][iInst][FinestMesh], config[iZone], FinestMesh, config[iZone]->GetTimeIter()); - - /*--- Space integration ---*/ - - Space_Integration(geometry[iZone][iInst][FinestMesh], solver_container[iZone][iInst][FinestMesh], numerics_container[iZone][iInst][FinestMesh][SolContainer_Position], - config[iZone], FinestMesh, NO_RK_ITER, RunTime_EqSystem); - - /*--- Time integration ---*/ - - Time_Integration(geometry[iZone][iInst][FinestMesh], solver_container[iZone][iInst][FinestMesh], config[iZone], NO_RK_ITER, - RunTime_EqSystem); - - /*--- Postprocessing ---*/ - - solver_container[iZone][iInst][FinestMesh][SolContainer_Position]->Postprocessing(geometry[iZone][iInst][FinestMesh], solver_container[iZone][iInst][FinestMesh], config[iZone], FinestMesh); - - if (RunTime_EqSystem == RUNTIME_HEAT_SYS) { - solver_container[iZone][iInst][FinestMesh][HEAT_SOL]->Heat_Fluxes(geometry[iZone][iInst][FinestMesh], solver_container[iZone][iInst][FinestMesh], config[iZone]); - } - - /*--- If turbulence model, copy the turbulence variables to the coarse levels ---*/ - - if (RunTime_EqSystem == RUNTIME_TURB_SYS) { - for (iMesh = FinestMesh; iMesh < config[iZone]->GetnMGLevels(); iMesh++) { - SetRestricted_Solution(RunTime_EqSystem, solver_container[iZone][iInst][iMesh][SolContainer_Position], solver_container[iZone][iInst][iMesh+1][SolContainer_Position], geometry[iZone][iInst][iMesh], geometry[iZone][iInst][iMesh+1], config[iZone]); - SetRestricted_EddyVisc(RunTime_EqSystem, solver_container[iZone][iInst][iMesh][SolContainer_Position], solver_container[iZone][iInst][iMesh+1][SolContainer_Position], geometry[iZone][iInst][iMesh], geometry[iZone][iInst][iMesh+1], config[iZone]); - } - } -} - -void CSingleGridIntegration::SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { - unsigned long Point_Fine, Point_Coarse; - unsigned short iVar, iChildren; - su2double Area_Parent, Area_Children, *Solution_Fine, *Solution; - - unsigned short nVar = sol_coarse->GetnVar(); - - Solution = new su2double[nVar]; - - /*--- Compute coarse solution from fine solution ---*/ - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { - Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); - - for (iVar = 0; iVar < nVar; iVar++) Solution[iVar] = 0.0; - - for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { - - Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); - Area_Children = geo_fine->node[Point_Fine]->GetVolume(); - Solution_Fine = sol_fine->GetNodes()->GetSolution(Point_Fine); - for (iVar = 0; iVar < nVar; iVar++) - Solution[iVar] += Solution_Fine[iVar]*Area_Children/Area_Parent; - } - - sol_coarse->GetNodes()->SetSolution(Point_Coarse,Solution); - - } - - /*--- MPI the new interpolated solution ---*/ - - sol_coarse->InitiateComms(geo_coarse, config, SOLUTION); - sol_coarse->CompleteComms(geo_coarse, config, SOLUTION); - - delete [] Solution; - -} - -void CSingleGridIntegration::SetRestricted_EddyVisc(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse, CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config) { - - unsigned long iVertex, Point_Fine, Point_Coarse; - unsigned short iMarker, iChildren; - su2double Area_Parent, Area_Children, EddyVisc_Fine, EddyVisc; - - /*--- Compute coarse Eddy Viscosity from fine solution ---*/ - - for (Point_Coarse = 0; Point_Coarse < geo_coarse->GetnPointDomain(); Point_Coarse++) { - Area_Parent = geo_coarse->node[Point_Coarse]->GetVolume(); - - EddyVisc = 0.0; - - for (iChildren = 0; iChildren < geo_coarse->node[Point_Coarse]->GetnChildren_CV(); iChildren++) { - Point_Fine = geo_coarse->node[Point_Coarse]->GetChildren_CV(iChildren); - Area_Children = geo_fine->node[Point_Fine]->GetVolume(); - EddyVisc_Fine = sol_fine->GetNodes()->GetmuT(Point_Fine); - EddyVisc += EddyVisc_Fine*Area_Children/Area_Parent; - } - - sol_coarse->GetNodes()->SetmuT(Point_Coarse,EddyVisc); - - } - - /*--- Update solution at the no slip wall boundary, only the first - variable (nu_tilde -in SA and SA_NEG- and k -in SST-), to guarantee that the eddy viscoisty - is zero on the surface ---*/ - - for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - if ((config->GetMarker_All_KindBC(iMarker) == HEAT_FLUX ) || - (config->GetMarker_All_KindBC(iMarker) == ISOTHERMAL ) || - (config->GetMarker_All_KindBC(iMarker) == CHT_WALL_INTERFACE )) { - for (iVertex = 0; iVertex < geo_coarse->nVertex[iMarker]; iVertex++) { - Point_Coarse = geo_coarse->vertex[iMarker][iVertex]->GetNode(); - sol_coarse->GetNodes()->SetmuT(Point_Coarse,0.0); - } - } - } - - /*--- MPI the new interpolated solution (this also includes the eddy viscosity) ---*/ - - sol_coarse->InitiateComms(geo_coarse, config, SOLUTION_EDDY); - sol_coarse->CompleteComms(geo_coarse, config, SOLUTION_EDDY); - -} - - -CStructuralIntegration::CStructuralIntegration(CConfig *config) : CIntegration(config) { } - -CStructuralIntegration::~CStructuralIntegration(void) { } - -void CStructuralIntegration::Structural_Iteration(CGeometry ****geometry, CSolver *****solver_container, - CNumerics ******numerics_container, CConfig **config, unsigned short RunTime_EqSystem, unsigned short iZone, unsigned short iInst) { - - unsigned short SolContainer_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); - - /*--- Preprocessing ---*/ - - solver_container[iZone][iInst][MESH_0][SolContainer_Position]->Preprocessing(geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], - config[iZone], numerics_container[iZone][iInst][MESH_0][SolContainer_Position], MESH_0, NO_RK_ITER, RunTime_EqSystem, false); - - - /*--- Space integration ---*/ - - Space_Integration_FEM(geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], numerics_container[iZone][iInst][MESH_0][SolContainer_Position], - config[iZone], RunTime_EqSystem); - - /*--- Time integration ---*/ - - Time_Integration_FEM(geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], numerics_container[iZone][iInst][MESH_0][SolContainer_Position], - config[iZone], RunTime_EqSystem); - - /*--- Postprocessing ---*/ - - solver_container[iZone][iInst][MESH_0][SolContainer_Position]->Postprocessing(geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], - config[iZone], numerics_container[iZone][iInst][MESH_0][SolContainer_Position], MESH_0); - -} - -CFEM_DG_Integration::CFEM_DG_Integration(CConfig *config) : CIntegration(config) { } - -CFEM_DG_Integration::~CFEM_DG_Integration(void) { } - -void CFEM_DG_Integration::SingleGrid_Iteration(CGeometry ****geometry, - CSolver *****solver_container, - CNumerics ******numerics_container, - CConfig **config, - unsigned short RunTime_EqSystem, - unsigned short iZone, - unsigned short iInst) { - - unsigned short iMesh, iStep, iLimit = 1; - unsigned short SolContainer_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); - unsigned short FinestMesh = config[iZone]->GetFinestMesh(); - - /*--- For now, we assume no geometric multigrid. ---*/ - iMesh = FinestMesh; - - /*--- Check if only the Jacobian of the spatial discretization must - be computed. If so, call the appropriate function and return. ---*/ - if (config[iZone]->GetJacobian_Spatial_Discretization_Only()) { - solver_container[iZone][iInst][iMesh][SolContainer_Position]->ComputeSpatialJacobian(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], - numerics_container[iZone][iInst][iMesh][SolContainer_Position], - config[iZone], iMesh, RunTime_EqSystem); - return; - } - - /*--- Determine the number of stages in the time stepping algorithm. - For the Runge-Kutta schemes this is the number of RK stages, - while for ADER-DG this information is not used, because a more - complicated algorithm must be used to facilitate time accurate - local time stepping. Note that we are currently hard-coding - the classical RK4 scheme. ---*/ - bool useADER = false; - switch (config[iZone]->GetKind_TimeIntScheme()) { - case RUNGE_KUTTA_EXPLICIT: iLimit = config[iZone]->GetnRKStep(); break; - case CLASSICAL_RK4_EXPLICIT: iLimit = 4; break; - case ADER_DG: iLimit = 1; useADER = true; break; - case EULER_EXPLICIT: case EULER_IMPLICIT: iLimit = 1; break; } - - /*--- In case an unsteady simulation is carried out, it is possible that a - synchronization time step is specified. If so, set the boolean - TimeSynSpecified to true, which leads to an outer loop in the - algorithm below. ---*/ - bool TimeSyncSpecified = false; - const su2double TimeSync = config[iZone]->GetTime_Step()/config[iZone]->GetTime_Ref(); - if(config[iZone]->GetTime_Marching() == TIME_STEPPING && - config[iZone]->GetUnst_CFL() != 0.0 && - TimeSync != 0.0) TimeSyncSpecified = true; - - /*--- Outer loop, which is only active when a synchronization time has been - specified for an unsteady simulation. ---*/ - bool syncTimeReached = false; - su2double timeEvolved = 0.0; - while( !syncTimeReached ) { - - /* Compute the time step for stability. */ - solver_container[iZone][iInst][iMesh][SolContainer_Position]->SetTime_Step(geometry[iZone][iInst][iMesh], - solver_container[iZone][iInst][iMesh], - config[iZone], iMesh, config[iZone]->GetTimeIter()); - /* Possibly overrule the specified time step when a synchronization time was - specified and determine whether or not the time loop must be continued. - When TimeSyncSpecified is false, the loop is always terminated. */ - if( TimeSyncSpecified ) - solver_container[iZone][iInst][iMesh][SolContainer_Position]->CheckTimeSynchronization(config[iZone], - TimeSync, timeEvolved, - syncTimeReached); - else - syncTimeReached = true; - - /*--- For ADER in combination with time accurate local time stepping, the - space and time integration are tightly coupled and cannot be treated - segregatedly. Therefore a different function is called for ADER to - carry out the space and time integration. ---*/ - if( useADER ) { - solver_container[iZone][iInst][iMesh][SolContainer_Position]->ADER_SpaceTimeIntegration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], - numerics_container[iZone][iInst][iMesh][SolContainer_Position], - config[iZone], iMesh, RunTime_EqSystem); - } - else { - - /*--- Time and space integration can be decoupled. ---*/ - for (iStep = 0; iStep < iLimit; iStep++) { - - /*--- Preprocessing ---*/ - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Preprocessing(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], - config[iZone], iMesh, iStep, RunTime_EqSystem, false); - - /*--- Space integration ---*/ - Space_Integration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], - numerics_container[iZone][iInst][iMesh][SolContainer_Position], - config[iZone], iMesh, iStep, RunTime_EqSystem); - - /*--- Time integration, update solution using the old solution plus the solution increment ---*/ - Time_Integration(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], - config[iZone], iStep, RunTime_EqSystem); - - /*--- Postprocessing ---*/ - solver_container[iZone][iInst][iMesh][SolContainer_Position]->Postprocessing(geometry[iZone][iInst][iMesh], solver_container[iZone][iInst][iMesh], - config[iZone], iMesh); - } - } - } - - /*--- Calculate the inviscid and viscous forces ---*/ - solver_container[iZone][iInst][FinestMesh][SolContainer_Position]->Pressure_Forces(geometry[iZone][iInst][iMesh], config[iZone]); - - solver_container[iZone][iInst][FinestMesh][SolContainer_Position]->Friction_Forces(geometry[iZone][iInst][iMesh], config[iZone]); - - /*--- Convergence strategy ---*/ - - //Convergence_Monitoring(geometry[iZone][iInst][FinestMesh], config[iZone], Iteration, monitor, FinestMesh); -} - -void CFEM_DG_Integration::Space_Integration(CGeometry *geometry, - CSolver **solver_container, - CNumerics **numerics, - CConfig *config, unsigned short iMesh, - unsigned short iStep, - unsigned short RunTime_EqSystem) { - - unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); - - /*--- Runge-Kutta type of time integration schemes. In the first step, i.e. - if iStep == 0, set the old solution (working solution for the DG part), - and if needed, the new solution. ---*/ - if (iStep == 0) { - solver_container[MainSolver]->Set_OldSolution(geometry); - - if (config->GetKind_TimeIntScheme() == CLASSICAL_RK4_EXPLICIT) { - solver_container[MainSolver]->Set_NewSolution(geometry); - } - } - - /*--- Compute the spatial residual by processing the task list. ---*/ - solver_container[MainSolver]->ProcessTaskList_DG(geometry, solver_container, numerics, config, iMesh); -} - -void CFEM_DG_Integration::Time_Integration(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iStep, - unsigned short RunTime_EqSystem) { - - unsigned short MainSolver = config->GetContainerPosition(RunTime_EqSystem); - - /*--- Perform the time integration ---*/ - switch (config->GetKind_TimeIntScheme()) { - case (RUNGE_KUTTA_EXPLICIT): - solver_container[MainSolver]->ExplicitRK_Iteration(geometry, solver_container, config, iStep); - break; - case (CLASSICAL_RK4_EXPLICIT): - solver_container[MainSolver]->ClassicalRK4_Iteration(geometry, solver_container, config, iStep); - break; - default: - SU2_MPI::Error("Time integration scheme not implemented.", CURRENT_FUNCTION); - } -} diff --git a/SU2_CFD/src/interfaces/cht/CConjugateHeatInterface.cpp b/SU2_CFD/src/interfaces/cht/CConjugateHeatInterface.cpp index 166ec4c6b5a5..027d221cc8d1 100644 --- a/SU2_CFD/src/interfaces/cht/CConjugateHeatInterface.cpp +++ b/SU2_CFD/src/interfaces/cht/CConjugateHeatInterface.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-2019, SU2 Contributors (cf. AUTHORS.md) diff --git a/SU2_CFD/src/iteration_structure.cpp b/SU2_CFD/src/iteration_structure.cpp index 64408875f47e..49c4b93d5b44 100644 --- a/SU2_CFD/src/iteration_structure.cpp +++ b/SU2_CFD/src/iteration_structure.cpp @@ -625,7 +625,7 @@ void CFluidIteration::Update(COutput *output, /*--- Update dual time solver for the dynamic mesh solver ---*/ if (config[val_iZone]->GetDeform_Mesh()) { - solver[val_iZone][val_iInst][MESH_0][MESH_SOL]->SetDualTime_Mesh(); + solver[val_iZone][val_iInst][MESH_0][MESH_SOL]->SetDualTime_Mesh(); } /*--- Update dual time solver for the turbulence model ---*/ @@ -1431,7 +1431,7 @@ void CFEAIteration::Iterate(COutput *output, /*--- Write the convergence history (first, compute Von Mises stress) ---*/ - Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0); + Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0); /*--- Run the second iteration ---*/ @@ -1470,7 +1470,8 @@ void CFEAIteration::Iterate(COutput *output, config, RUNTIME_FEA_SYS, val_iZone, val_iInst); /*--- Write the convergence history (first, compute Von Mises stress) ---*/ - StopCalc = Monitor(output, integration, geometry, solver, numerics, config, surface_movement, grid_movement, FFDBox, val_iZone, INST_0); + StopCalc = Monitor(output, integration, geometry, solver, numerics, config, + surface_movement, grid_movement, FFDBox, val_iZone, INST_0); if (StopCalc) break; @@ -1485,7 +1486,8 @@ void CFEAIteration::Iterate(COutput *output, /*--- Here we have to restart the solution to the original one of the iteration ---*/ /*--- Retrieve the Solution_Old as the current solution before subiterating ---*/ - solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->ResetInitialCondition(geometry[val_iZone][val_iInst], solver[val_iZone][val_iInst], config[val_iZone], TimeIter); + solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->ResetInitialCondition(geometry[val_iZone][val_iInst], + solver[val_iZone][val_iInst], config[val_iZone], TimeIter); /*--- For the number of increments ---*/ for (iIncrement = 0; iIncrement < nIncrements; iIncrement++) { @@ -1601,7 +1603,8 @@ void CFEAIteration::Update(COutput *output, /*----------------- Update structural solver ----------------------*/ if (dynamic) { - integration[val_iZone][val_iInst][FEA_SOL]->SetFEM_StructuralSolver(geometry[val_iZone][val_iInst][MESH_0], solver[val_iZone][val_iInst][MESH_0], config[val_iZone], MESH_0); + + integration[val_iZone][val_iInst][FEA_SOL]->SetStructural_Solver(geometry[val_iZone][val_iInst][MESH_0], solver[val_iZone][val_iInst][MESH_0], config[val_iZone], MESH_0); integration[val_iZone][val_iInst][FEA_SOL]->SetConvergence(false); /*--- Verify convergence criteria (based on total time) ---*/ @@ -1610,14 +1613,14 @@ void CFEAIteration::Update(COutput *output, Physical_t = (TimeIter+1)*Physical_dt; if (Physical_t >= config[val_iZone]->GetTotal_DynTime()) integration[val_iZone][val_iInst][FEA_SOL]->SetConvergence(true); - } else if ( static_fem && fsi) { + + } else if ( static_fem && fsi) { /*--- For FSI problems, output the relaxed result, which is the one transferred into the fluid domain (for restart purposes) ---*/ switch (config[val_iZone]->GetKind_TimeIntScheme_FEA()) { - case (NEWMARK_IMPLICIT): + case (NEWMARK_IMPLICIT): solver[val_iZone][val_iInst][MESH_0][FEA_SOL]->ImplicitNewmark_Relaxation(geometry[val_iZone][val_iInst][MESH_0], solver[val_iZone][val_iInst][MESH_0], config[val_iZone]); - break; - + break; } } @@ -2288,20 +2291,18 @@ void CDiscAdjFluidIteration::InitializeAdjoint(CSolver *****solver, CGeometry ** if ((Kind_Solver == DISC_ADJ_NAVIER_STOKES) || (Kind_Solver == DISC_ADJ_RANS) || (Kind_Solver == DISC_ADJ_EULER) || (Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES) || (Kind_Solver == DISC_ADJ_INC_RANS) || (Kind_Solver == DISC_ADJ_INC_EULER)) { - solver[iZone][iInst][MESH_0][ADJFLOW_SOL]->SetAdjoint_Output(geometry[iZone][iInst][MESH_0], - config[iZone]); + solver[iZone][iInst][MESH_0][ADJFLOW_SOL]->SetAdjoint_Output(geometry[iZone][iInst][MESH_0], config[iZone]); } if (turbulent && !frozen_visc) { - solver[iZone][iInst][MESH_0][ADJTURB_SOL]->SetAdjoint_Output(geometry[iZone][iInst][MESH_0], - config[iZone]); + solver[iZone][iInst][MESH_0][ADJTURB_SOL]->SetAdjoint_Output(geometry[iZone][iInst][MESH_0], config[iZone]); } if (heat) { - solver[iZone][iInst][MESH_0][ADJHEAT_SOL]->SetAdjoint_Output(geometry[iZone][iInst][MESH_0], - config[iZone]); + solver[iZone][iInst][MESH_0][ADJHEAT_SOL]->SetAdjoint_Output(geometry[iZone][iInst][MESH_0], config[iZone]); } - if (interface_boundary){ + + if (interface_boundary) { solver[iZone][iInst][MESH_0][FLOW_SOL]->SetVertexTractionsAdjoint(geometry[iZone][iInst][MESH_0], config[iZone]); } diff --git a/SU2_CFD/src/limiters/CLimiterDetails.cpp b/SU2_CFD/src/limiters/CLimiterDetails.cpp new file mode 100644 index 000000000000..70d9e9fb01ac --- /dev/null +++ b/SU2_CFD/src/limiters/CLimiterDetails.cpp @@ -0,0 +1,36 @@ +/*! + * \file CLimiterDetails.cpp + * \brief A class template that allows defining limiters via + * specialization of particular details. + * \author P. Gomes + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../Common/include/geometry/CGeometry.hpp" +#include "../../../Common/include/omp_structure.hpp" +#include "../../include/limiters/CLimiterDetails.hpp" + +/*--- Definition of the static members of the Venkatakrishnan-Wang + * specialization of CLimiterDetails, need to be here due to ODR. ---*/ +su2activevector CLimiterDetails::sharedMin; +su2activevector CLimiterDetails::sharedMax; diff --git a/SU2_CFD/src/meson.build b/SU2_CFD/src/meson.build index b731e0ca0f57..f9420e857e4e 100644 --- a/SU2_CFD/src/meson.build +++ b/SU2_CFD/src/meson.build @@ -1,23 +1,12 @@ -su2_cfd_src = files(['integration_structure.cpp', - 'numerics_adjoint_mean.cpp', - 'transport_model.cpp', - 'numerics_adjoint_turbulent.cpp', +su2_cfd_src = files(['transport_model.cpp', 'fluid_model_pvdw.cpp', - 'integration_time.cpp', 'fluid_model_pig.cpp', 'iteration_structure.cpp', 'fluid_model_inc.cpp', - 'numerics_direct_turbulent.cpp', - 'numerics_direct_transition.cpp', 'definition_structure.cpp', - 'numerics_direct_mean_inc.cpp', 'fluid_model.cpp', - 'numerics_direct_mean.cpp', - 'numerics_direct_heat.cpp', 'fluid_model_ppr.cpp', 'python_wrapper_structure.cpp', - 'numerics_structure.cpp', - 'numerics_template.cpp', 'CMarkerProfileReaderFVM.cpp', 'SU2_CFD.cpp']) @@ -104,14 +93,29 @@ su2_cfd_src += files(['solvers/CAdjEulerSolver.cpp', 'solvers/CTurbSASolver.cpp', 'solvers/CTurbSSTSolver.cpp']) -su2_cfd_src += files(['numerics/elasticity/CFEAElasticity.cpp', +su2_cfd_src += files(['numerics/CNumerics.cpp', + 'numerics/template.cpp', + 'numerics/transition.cpp', + 'numerics/heat.cpp', + 'numerics/flow/convection/roe.cpp', + 'numerics/flow/convection/fds.cpp', + 'numerics/flow/convection/fvs.cpp', + 'numerics/flow/convection/cusp.cpp', + 'numerics/flow/convection/hllc.cpp', + 'numerics/flow/convection/ausm_slau.cpp', + 'numerics/flow/convection/centered.cpp', + 'numerics/flow/flow_diffusion.cpp', + 'numerics/flow/flow_sources.cpp', + 'numerics/continuous_adjoint/adj_convection.cpp', + 'numerics/continuous_adjoint/adj_diffusion.cpp', + 'numerics/continuous_adjoint/adj_sources.cpp', + 'numerics/turbulent/turb_convection.cpp', + 'numerics/turbulent/turb_diffusion.cpp', + 'numerics/turbulent/turb_sources.cpp', + 'numerics/elasticity/CFEAElasticity.cpp', 'numerics/elasticity/CFEALinearElasticity.cpp', - 'numerics/elasticity/CFEAMeshElasticity.cpp', 'numerics/elasticity/CFEANonlinearElasticity.cpp', - 'numerics/elasticity/CFEM_NeoHookean_Comp.cpp', - 'numerics/elasticity/CFEM_Knowles_NearInc.cpp', - 'numerics/elasticity/CFEM_IdealDE.cpp', - 'numerics/elasticity/CFEM_DielectricElastomer.cpp']) + 'numerics/elasticity/nonlinear_models.cpp']) su2_cfd_src += files(['interfaces/CInterface.cpp', 'interfaces/cfd/CConservativeVarsInterface.cpp', @@ -131,6 +135,14 @@ su2_cfd_src += files(['drivers/CDriver.cpp', 'drivers/CDiscAdjSinglezoneDriver.cpp', 'drivers/CDummyDriver.cpp']) +su2_cfd_src += files(['integration/CIntegration.cpp', + 'integration/CSingleGridIntegration.cpp', + 'integration/CMultiGridIntegration.cpp', + 'integration/CStructuralIntegration.cpp', + 'integration/CFEM_DG_Integration.cpp']) + +su2_cfd_src += files(['limiters/CLimiterDetails.cpp']) + if get_option('enable-normal') su2_cfd = executable('SU2_CFD', su2_cfd_src, diff --git a/SU2_CFD/src/numerics_structure.cpp b/SU2_CFD/src/numerics/CNumerics.cpp similarity index 95% rename from SU2_CFD/src/numerics_structure.cpp rename to SU2_CFD/src/numerics/CNumerics.cpp index 2fd88bc0ce87..4b05dcc1fd06 100644 --- a/SU2_CFD/src/numerics_structure.cpp +++ b/SU2_CFD/src/numerics/CNumerics.cpp @@ -1,12 +1,14 @@ /*! - * \file numerics_structure.cpp - * \brief This file contains all the numerical methods. + * \file CNumerics.cpp + * \brief Implementation of the base for all numerics classes. + * Contains methods for common tasks, e.g. compute flux + * Jacobians. * \author F. Palacios, T. Economon * \version 7.0.1 "Blackbird" * * 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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -26,21 +28,18 @@ */ -#include "../include/numerics_structure.hpp" +#include "../../include/numerics/CNumerics.hpp" +#include "../../include/fluid_model.hpp" CNumerics::CNumerics(void) { Normal = NULL; UnitNormal = NULL; UnitNormald = NULL; - - U_n = NULL; - U_nM1 = NULL; - U_nP1 = NULL; - + Proj_Flux_Tensor = NULL; Flux_Tensor = NULL; - + tau = NULL; delta = NULL; delta3 = NULL; @@ -50,32 +49,25 @@ CNumerics::CNumerics(void) { Vector = NULL; - Enthalpy_formation = NULL; - Theta_v = NULL; - l = NULL; m = NULL; - + using_uq = false; } CNumerics::CNumerics(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) { - + const CConfig* config) { + unsigned short iVar, iDim, jDim; - + Normal = NULL; UnitNormal = NULL; UnitNormald = NULL; - - U_n = NULL; - U_nM1 = NULL; - U_nP1 = NULL; - + Proj_Flux_Tensor = NULL; Flux_Tensor = NULL; - + tau = NULL; delta = NULL; delta3 = NULL; @@ -83,23 +75,9 @@ CNumerics::CNumerics(unsigned short val_nDim, unsigned short val_nVar, Diffusion_Coeff_i = NULL; Diffusion_Coeff_j = NULL; - Enthalpy_formation = NULL; - Theta_v = NULL; - l = NULL; m = NULL; - MeanReynoldsStress = NULL; - MeanPerturbedRSM = NULL; - A_ij = NULL; - Eig_Vec = NULL; - New_Eig_Vec = NULL; - newA_ij = NULL; - Corners = NULL; - Eig_Val = NULL; - Barycentric_Coord = NULL; - New_Coord = NULL; - nDim = val_nDim; nVar = val_nVar; Gamma = config->GetGamma(); @@ -144,20 +122,16 @@ CNumerics::CNumerics(unsigned short val_nDim, unsigned short val_nVar, } } - U_n = new su2double [nVar]; - U_nM1 = new su2double [nVar]; - U_nP1 = new su2double [nVar]; - Proj_Flux_Tensor = new su2double [nVar]; turb_ke_i = 0.0; turb_ke_j = 0.0; - + Vector = new su2double[nDim]; - + l = new su2double [nDim]; m = new su2double [nDim]; - + Dissipation_ij = 1.0; /* --- Initializing variables for the UQ methodology --- */ @@ -165,7 +139,7 @@ CNumerics::CNumerics(unsigned short val_nDim, unsigned short val_nVar, if (using_uq){ MeanReynoldsStress = new su2double* [3]; MeanPerturbedRSM = new su2double* [3]; - A_ij = new su2double* [3]; + A_ij = new su2double* [3]; newA_ij = new su2double* [3]; Eig_Vec = new su2double* [3]; New_Eig_Vec = new su2double* [3]; @@ -196,7 +170,7 @@ CNumerics::CNumerics(unsigned short val_nDim, unsigned short val_nVar, Corners[2][0] = 0.5; Corners[2][1] = 0.866025; } - + } CNumerics::~CNumerics(void) { @@ -204,10 +178,6 @@ CNumerics::~CNumerics(void) { if (UnitNormal!= NULL) delete [] UnitNormal; if (UnitNormald!= NULL) delete [] UnitNormald; - if (U_n!= NULL) delete [] U_n; - if (U_nM1!= NULL) delete [] U_nM1; - if (U_nP1!= NULL) delete [] U_nP1; - // visc if (Proj_Flux_Tensor!= NULL) delete [] Proj_Flux_Tensor; @@ -243,9 +213,6 @@ CNumerics::~CNumerics(void) { if (Diffusion_Coeff_j != NULL) delete [] Diffusion_Coeff_j; if (Vector != NULL) delete [] Vector; - if(Enthalpy_formation != NULL) delete [] Enthalpy_formation; - if(Theta_v != NULL) delete [] Theta_v; - if (l != NULL) delete [] l; if (m != NULL) delete [] m; @@ -295,7 +262,7 @@ void CNumerics::GetInviscidFlux(su2double val_density, su2double *val_velocity, Flux_Tensor[4][2] = Flux_Tensor[0][2]*val_enthalpy; } - if (nDim == 2) { + else { Flux_Tensor[0][0] = val_density*val_velocity[0]; Flux_Tensor[1][0] = Flux_Tensor[0][0]*val_velocity[0]+val_pressure; Flux_Tensor[2][0] = Flux_Tensor[0][0]*val_velocity[1]; @@ -314,11 +281,11 @@ void CNumerics::GetInviscidProjFlux(su2double *val_density, su2double *val_enthalpy, su2double *val_normal, su2double *val_Proj_Flux) { - - su2double rhou, rhov, rhow; - + + su2double rhou, rhov, rhow; + if (nDim == 2) { - + rhou = (*val_density)*val_velocity[0]; rhov = (*val_density)*val_velocity[1]; @@ -331,10 +298,10 @@ void CNumerics::GetInviscidProjFlux(su2double *val_density, val_Proj_Flux[1] += rhov*val_velocity[0]*val_normal[1]; val_Proj_Flux[2] += (rhov*val_velocity[1]+(*val_pressure))*val_normal[1]; val_Proj_Flux[3] += rhov*(*val_enthalpy)*val_normal[1]; - - } + + } else { - + rhou = (*val_density)*val_velocity[0]; rhov = (*val_density)*val_velocity[1]; rhow = (*val_density)*val_velocity[2]; @@ -356,7 +323,7 @@ void CNumerics::GetInviscidProjFlux(su2double *val_density, val_Proj_Flux[2] += rhow*val_velocity[1]*val_normal[2]; val_Proj_Flux[3] += (rhow*val_velocity[2]+(*val_pressure))*val_normal[2]; val_Proj_Flux[4] += rhow*(*val_enthalpy)*val_normal[2]; - + } } @@ -369,7 +336,7 @@ void CNumerics::GetInviscidIncProjFlux(su2double *val_density, su2double *val_normal, su2double *val_Proj_Flux) { su2double rhou, rhov, rhow; - + if (nDim == 2) { rhou = (*val_density)*val_velocity[0]; rhov = (*val_density)*val_velocity[1]; @@ -383,14 +350,14 @@ void CNumerics::GetInviscidIncProjFlux(su2double *val_density, rhou = (*val_density)*val_velocity[0]; rhov = (*val_density)*val_velocity[1]; rhow = (*val_density)*val_velocity[2]; - + val_Proj_Flux[0] = rhou*val_normal[0] + rhov*val_normal[1] + rhow*val_normal[2]; val_Proj_Flux[1] = (rhou*val_velocity[0]+(*val_pressure))*val_normal[0] + rhou*val_velocity[1]*val_normal[1] + rhou*val_velocity[2]*val_normal[2]; val_Proj_Flux[2] = rhov*val_velocity[0]*val_normal[0] + (rhov*val_velocity[1]+(*val_pressure))*val_normal[1] + rhov*val_velocity[2]*val_normal[2]; val_Proj_Flux[3] = rhow*val_velocity[0]*val_normal[0] + rhow*val_velocity[1]*val_normal[1] + (rhow*val_velocity[2]+(*val_pressure))*val_normal[2]; val_Proj_Flux[4] = (rhou*val_normal[0] + rhov*val_normal[1] + rhow*val_normal[2])*(*val_enthalpy); } - + } void CNumerics::GetInviscidProjJac(su2double *val_velocity, su2double *val_energy, @@ -399,22 +366,22 @@ void CNumerics::GetInviscidProjJac(su2double *val_velocity, su2double *val_energ AD_BEGIN_PASSIVE unsigned short iDim, jDim; su2double sqvel, proj_vel, phi, a1, a2; - + sqvel = 0.0; proj_vel = 0.0; for (iDim = 0; iDim < nDim; iDim++) { sqvel += val_velocity[iDim]*val_velocity[iDim]; proj_vel += val_velocity[iDim]*val_normal[iDim]; } - + phi = 0.5*Gamma_Minus_One*sqvel; a1 = Gamma*(*val_energy)-phi; a2 = Gamma-1.0; - + val_Proj_Jac_Tensor[0][0] = 0.0; for (iDim = 0; iDim < nDim; iDim++) val_Proj_Jac_Tensor[0][iDim+1] = val_scale*val_normal[iDim]; val_Proj_Jac_Tensor[0][nDim+1] = 0.0; - + for (iDim = 0; iDim < nDim; iDim++) { val_Proj_Jac_Tensor[iDim+1][0] = val_scale*(val_normal[iDim]*phi - val_velocity[iDim]*proj_vel); for (jDim = 0; jDim < nDim; jDim++) @@ -422,7 +389,7 @@ void CNumerics::GetInviscidProjJac(su2double *val_velocity, su2double *val_energ val_Proj_Jac_Tensor[iDim+1][iDim+1] += val_scale*proj_vel; val_Proj_Jac_Tensor[iDim+1][nDim+1] = val_scale*a2*val_normal[iDim]; } - + val_Proj_Jac_Tensor[nDim+1][0] = val_scale*proj_vel*(phi-a1); for (iDim = 0; iDim < nDim; iDim++) val_Proj_Jac_Tensor[nDim+1][iDim+1] = val_scale*(val_normal[iDim]*a1-a2*val_velocity[iDim]*proj_vel); @@ -537,7 +504,9 @@ void CNumerics::GetInviscidIncProjJac(su2double *val_density, su2double *val_vel AD_END_PASSIVE } -void CNumerics::GetPreconditioner(su2double *val_density, su2double *val_velocity, su2double *val_betainc2, su2double *val_cp, su2double *val_temperature, su2double *val_drhodt, su2double **val_Precon) { +void CNumerics::GetPreconditioner(su2double *val_density, su2double *val_velocity, + su2double *val_betainc2, su2double *val_cp, + su2double *val_temperature, su2double *val_drhodt, su2double **val_Precon) { unsigned short iDim, jDim; val_Precon[0][0] = 1.0/(*val_betainc2); @@ -561,7 +530,8 @@ void CNumerics::GetPreconditioner(su2double *val_density, su2double *val_velocit } -void CNumerics::GetPreconditionedProjJac(su2double *val_density, su2double *val_lambda, su2double *val_betainc2, su2double *val_normal, su2double **val_invPrecon_A) { +void CNumerics::GetPreconditionedProjJac(su2double *val_density, su2double *val_lambda, + su2double *val_betainc2, su2double *val_normal, su2double **val_invPrecon_A) { unsigned short iDim, jDim, kDim; val_invPrecon_A[0][0] = val_lambda[nDim]/2.0 + val_lambda[nDim+1]/2.0; @@ -589,105 +559,89 @@ void CNumerics::GetPreconditionedProjJac(su2double *val_density, su2double *val_ for (iDim = 0; iDim < nDim; iDim++) val_invPrecon_A[iDim+1][nDim+1] = 0.0; val_invPrecon_A[nDim+1][nDim+1] = val_lambda[nDim-1]; - -} - -void CNumerics::SetPastSol (su2double *val_u_nM1, su2double *val_u_n, su2double *val_u_nP1) { - unsigned short iVar; - - for (iVar = 0; iVar < nVar; iVar++) { - U_nM1[iVar] = val_u_nM1[iVar]; - U_n[iVar] = val_u_n[iVar]; - U_nP1[iVar] = val_u_nP1[iVar]; - } } -void CNumerics::SetPastVolume (su2double val_volume_nM1, su2double val_volume_n, su2double val_volume_nP1) { - Volume_nM1 = val_volume_nM1; - Volume_n = val_volume_n; - Volume_nP1 = val_volume_nP1; -} - void CNumerics::GetPMatrix(su2double *val_density, su2double *val_velocity, su2double *val_soundspeed, su2double *val_normal, su2double **val_p_tensor) { - + su2double sqvel, rhooc, rhoxc; //su2double c2; - + rhooc = *val_density / *val_soundspeed; rhoxc = *val_density * *val_soundspeed; //c2 = *val_soundspeed * *val_soundspeed; - + if (nDim == 2) { - + sqvel = val_velocity[0]*val_velocity[0]+val_velocity[1]*val_velocity[1]; - + val_p_tensor[0][0] = 1.0; val_p_tensor[0][1]=0.0; val_p_tensor[0][2]=0.5*rhooc; val_p_tensor[0][3]=0.5*rhooc; - + val_p_tensor[1][0]=val_velocity[0]; val_p_tensor[1][1]=*val_density*val_normal[1]; val_p_tensor[1][2]=0.5*(val_velocity[0]*rhooc+val_normal[0]**val_density); val_p_tensor[1][3]=0.5*(val_velocity[0]*rhooc-val_normal[0]**val_density); - + val_p_tensor[2][0]=val_velocity[1]; val_p_tensor[2][1]=-*val_density*val_normal[0]; val_p_tensor[2][2]=0.5*(val_velocity[1]*rhooc+val_normal[1]**val_density); val_p_tensor[2][3]=0.5*(val_velocity[1]*rhooc-val_normal[1]**val_density); - + val_p_tensor[3][0]=0.5*sqvel; val_p_tensor[3][1]=*val_density*val_velocity[0]*val_normal[1]-*val_density*val_velocity[1]*val_normal[0]; val_p_tensor[3][2]=0.5*(0.5*sqvel*rhooc+*val_density*val_velocity[0]*val_normal[0]+*val_density*val_velocity[1]*val_normal[1]+rhoxc/Gamma_Minus_One); val_p_tensor[3][3]=0.5*(0.5*sqvel*rhooc-*val_density*val_velocity[0]*val_normal[0]-*val_density*val_velocity[1]*val_normal[1]+rhoxc/Gamma_Minus_One); - + } else { - + sqvel = val_velocity[0]*val_velocity[0]+val_velocity[1]*val_velocity[1]+val_velocity[2]*val_velocity[2]; - + val_p_tensor[0][0]=val_normal[0]; val_p_tensor[0][1]=val_normal[1]; val_p_tensor[0][2]=val_normal[2]; val_p_tensor[0][3]=0.5*rhooc; val_p_tensor[0][4]=0.5*rhooc; - + val_p_tensor[1][0]=val_velocity[0]*val_normal[0]; val_p_tensor[1][1]=val_velocity[0]*val_normal[1]-*val_density*val_normal[2]; val_p_tensor[1][2]=val_velocity[0]*val_normal[2]+*val_density*val_normal[1]; val_p_tensor[1][3]=0.5*(val_velocity[0]*rhooc+*val_density*val_normal[0]); val_p_tensor[1][4]=0.5*(val_velocity[0]*rhooc-*val_density*val_normal[0]); - + val_p_tensor[2][0]=val_velocity[1]*val_normal[0]+*val_density*val_normal[2]; val_p_tensor[2][1]=val_velocity[1]*val_normal[1]; val_p_tensor[2][2]=val_velocity[1]*val_normal[2]-*val_density*val_normal[0]; val_p_tensor[2][3]=0.5*(val_velocity[1]*rhooc+*val_density*val_normal[1]); val_p_tensor[2][4]=0.5*(val_velocity[1]*rhooc-*val_density*val_normal[1]); - + val_p_tensor[3][0]=val_velocity[2]*val_normal[0]-*val_density*val_normal[1]; val_p_tensor[3][1]=val_velocity[2]*val_normal[1]+*val_density*val_normal[0]; val_p_tensor[3][2]=val_velocity[2]*val_normal[2]; val_p_tensor[3][3]=0.5*(val_velocity[2]*rhooc+*val_density*val_normal[2]); val_p_tensor[3][4]=0.5*(val_velocity[2]*rhooc-*val_density*val_normal[2]); - + val_p_tensor[4][0]=0.5*sqvel*val_normal[0]+*val_density*val_velocity[1]*val_normal[2]-*val_density*val_velocity[2]*val_normal[1]; val_p_tensor[4][1]=0.5*sqvel*val_normal[1]-*val_density*val_velocity[0]*val_normal[2]+*val_density*val_velocity[2]*val_normal[0]; val_p_tensor[4][2]=0.5*sqvel*val_normal[2]+*val_density*val_velocity[0]*val_normal[1]-*val_density*val_velocity[1]*val_normal[0]; val_p_tensor[4][3]=0.5*(0.5*sqvel*rhooc+*val_density*(val_velocity[0]*val_normal[0]+val_velocity[1]*val_normal[1]+val_velocity[2]*val_normal[2])+rhoxc/Gamma_Minus_One); val_p_tensor[4][4]=0.5*(0.5*sqvel*rhooc-*val_density*(val_velocity[0]*val_normal[0]+val_velocity[1]*val_normal[1]+val_velocity[2]*val_normal[2])+rhoxc/Gamma_Minus_One); - + } - + } -void CNumerics::GetPMatrix(su2double *val_density, su2double *val_velocity, - su2double *val_soundspeed, su2double *val_enthalpy, su2double *val_chi, su2double *val_kappa, su2double *val_normal, su2double **val_p_tensor) { +void CNumerics::GetPMatrix(su2double *val_density, su2double *val_velocity, su2double *val_soundspeed, + su2double *val_enthalpy, su2double *val_chi, su2double *val_kappa, + su2double *val_normal, su2double **val_p_tensor) { su2double sqvel, rhooc, zeta; //su2double rhoxc, c2; - + rhooc = *val_density / *val_soundspeed; //rhoxc = *val_density * *val_soundspeed; //c2 = *val_soundspeed * *val_soundspeed; @@ -754,8 +708,9 @@ void CNumerics::GetPMatrix(su2double *val_density, su2double *val_velocity, } void CNumerics::GetPMatrix_inv(su2double *val_density, su2double *val_velocity, - su2double *val_soundspeed, su2double *val_normal, su2double **val_invp_tensor) { - + su2double *val_soundspeed, su2double *val_normal, + su2double **val_invp_tensor) { + su2double rhoxc, c2, gm1, k0orho, k1orho, gm1_o_c2, gm1_o_rhoxc, sqvel; rhoxc = *val_density * *val_soundspeed; @@ -767,7 +722,7 @@ void CNumerics::GetPMatrix_inv(su2double *val_density, su2double *val_velocity, gm1_o_rhoxc = gm1/rhoxc; if (nDim == 3) { - + sqvel = val_velocity[0]*val_velocity[0]+val_velocity[1]*val_velocity[1]+val_velocity[2]*val_velocity[2]; val_invp_tensor[0][0]=val_normal[0]-val_normal[2]*val_velocity[1] / *val_density+val_normal[1]*val_velocity[2] / *val_density-val_normal[0]*0.5*gm1*sqvel/c2; @@ -799,10 +754,10 @@ void CNumerics::GetPMatrix_inv(su2double *val_density, su2double *val_velocity, val_invp_tensor[4][2]=-val_normal[1] / *val_density-gm1*val_velocity[1]/rhoxc; val_invp_tensor[4][3]=-val_normal[2] / *val_density-gm1*val_velocity[2]/rhoxc; val_invp_tensor[4][4]=Gamma_Minus_One/rhoxc; - + } - if (nDim == 2) { - + else { + sqvel = val_velocity[0]*val_velocity[0]+val_velocity[1]*val_velocity[1]; val_invp_tensor[0][0] = 1.0-0.5*gm1_o_c2*sqvel; @@ -824,12 +779,13 @@ void CNumerics::GetPMatrix_inv(su2double *val_density, su2double *val_velocity, val_invp_tensor[3][1]=-k0orho-gm1_o_rhoxc*val_velocity[0]; val_invp_tensor[3][2]=-k1orho-gm1_o_rhoxc*val_velocity[1]; val_invp_tensor[3][3]=gm1_o_rhoxc; - + } } -void CNumerics::GetPMatrix_inv(su2double **val_invp_tensor, su2double *val_density, su2double *val_velocity, - su2double *val_soundspeed, su2double *val_chi, su2double *val_kappa, su2double *val_normal) { +void CNumerics::GetPMatrix_inv(su2double **val_invp_tensor, su2double *val_density, + su2double *val_velocity, su2double *val_soundspeed, + su2double *val_chi, su2double *val_kappa, su2double *val_normal) { su2double rhoxc, c2, k0orho, k1orho, sqvel, k_o_c2, k_o_rhoxc, dp_drho; @@ -840,7 +796,6 @@ void CNumerics::GetPMatrix_inv(su2double **val_invp_tensor, su2double *val_densi k_o_c2 = (*val_kappa)/c2; k_o_rhoxc = (*val_kappa)/rhoxc; - if (nDim == 3) { sqvel = val_velocity[0]*val_velocity[0]+val_velocity[1]*val_velocity[1]+val_velocity[2]*val_velocity[2]; dp_drho = *val_chi + 0.5*sqvel*(*val_kappa); @@ -875,7 +830,7 @@ void CNumerics::GetPMatrix_inv(su2double **val_invp_tensor, su2double *val_densi val_invp_tensor[4][3]=-val_normal[2] / *val_density- val_velocity[2]*k_o_rhoxc; val_invp_tensor[4][4]= k_o_rhoxc; } - if (nDim == 2) { + else { sqvel = val_velocity[0]*val_velocity[0]+val_velocity[1]*val_velocity[1]; dp_drho = *val_chi + 0.5*sqvel*(*val_kappa); @@ -971,7 +926,8 @@ void CNumerics::GetinvRinvPe(su2double Beta2, su2double val_enthalpy, } -void CNumerics::GetRMatrix(su2double val_pressure, su2double val_soundspeed, su2double val_density, su2double* val_velocity, su2double **R_Matrix) { +void CNumerics::GetRMatrix(su2double val_pressure, su2double val_soundspeed, su2double val_density, + su2double* val_velocity, su2double **R_Matrix) { su2double sqvel; //su2double factor = 1.0/(val_soundspeed*val_soundspeed*1); @@ -1046,6 +1002,7 @@ void CNumerics::GetRMatrix(su2double val_soundspeed, su2double val_density, su2d su2double cc, rhoc; cc = val_soundspeed*val_soundspeed; rhoc = val_density*val_soundspeed; + if (nDim == 2) { R_Matrix[0][0] = -1.0/cc; R_Matrix[0][1] = 0.0; @@ -1100,7 +1057,7 @@ void CNumerics::GetRMatrix(su2double val_soundspeed, su2double val_density, su2d R_Matrix[4][3] = 0.5; R_Matrix[4][4] = 0.5; -} + } } @@ -1181,23 +1138,23 @@ void CNumerics::ComputeResJacobianGiles(CFluidModel *FluidModel, su2double press dsdrho_P = FluidModel->Getdsdrho_P(); dsdP_rho = FluidModel->GetdsdP_rho(); - if (nDim == 2){ + if (nDim == 2) { R_c[0][0] = -1/cc*dsdrho_P; //a11 - R_c[0][1] = 0.0; //a12 - R_c[0][2] = 0.5/cc*dsdrho_P + 0.5*dsdP_rho; //a13 + R_c[0][1] = 0.0; //a12 + R_c[0][2] = 0.5/cc*dsdrho_P + 0.5*dsdP_rho; //a13 - R_c[1][0] = 0.0; //a21 + R_c[1][0] = 0.0; //a21 R_c[1][1] = 1/rhoc; //a22 - R_c[1][2] = -0.5/rhoc*tan(alphaInBC); //a23 + R_c[1][2] = -0.5/rhoc*tan(alphaInBC); //a23 - R_c[2][0] = -1/cc*dhdrho_P; //a31 - R_c[2][1] = turboVel[1]/rhoc; //a32 + R_c[2][0] = -1/cc*dhdrho_P; //a31 + R_c[2][1] = turboVel[1]/rhoc; //a32 R_c[2][2] = 0.5/cc*dhdrho_P + 0.5*turboVel[0]/rhoc + 0.5*dhdP_rho; //a33 InvMatrix3D(R_c, R_c_inv); } - else{ + else { R_c[0][0] = -1/cc*dsdrho_P; //a11 R_c[0][1] = 0.0; //a12 R_c[0][2] = 0.0; //a13 @@ -1288,7 +1245,7 @@ void CNumerics::GetCharJump(su2double val_soundspeed, su2double val_density, su2 if (nDim == 2) { delta_char[0] = -cc*delta_prim[0] + delta_prim[3]; delta_char[1] = rhoc*delta_prim[2]; - delta_char[2] = rhoc*delta_prim[1] + delta_prim[3]; ; + delta_char[2] = rhoc*delta_prim[1] + delta_prim[3]; ; delta_char[3] = -rhoc*delta_prim[1] + delta_prim[3]; }else { delta_char[0] = -cc*delta_prim[0] + delta_prim[4]; @@ -1299,8 +1256,8 @@ void CNumerics::GetCharJump(su2double val_soundspeed, su2double val_density, su2 } } -void CNumerics::GetPrecondJacobian(su2double Beta2, su2double r_hat, su2double s_hat, su2double t_hat, su2double rB2a2, su2double* Lambda, su2double *val_normal, - su2double **val_absPeJac) { +void CNumerics::GetPrecondJacobian(su2double Beta2, su2double r_hat, su2double s_hat, su2double t_hat, + su2double rB2a2, su2double* Lambda, su2double *val_normal, su2double **val_absPeJac) { su2double lam1, lam2, lam3, lam4; lam1 = Lambda[0]; lam2 = Lambda[1]; lam3 = Lambda[2]; lam4 = Lambda[3]; @@ -1380,8 +1337,7 @@ void CNumerics::GetJacInviscidLambda_fabs(su2double *val_velocity, su2double val val_Lambda_Vector[3] = fabs(ProjVelocity + val_soundspeed); val_Lambda_Vector[4] = fabs(ProjVelocity - val_soundspeed); } - - if (nDim == 2) { + else { val_Lambda_Vector[0] = fabs(ProjVelocity); val_Lambda_Vector[1] = fabs(ProjVelocity); val_Lambda_Vector[2] = fabs(ProjVelocity + val_soundspeed); @@ -1396,7 +1352,7 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j su2double dPhiE_dn, su2double *Normal, su2double *Edge_Vector, su2double dist_ij_2, su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, bool implicit) { - + su2double Sigma_xx, Sigma_yy, Sigma_zz, Sigma_xy, Sigma_xz, Sigma_yz, Sigma_xx5, Sigma_yy5, Sigma_zz5, Sigma_xy5, Sigma_xz5, Sigma_yz5, Sigma_5, eta_xx, eta_yy, eta_zz, eta_xy, eta_xz, eta_yz; @@ -1405,11 +1361,11 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j su2double dSigmaxx_phi3, dSigmayy_phi3, dSigmazz_phi3, dSigmaxy_phi3, dSigmaxz_phi3, dSigmayz_phi3; su2double dSigma5_psi5; unsigned short iVar, jVar; - + if (nDim == 3) { - + /*--- Residual at iPoint ---*/ - + Sigma_xx = ViscDens_i * (FOUR3 * Mean_GradPhi[0][0] - TWO3 * Mean_GradPhi[1][1] - TWO3 * Mean_GradPhi[2][2]); Sigma_yy = ViscDens_i * (-TWO3 * Mean_GradPhi[0][0] + FOUR3 * Mean_GradPhi[1][1] - TWO3 * Mean_GradPhi[2][2]); Sigma_zz = ViscDens_i * (-TWO3 * Mean_GradPhi[0][0] - TWO3 * Mean_GradPhi[1][1] + FOUR3 * Mean_GradPhi[2][2]); @@ -1425,22 +1381,22 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j Sigma_5 = XiDens_i * dPhiE_dn; eta_xx = Sigma_xx + Sigma_xx5; eta_yy = Sigma_yy + Sigma_yy5; eta_zz = Sigma_zz + Sigma_zz5; eta_xy = Sigma_xy + Sigma_xy5; eta_xz = Sigma_xz + Sigma_xz5; eta_yz = Sigma_yz + Sigma_yz5; - + val_residual_i[0] = - (Velocity_i[0] * Normal[0] * eta_xx + Velocity_i[1] * Normal[1] * eta_yy + Velocity_i[2] * Normal[2] * eta_zz + (Velocity_i[0] * Normal[1] + Velocity_i[1] * Normal[0]) * eta_xy + (Velocity_i[0] * Normal[2] + Velocity_i[2] * Normal[0]) * eta_xz + (Velocity_i[2] * Normal[1] + Velocity_i[1] * Normal[2]) * eta_yz - (sq_vel_i - Pressure_i/(Density_i*Gamma_Minus_One)) * Sigma_5); - + val_residual_i[1] = (eta_xx * Normal[0] + eta_xy * Normal[1] + eta_xz * Normal[2] - Velocity_i[0] * Sigma_5); val_residual_i[2] = (eta_xy * Normal[0] + eta_yy * Normal[1] + eta_yz * Normal[2] - Velocity_i[1] * Sigma_5); val_residual_i[3] = (eta_xz * Normal[0] + eta_yz * Normal[1] + eta_zz * Normal[2] - Velocity_i[2] * Sigma_5); val_residual_i[4] = (Sigma_5); - + /*--- Computation of the Jacobians at Point i---*/ - + if (implicit) { - + dSigmaxx_phi1 = -FOUR3 * ViscDens_i * Edge_Vector[0]/dist_ij_2; dSigmaxx_phi2 = TWO3 * ViscDens_i * Edge_Vector[1]/dist_ij_2; dSigmaxx_phi3 = TWO3 * ViscDens_i * Edge_Vector[2]/dist_ij_2; @@ -1459,7 +1415,7 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j dSigmayz_phi1 = 0; dSigmayz_phi2 = -ViscDens_i * Edge_Vector[2]/dist_ij_2; dSigmayz_phi3 = -ViscDens_i * Edge_Vector[1]/dist_ij_2; - + // dSigmaxx5_psi5 = -ViscDens_i * ( FOUR3*Velocity_i[0]*Edge_Vector[0] - TWO3*Velocity_i[1]*Edge_Vector[1] - TWO3*Velocity_i[2]*Edge_Vector[2])/dist_ij_2; // dSigmayy5_psi5 = -ViscDens_i * (- TWO3*Velocity_i[0]*Edge_Vector[0] + FOUR3*Velocity_i[1]*Edge_Vector[1] - TWO3*Velocity_i[2]*Edge_Vector[2])/dist_ij_2; // dSigmazz5_psi5 = -ViscDens_i * (- TWO3*Velocity_i[0]*Edge_Vector[0] - TWO3*Velocity_i[1]*Edge_Vector[1] + FOUR3*Velocity_i[2]*Edge_Vector[2])/dist_ij_2; @@ -1467,7 +1423,7 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j // dSigmaxz5_psi5 = -ViscDens_i * ( Velocity_i[0]*Edge_Vector[2] + Velocity_i[2]*Edge_Vector[0] )/dist_ij_2; // dSigmayz5_psi5 = -ViscDens_i * ( Velocity_i[1]*Edge_Vector[2] + Velocity_i[2]*Edge_Vector[1] )/dist_ij_2; dSigma5_psi5 = -XiDens_i * ( Edge_Vector[0]*Normal[0] + Edge_Vector[1]*Normal[1] + Edge_Vector[2]*Normal[2] )/dist_ij_2; - + val_Jacobian_ii[0][0] = 0; val_Jacobian_ii[0][1] = -( Velocity_i[0]*Normal[0]*dSigmaxx_phi1 + Velocity_i[1]*Normal[1]*dSigmayy_phi1 + Velocity_i[2]*Normal[2]*dSigmazz_phi1 + (Velocity_i[0]*Normal[1] + Velocity_i[1]*Normal[0])*dSigmaxy_phi1 @@ -1482,38 +1438,38 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j + (Velocity_i[0]*Normal[2] + Velocity_i[2]*Normal[0])*dSigmaxz_phi3 + (Velocity_i[2]*Normal[1] + Velocity_i[1]*Normal[2])*dSigmayz_phi3 ); val_Jacobian_ii[0][4] = (sq_vel_i - Pressure_i/(Density_i*Gamma_Minus_One)) * dSigma5_psi5; - + val_Jacobian_ii[1][0] = 0; val_Jacobian_ii[1][1] = Normal[0]*dSigmaxx_phi1 + Normal[1]*dSigmaxy_phi1 + Normal[2]*dSigmaxz_phi1; val_Jacobian_ii[1][2] = Normal[0]*dSigmaxx_phi2 + Normal[1]*dSigmaxy_phi2 + Normal[2]*dSigmaxz_phi2; val_Jacobian_ii[1][3] = Normal[0]*dSigmaxx_phi3 + Normal[1]*dSigmaxy_phi3 + Normal[2]*dSigmaxz_phi3; val_Jacobian_ii[1][4] = -Velocity_i[0]*dSigma5_psi5; - + val_Jacobian_ii[2][0] = 0; val_Jacobian_ii[2][1] = Normal[0]*dSigmaxy_phi1 + Normal[1]*dSigmayy_phi1 + Normal[2]*dSigmayz_phi1; val_Jacobian_ii[2][2] = Normal[0]*dSigmaxy_phi2 + Normal[1]*dSigmayy_phi2 + Normal[2]*dSigmayz_phi2; val_Jacobian_ii[2][3] = Normal[0]*dSigmaxy_phi3 + Normal[1]*dSigmayy_phi3 + Normal[2]*dSigmayz_phi3; val_Jacobian_ii[2][4] = -Velocity_i[1]*dSigma5_psi5; - + val_Jacobian_ii[3][0] = 0; val_Jacobian_ii[3][1] = Normal[0]*dSigmaxz_phi1 + Normal[1]*dSigmayz_phi1 + Normal[2]*dSigmazz_phi1; val_Jacobian_ii[3][2] = Normal[0]*dSigmaxz_phi2 + Normal[1]*dSigmayz_phi2 + Normal[2]*dSigmazz_phi2; val_Jacobian_ii[3][3] = Normal[0]*dSigmaxz_phi3 + Normal[1]*dSigmayz_phi3 + Normal[2]*dSigmazz_phi3; val_Jacobian_ii[3][4] = -Velocity_i[2]*dSigma5_psi5; - + val_Jacobian_ii[4][0] = 0; val_Jacobian_ii[4][1] = 0; val_Jacobian_ii[4][2] = 0; val_Jacobian_ii[4][3] = 0; val_Jacobian_ii[4][4] = dSigma5_psi5; - + for (iVar = 0; iVar < nVar; iVar++) for (jVar = 0; jVar < nVar; jVar++) val_Jacobian_ij[iVar][jVar] = -val_Jacobian_ii[iVar][jVar]; } - + /*--- Residual at jPoint ---*/ - + Sigma_xx = ViscDens_j * (FOUR3 * Mean_GradPhi[0][0] - TWO3 * Mean_GradPhi[1][1] - TWO3 * Mean_GradPhi[2][2]); Sigma_yy = ViscDens_j * (-TWO3 * Mean_GradPhi[0][0] + FOUR3 * Mean_GradPhi[1][1] - TWO3 * Mean_GradPhi[2][2]); Sigma_zz = ViscDens_j * (-TWO3 * Mean_GradPhi[0][0] - TWO3 * Mean_GradPhi[1][1] + FOUR3 * Mean_GradPhi[2][2]); @@ -1529,7 +1485,7 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j Sigma_5 = XiDens_j * dPhiE_dn; eta_xx = Sigma_xx + Sigma_xx5; eta_yy = Sigma_yy + Sigma_yy5; eta_zz = Sigma_zz + Sigma_zz5; eta_xy = Sigma_xy + Sigma_xy5; eta_xz = Sigma_xz + Sigma_xz5; eta_yz = Sigma_yz + Sigma_yz5; - + val_residual_j[0] = - (Velocity_j[0] * Normal[0] * eta_xx + Velocity_j[1] * Normal[1] * eta_yy + Velocity_j[2] * Normal[2] * eta_zz + (Velocity_j[0] * Normal[1] + Velocity_j[1] * Normal[0]) * eta_xy + (Velocity_j[0] * Normal[2] + Velocity_j[2] * Normal[0]) * eta_xz @@ -1539,11 +1495,11 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j val_residual_j[2] = (eta_xy * Normal[0] + eta_yy * Normal[1] + eta_yz * Normal[2] - Velocity_j[1] * Sigma_5); val_residual_j[3] = (eta_xz * Normal[0] + eta_yz * Normal[1] + eta_zz * Normal[2] - Velocity_j[2] * Sigma_5); val_residual_j[4] = (Sigma_5); - + /*--- Computation of the Jacobians at Point j---*/ - + if (implicit) { - + dSigmaxx_phi1 = FOUR3 * ViscDens_j * Edge_Vector[0]/dist_ij_2; dSigmaxx_phi2 = -TWO3 * ViscDens_j * Edge_Vector[1]/dist_ij_2; dSigmaxx_phi3 = -TWO3 * ViscDens_j * Edge_Vector[2]/dist_ij_2; @@ -1562,7 +1518,7 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j dSigmayz_phi1 = 0; dSigmayz_phi2 = ViscDens_j * Edge_Vector[2]/dist_ij_2; dSigmayz_phi3 = ViscDens_j * Edge_Vector[1]/dist_ij_2; - + // dSigmaxx5_psi5 = ViscDens_j * ( FOUR3*Velocity_j[0]*Edge_Vector[0] - TWO3*Velocity_j[1]*Edge_Vector[1] - TWO3*Velocity_j[2]*Edge_Vector[2])/dist_ij_2; // dSigmayy5_psi5 = ViscDens_j * (- TWO3*Velocity_j[0]*Edge_Vector[0] + FOUR3*Velocity_j[1]*Edge_Vector[1] - TWO3*Velocity_j[2]*Edge_Vector[2])/dist_ij_2; // dSigmazz5_psi5 = ViscDens_j * (- TWO3*Velocity_j[0]*Edge_Vector[0] - TWO3*Velocity_j[1]*Edge_Vector[1] + FOUR3*Velocity_j[2]*Edge_Vector[2])/dist_ij_2; @@ -1570,7 +1526,7 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j // dSigmaxz5_psi5 = ViscDens_j * ( Velocity_j[0]*Edge_Vector[2] + Velocity_j[2]*Edge_Vector[0] )/dist_ij_2; // dSigmayz5_psi5 = ViscDens_j * ( Velocity_j[1]*Edge_Vector[2] + Velocity_j[2]*Edge_Vector[1] )/dist_ij_2; dSigma5_psi5 = XiDens_j * ( Edge_Vector[0]*Normal[0] + Edge_Vector[1]*Normal[1] + Edge_Vector[2]*Normal[2] )/dist_ij_2; - + val_Jacobian_jj[0][0] = 0; val_Jacobian_jj[0][1] = -( Velocity_j[0]*Normal[0]*dSigmaxx_phi1 + Velocity_j[1]*Normal[1]*dSigmayy_phi1 + Velocity_j[2]*Normal[2]*dSigmazz_phi1 + (Velocity_j[0]*Normal[1] + Velocity_j[1]*Normal[0])*dSigmaxy_phi1 @@ -1585,41 +1541,41 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j + (Velocity_j[0]*Normal[2] + Velocity_j[2]*Normal[0])*dSigmaxz_phi3 + (Velocity_j[2]*Normal[1] + Velocity_j[1]*Normal[2])*dSigmayz_phi3 ); val_Jacobian_jj[0][4] = (sq_vel_j - Pressure_j/(Density_j*Gamma_Minus_One)) * dSigma5_psi5; - + val_Jacobian_jj[1][0] = 0; val_Jacobian_jj[1][1] = Normal[0]*dSigmaxx_phi1 + Normal[1]*dSigmaxy_phi1 + Normal[2]*dSigmaxz_phi1; val_Jacobian_jj[1][2] = Normal[0]*dSigmaxx_phi2 + Normal[1]*dSigmaxy_phi2 + Normal[2]*dSigmaxz_phi2; val_Jacobian_jj[1][3] = Normal[0]*dSigmaxx_phi3 + Normal[1]*dSigmaxy_phi3 + Normal[2]*dSigmaxz_phi3; val_Jacobian_jj[1][4] = -Velocity_j[0]*dSigma5_psi5; - + val_Jacobian_jj[2][0] = 0; val_Jacobian_jj[2][1] = Normal[0]*dSigmaxy_phi1 + Normal[1]*dSigmayy_phi1 + Normal[2]*dSigmayz_phi1; val_Jacobian_jj[2][2] = Normal[0]*dSigmaxy_phi2 + Normal[1]*dSigmayy_phi2 + Normal[2]*dSigmayz_phi2; val_Jacobian_jj[2][3] = Normal[0]*dSigmaxy_phi3 + Normal[1]*dSigmayy_phi3 + Normal[2]*dSigmayz_phi3; val_Jacobian_jj[2][4] = -Velocity_j[1]*dSigma5_psi5; - + val_Jacobian_jj[3][0] = 0; val_Jacobian_jj[3][1] = Normal[0]*dSigmaxz_phi1 + Normal[1]*dSigmayz_phi1 + Normal[2]*dSigmazz_phi1; val_Jacobian_jj[3][2] = Normal[0]*dSigmaxz_phi2 + Normal[1]*dSigmayz_phi2 + Normal[2]*dSigmazz_phi2; val_Jacobian_jj[3][3] = Normal[0]*dSigmaxz_phi3 + Normal[1]*dSigmayz_phi3 + Normal[2]*dSigmazz_phi3; val_Jacobian_jj[3][4] = -Velocity_j[2]*dSigma5_psi5; - + val_Jacobian_jj[4][0] = 0; val_Jacobian_jj[4][1] = 0; val_Jacobian_jj[4][2] = 0; val_Jacobian_jj[4][3] = 0; val_Jacobian_jj[4][4] = dSigma5_psi5; - + for (iVar = 0; iVar < nVar; iVar++) for (jVar = 0; jVar < nVar; jVar++) val_Jacobian_ji[iVar][jVar] = -val_Jacobian_jj[iVar][jVar]; } - + } else if (nDim == 2) { - + /*--- Residual at iPoint ---*/ - + Sigma_xx = ViscDens_i * (FOUR3 * Mean_GradPhi[0][0] - TWO3 * Mean_GradPhi[1][1]); Sigma_yy = ViscDens_i * (-TWO3 * Mean_GradPhi[0][0] + FOUR3 * Mean_GradPhi[1][1]); Sigma_xy = ViscDens_i * (Mean_GradPhi[1][0] + Mean_GradPhi[0][1]); @@ -1628,58 +1584,58 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j Sigma_xy5 = ViscDens_i * (Velocity_i[0] * Mean_GradPsiE[1] + Velocity_i[1] * Mean_GradPsiE[0]); Sigma_5 = XiDens_i * dPhiE_dn; eta_xx = Sigma_xx + Sigma_xx5; eta_yy = Sigma_yy + Sigma_yy5; eta_xy = Sigma_xy + Sigma_xy5; - + val_residual_i[0] = - (Velocity_i[0] * Normal[0] * eta_xx + Velocity_i[1] * Normal[1] * eta_yy + (Velocity_i[0] * Normal[1] + Velocity_i[1] * Normal[0]) * eta_xy - (sq_vel_i - Pressure_i/(Density_i*Gamma_Minus_One)) * Sigma_5); val_residual_i[1] = (eta_xx * Normal[0] + eta_xy * Normal[1] - Velocity_i[0] * Sigma_5); val_residual_i[2] = (eta_xy * Normal[0] + eta_yy * Normal[1] - Velocity_i[1] * Sigma_5); val_residual_i[3] = (Sigma_5); - + /*--- Computation of the Jacobians at Point i---*/ - + if (implicit) { - + dSigmaxx_phi1 = -FOUR3 * ViscDens_i * Edge_Vector[0]/dist_ij_2; dSigmaxx_phi2 = TWO3 * ViscDens_i * Edge_Vector[1]/dist_ij_2; dSigmayy_phi1 = TWO3 * ViscDens_i * Edge_Vector[0]/dist_ij_2; dSigmayy_phi2 = -FOUR3 * ViscDens_i * Edge_Vector[1]/dist_ij_2; dSigmaxy_phi1 = -ViscDens_i * Edge_Vector[1]/dist_ij_2; dSigmaxy_phi2 = -ViscDens_i * Edge_Vector[0]/dist_ij_2; - + // dSigmaxx5_psi5 = -ViscDens_i * ( FOUR3*Velocity_i[0]*Edge_Vector[0] - TWO3*Velocity_i[1]*Edge_Vector[1] )/dist_ij_2; // dSigmayy5_psi5 = -ViscDens_i * (- TWO3*Velocity_i[0]*Edge_Vector[0] + FOUR3*Velocity_i[1]*Edge_Vector[1] )/dist_ij_2; // dSigmaxy5_psi5 = -ViscDens_i * ( Velocity_i[0]*Edge_Vector[1] + Velocity_i[1]*Edge_Vector[0] )/dist_ij_2; dSigma5_psi5 = -XiDens_i * ( Edge_Vector[0]*Normal[0] + Edge_Vector[1]*Normal[1] )/dist_ij_2; - + val_Jacobian_ii[0][0] = 0; - + val_Jacobian_ii[0][1] = -( Velocity_i[0]*Normal[0]*dSigmaxx_phi1 + Velocity_i[1]*Normal[1]*dSigmayy_phi1 + (Velocity_i[0]*Normal[1] + Velocity_i[1]*Normal[0])*dSigmaxy_phi1 ); val_Jacobian_ii[0][2] = -( Velocity_i[0]*Normal[0]*dSigmaxx_phi2 + Velocity_i[1]*Normal[1]*dSigmayy_phi2 + (Velocity_i[0]*Normal[1] + Velocity_i[1]*Normal[0])*dSigmaxy_phi2 ); val_Jacobian_ii[0][3] = (sq_vel_i - Pressure_i/(Density_i*Gamma_Minus_One)) * dSigma5_psi5; - + val_Jacobian_ii[1][0] = 0; val_Jacobian_ii[1][1] = Normal[0]*dSigmaxx_phi1 + Normal[1]*dSigmaxy_phi1; val_Jacobian_ii[1][2] = Normal[0]*dSigmaxx_phi2 + Normal[1]*dSigmaxy_phi2; val_Jacobian_ii[1][3] = -Velocity_i[0]*dSigma5_psi5; - + val_Jacobian_ii[2][0] = 0; val_Jacobian_ii[2][1] = Normal[0]*dSigmaxy_phi1 + Normal[1]*dSigmayy_phi1; val_Jacobian_ii[2][2] = Normal[0]*dSigmaxy_phi2 + Normal[1]*dSigmayy_phi2; val_Jacobian_ii[2][3] = -Velocity_i[1]*dSigma5_psi5; - + val_Jacobian_ii[3][0] = 0; val_Jacobian_ii[3][1] = 0; val_Jacobian_ii[3][2] = 0; val_Jacobian_ii[3][3] = dSigma5_psi5; - + for (iVar = 0; iVar < nVar; iVar++) for (jVar = 0; jVar < nVar; jVar++) val_Jacobian_ij[iVar][jVar] = -val_Jacobian_ii[iVar][jVar]; } - + /*--- Residual at jPoint ---*/ Sigma_xx = ViscDens_j * (FOUR3 * Mean_GradPhi[0][0] - TWO3 * Mean_GradPhi[1][1]); Sigma_yy = ViscDens_j * (-TWO3 * Mean_GradPhi[0][0] + FOUR3 * Mean_GradPhi[1][1]); @@ -1689,14 +1645,14 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j Sigma_xy5 = ViscDens_j * (Velocity_j[0] * Mean_GradPsiE[1] + Velocity_j[1] * Mean_GradPsiE[0]); Sigma_5 = XiDens_j * dPhiE_dn; eta_xx = Sigma_xx + Sigma_xx5; eta_yy = Sigma_yy + Sigma_yy5; eta_xy = Sigma_xy + Sigma_xy5; - + val_residual_j[0] = - (Velocity_j[0] * Normal[0] * eta_xx + Velocity_j[1] * Normal[1] * eta_yy + (Velocity_j[0] * Normal[1] + Velocity_j[1] * Normal[0]) * eta_xy - (sq_vel_j - Pressure_j/(Density_j*Gamma_Minus_One)) * Sigma_5); val_residual_j[1] = (eta_xx * Normal[0] + eta_xy * Normal[1] - Velocity_j[0] * Sigma_5); val_residual_j[2] = (eta_xy * Normal[0] + eta_yy * Normal[1] - Velocity_j[1] * Sigma_5); val_residual_j[3] = (Sigma_5); - + /*--- Computation of the Jacobians at Point j---*/ if (implicit) { dSigmaxx_phi1 = FOUR3 * ViscDens_j * Edge_Vector[0]/dist_ij_2; @@ -1705,40 +1661,40 @@ void CNumerics::GetAdjViscousFlux_Jac(su2double Pressure_i, su2double Pressure_j dSigmayy_phi2 = FOUR3 * ViscDens_j * Edge_Vector[1]/dist_ij_2; dSigmaxy_phi1 = ViscDens_j * Edge_Vector[1]/dist_ij_2; dSigmaxy_phi2 = ViscDens_j * Edge_Vector[0]/dist_ij_2; - + // dSigmaxx5_psi5 = ViscDens_j * ( FOUR3*Velocity_j[0]*Edge_Vector[0] - TWO3*Velocity_j[1]*Edge_Vector[1] )/dist_ij_2; // dSigmayy5_psi5 = ViscDens_j * (- TWO3*Velocity_j[0]*Edge_Vector[0] + FOUR3*Velocity_j[1]*Edge_Vector[1] )/dist_ij_2; // dSigmaxy5_psi5 = ViscDens_j * ( Velocity_j[0]*Edge_Vector[1] + Velocity_j[1]*Edge_Vector[0] )/dist_ij_2; dSigma5_psi5 = XiDens_j * ( Edge_Vector[0]*Normal[0] + Edge_Vector[1]*Normal[1] )/dist_ij_2; - + val_Jacobian_jj[0][0] = 0; val_Jacobian_jj[0][1] = -( Velocity_j[0]*Normal[0]*dSigmaxx_phi1 + Velocity_j[1]*Normal[1]*dSigmayy_phi1 + (Velocity_j[0]*Normal[1] + Velocity_j[1]*Normal[0])*dSigmaxy_phi1 ); val_Jacobian_jj[0][2] = -( Velocity_j[0]*Normal[0]*dSigmaxx_phi2 + Velocity_j[1]*Normal[1]*dSigmayy_phi2 + (Velocity_j[0]*Normal[1] + Velocity_j[1]*Normal[0])*dSigmaxy_phi2 ); val_Jacobian_jj[0][3] = (sq_vel_j - Pressure_j/(Density_j*Gamma_Minus_One)) * dSigma5_psi5; - + val_Jacobian_jj[1][0] = 0; val_Jacobian_jj[1][1] = Normal[0]*dSigmaxx_phi1 + Normal[1]*dSigmaxy_phi1; val_Jacobian_jj[1][2] = Normal[0]*dSigmaxx_phi2 + Normal[1]*dSigmaxy_phi2; val_Jacobian_jj[1][3] = -Velocity_j[0]*dSigma5_psi5; - + val_Jacobian_jj[2][0] = 0; val_Jacobian_jj[2][1] = Normal[0]*dSigmaxy_phi1 + Normal[1]*dSigmayy_phi1; val_Jacobian_jj[2][2] = Normal[0]*dSigmaxy_phi2 + Normal[1]*dSigmayy_phi2; val_Jacobian_jj[2][3] = -Velocity_j[1]*dSigma5_psi5; - + val_Jacobian_jj[3][0] = 0; val_Jacobian_jj[3][1] = 0; val_Jacobian_jj[3][2] = 0; val_Jacobian_jj[3][3] = dSigma5_psi5; - + for (iVar = 0; iVar < nVar; iVar++) for (jVar = 0; jVar < nVar; jVar++) val_Jacobian_ji[iVar][jVar] = -val_Jacobian_jj[iVar][jVar]; } } - + } void CNumerics::GetPrimitive2Conservative (su2double *val_Mean_PrimVar, su2double *val_Mean_SecVar, su2double **val_Jac_PC) { @@ -1834,24 +1790,24 @@ void CNumerics::GetPrimitive2Conservative (su2double *val_Mean_PrimVar, su2doubl void CNumerics::CreateBasis(su2double *val_Normal) { unsigned short iDim; su2double modm, modl; - + /*--- Define l as a vector in the plane normal to the supplied vector ---*/ l[0] = 0.0; l[1] = -val_Normal[2]; l[2] = val_Normal[1]; - + /*--- Check for the zero vector and re-assign if needed ---*/ if (l[0] == 0.0 && l[1] == 0.0 && l[2] == 0.0) { l[0] = -val_Normal[2]; l[1] = 0.0; l[2] = val_Normal[0]; } - + /*--- Take vector product of n * l to make m ---*/ m[0] = val_Normal[1]*l[2] - val_Normal[2]*l[1]; m[1] = val_Normal[2]*l[0] - val_Normal[0]*l[2]; m[2] = val_Normal[0]*l[1] - val_Normal[1]*l[0]; - + /*--- Normalize ---*/ modm =0 ; modl = 0; for (iDim =0 ; iDim < nDim; iDim++) { @@ -1866,17 +1822,18 @@ void CNumerics::CreateBasis(su2double *val_Normal) { } } -void CNumerics::SetRoe_Dissipation(const su2double Dissipation_i, - const su2double Dissipation_j, - const su2double Sensor_i, - const su2double Sensor_j, - su2double& Dissipation_ij, - CConfig *config) { +su2double CNumerics::GetRoe_Dissipation(const su2double Dissipation_i, + const su2double Dissipation_j, + const su2double Sensor_i, + const su2double Sensor_j, + const CConfig* config) const { /*--- Check for valid input ---*/ unsigned short roe_low_diss = config->GetKind_RoeLowDiss(); + su2double Dissipation_ij = 0.0; + assert((Dissipation_i >= 0) && (Dissipation_i <= 1)); assert((Dissipation_j >= 0) && (Dissipation_j <= 1)); if (roe_low_diss == FD_DUCROS || roe_low_diss == NTS_DUCROS) { @@ -1887,30 +1844,30 @@ void CNumerics::SetRoe_Dissipation(const su2double Dissipation_i, /*--- A minimum level of upwinding is used to enhance stability ---*/ const su2double Min_Dissipation = 0.05; - + const su2double Mean_Dissipation = 0.5*(Dissipation_i + Dissipation_j); const su2double Mean_Sensor = 0.5*(Sensor_i + Sensor_j); - + if (roe_low_diss == FD || roe_low_diss == FD_DUCROS){ Dissipation_ij = max(0.05,1.0 - (0.5 * (Dissipation_i + Dissipation_j))); - + if (roe_low_diss == FD_DUCROS){ - + /*--- See Jonhsen et al. JCP 229 (2010) pag. 1234 ---*/ su2double Ducros_ij; - + if (0.5*(Sensor_i + Sensor_j) > 0.65) Ducros_ij = 1.0; else Ducros_ij = 0.05; - + Dissipation_ij = max(Ducros_ij, Dissipation_ij); } } else if (roe_low_diss == NTS) { - + Dissipation_ij = max(Min_Dissipation, Mean_Dissipation); } else if (roe_low_diss == NTS_DUCROS) { @@ -1929,7 +1886,7 @@ void CNumerics::SetRoe_Dissipation(const su2double Dissipation_i, CURRENT_FUNCTION); } - + return Dissipation_ij; } void CNumerics::EigenDecomposition(su2double **A_ij, su2double **Eig_Vec, su2double *Eig_Val, unsigned short n){ @@ -2163,7 +2120,7 @@ void CNumerics::tql2(su2double **V, su2double *d, su2double *e, unsigned short n * LC: QA193.M37 */ - + int i,j,k,l; for (i = 1; i < n; i++) { e[i-1] = e[i]; @@ -2276,6 +2233,3 @@ void CNumerics::tql2(su2double **V, su2double *d, su2double *e, unsigned short n } } -CSourceNothing::CSourceNothing(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { } - -CSourceNothing::~CSourceNothing(void) { } diff --git a/SU2_CFD/src/numerics/continuous_adjoint/adj_convection.cpp b/SU2_CFD/src/numerics/continuous_adjoint/adj_convection.cpp new file mode 100644 index 000000000000..14d2d7f40346 --- /dev/null +++ b/SU2_CFD/src/numerics/continuous_adjoint/adj_convection.cpp @@ -0,0 +1,846 @@ +/*! + * \file adj_convection.cpp + * \brief Implementation of adjoint convection numerics classes. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/numerics/continuous_adjoint/adj_convection.hpp" + +CCentLax_AdjFlow::CCentLax_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + Diff_Psi = new su2double [nVar]; MeanPhi = new su2double [nDim]; + Velocity_i = new su2double [nDim]; Velocity_j = new su2double [nDim]; + + implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); + + grid_movement = config->GetGrid_Movement(); + + Param_p = 0.3; + Param_Kappa_0 = config->GetKappa_1st_AdjFlow(); + +} + +CCentLax_AdjFlow::~CCentLax_AdjFlow(void) { + + delete [] Diff_Psi; delete [] MeanPhi; + delete [] Velocity_i; delete [] Velocity_j; + +} + +void CCentLax_AdjFlow::ComputeResidual (su2double *val_resconv_i, su2double *val_resvisc_i, su2double *val_resconv_j, su2double *val_resvisc_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, + CConfig *config) { + + /*--- Mean value of the adjoint variables ---*/ + MeanPsiRho = 0.5*(Psi_i[0]+Psi_j[0]); + for (iDim = 0; iDim < nDim; iDim++) + MeanPhi[iDim] = 0.5*(Psi_i[iDim+1]+Psi_j[iDim+1]); + MeanPsiE = 0.5*(Psi_i[nVar-1]+Psi_j[nVar-1]); + + /*--- Evaluation at point i ---*/ + ProjVelocity_i = 0; ProjPhi = 0; ProjPhi_Vel = 0; sq_vel = 0; Area = 0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = U_i[iDim+1] / U_i[0]; + ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; + ProjPhi += MeanPhi[iDim]*Normal[iDim]; + ProjPhi_Vel += MeanPhi[iDim]*Velocity_i[iDim]; + sq_vel += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; + Area += Normal[iDim]*Normal[iDim]; + } + Area = sqrt(Area); + phis1 = ProjPhi + ProjVelocity_i*MeanPsiE; + phis2 = MeanPsiRho + ProjPhi_Vel + Enthalpy_i*MeanPsiE; + + /*--- Compute inviscid residual at point i ---*/ + val_resconv_i[0] = ProjVelocity_i*MeanPsiRho - phis2*ProjVelocity_i + Gamma_Minus_One*phis1*sq_vel; + for (iDim = 0; iDim < nDim; iDim++) + val_resconv_i[iDim+1] = ProjVelocity_i*MeanPhi[iDim] + phis2*Normal[iDim] - Gamma_Minus_One*phis1*Velocity_i[iDim]; + val_resconv_i[nVar-1] = ProjVelocity_i*MeanPsiE + Gamma_Minus_One*phis1; + + /*--- Flux contributions due to grid motion at point i ---*/ + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + val_resconv_i[0] -= ProjGridVel*MeanPsiRho; + for (iDim = 0; iDim < nDim; iDim++) + val_resconv_i[iDim+1] -= ProjGridVel*MeanPhi[iDim]; + val_resconv_i[nVar-1] -= ProjGridVel*MeanPsiE; + } + + /*--- Inviscid contribution to the implicit part ---*/ + if (implicit) { + val_Jacobian_ii[0][0] = 0.0; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_ii[0][jDim+1] = -0.5*ProjVelocity_i*Velocity_i[jDim] + Gamma_Minus_One*sq_vel*0.5*Normal[jDim]; + val_Jacobian_ii[0][nVar-1] = 0.5*ProjVelocity_i*(Gamma_Minus_One*sq_vel - Enthalpy_i); + for (iDim = 0; iDim < nDim; iDim++) { + val_Jacobian_ii[iDim+1][0] = 0.5*Normal[iDim]; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_ii[iDim+1][jDim+1] = 0.5*Normal[iDim]*Velocity_i[jDim] - 0.5*Gamma_Minus_One*Velocity_i[iDim]*Normal[jDim]; + val_Jacobian_ii[iDim+1][iDim+1] += 0.5*ProjVelocity_i; + val_Jacobian_ii[iDim+1][nVar-1] = 0.5*Enthalpy_i*Normal[iDim] - 0.5*Gamma_Minus_One*Velocity_i[iDim]*ProjVelocity_i; + } + val_Jacobian_ii[nVar-1][0] = 0; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_ii[nVar-1][jDim+1] = 0.5*Gamma_Minus_One*Normal[jDim]; + val_Jacobian_ii[nVar-1][nVar-1] = 0.5*Gamma*ProjVelocity_i; + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + val_Jacobian_ij[iVar][jVar] = val_Jacobian_ii[iVar][jVar]; + + /*--- Jacobian contributions due to grid motion at point i ---*/ + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) { + val_Jacobian_ii[iVar][iVar] -= 0.5*ProjGridVel; + val_Jacobian_ij[iVar][iVar] -= 0.5*ProjGridVel; + } + } + } + + /*--- Evaluation at point j ---*/ + ProjVelocity_j = 0; ProjPhi_Vel = 0; sq_vel = 0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_j[iDim] = U_j[iDim+1] / U_j[0]; + ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; + ProjPhi_Vel += MeanPhi[iDim]*Velocity_j[iDim]; + sq_vel += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; + } + + phis1 = ProjPhi + ProjVelocity_j*MeanPsiE; + phis2 = MeanPsiRho + ProjPhi_Vel + Enthalpy_j*MeanPsiE; + + /*--- Compute inviscid residual at point j ---*/ + val_resconv_j[0] = -(ProjVelocity_j*MeanPsiRho - phis2*ProjVelocity_j + Gamma_Minus_One*phis1*sq_vel); + for (iDim = 0; iDim < nDim; iDim++) + val_resconv_j[iDim+1] = -(ProjVelocity_j*MeanPhi[iDim] + phis2*Normal[iDim] - Gamma_Minus_One*phis1*Velocity_j[iDim]); + val_resconv_j[nVar-1] = -(ProjVelocity_j*MeanPsiE + Gamma_Minus_One*phis1); + + /*--- Flux contributions due to grid movement at point j ---*/ + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + val_resconv_j[0] += ProjGridVel*MeanPsiRho; + for (iDim = 0; iDim < nDim; iDim++) + val_resconv_j[iDim+1] += ProjGridVel*MeanPhi[iDim]; + val_resconv_j[nVar-1] += ProjGridVel*MeanPsiE; + } + + /*--- Inviscid contribution to the implicit part ---*/ + if (implicit) { + val_Jacobian_jj[0][0] = 0.0; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_jj[0][jDim+1] = 0.5*ProjVelocity_j*Velocity_j[jDim] - Gamma_Minus_One*sq_vel*0.5*Normal[jDim]; + val_Jacobian_jj[0][nVar-1] = -0.5*ProjVelocity_j*(Gamma_Minus_One*sq_vel - Enthalpy_j); + for (iDim = 0; iDim < nDim; iDim++) { + val_Jacobian_jj[iDim+1][0] = -0.5*Normal[iDim]; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_jj[iDim+1][jDim+1] = -0.5*Normal[iDim]*Velocity_j[jDim] + 0.5*Gamma_Minus_One*Velocity_j[iDim]*Normal[jDim]; + val_Jacobian_jj[iDim+1][iDim+1] -= 0.5*ProjVelocity_j; + val_Jacobian_jj[iDim+1][nVar-1] = -0.5*Enthalpy_j*Normal[iDim] + 0.5*Gamma_Minus_One*Velocity_j[iDim]*ProjVelocity_j; + } + val_Jacobian_jj[nVar-1][0] = 0; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_jj[nVar-1][jDim+1] = -0.5*Gamma_Minus_One*Normal[jDim]; + val_Jacobian_jj[nVar-1][nVar-1] = -0.5*Gamma*ProjVelocity_j; + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + val_Jacobian_ji[iVar][jVar] = val_Jacobian_jj[iVar][jVar]; + + /*--- Jacobian contributions due to grid movement at point j ---*/ + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) { + val_Jacobian_jj[iVar][iVar] += 0.5*ProjGridVel; + val_Jacobian_ji[iVar][iVar] += 0.5*ProjGridVel; + } + } + } + + /*--- Computes differences btw. variables ---*/ + for (iVar = 0; iVar < nVar; iVar++) + Diff_Psi[iVar] = Psi_i[iVar]-Psi_j[iVar]; + + /*--- Adjustment to projected velocity due to grid motion ---*/ + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + ProjVelocity_i -= ProjGridVel; + ProjVelocity_j += ProjGridVel; + } + + /*--- Compute spectral radius ---*/ + Local_Lambda_i = (fabs(ProjVelocity_i)+SoundSpeed_i*Area); + Local_Lambda_j = (fabs(ProjVelocity_j)+SoundSpeed_j*Area); + MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); + + /*--- Compute streching factor ---*/ + Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); + Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); + StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); + + sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); + Epsilon_0 = Param_Kappa_0*sc2*su2double(nDim)/3.0; + + /*--- Artifical dissipation evaluation ---*/ + for (iVar = 0; iVar < nVar; iVar++) { + Residual = Epsilon_0*StretchingFactor*MeanLambda*Diff_Psi[iVar]; + val_resvisc_i[iVar] = -Residual; + val_resvisc_j[iVar] = Residual; + } + + /*--- Contribution to implicit part ---*/ + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) { + val_Jacobian_ii[iVar][iVar] -= Epsilon_0*StretchingFactor*MeanLambda; + val_Jacobian_ij[iVar][iVar] += Epsilon_0*StretchingFactor*MeanLambda; + val_Jacobian_ji[iVar][iVar] += Epsilon_0*StretchingFactor*MeanLambda; + val_Jacobian_jj[iVar][iVar] -= Epsilon_0*StretchingFactor*MeanLambda; + } + } + +} + +CCentJST_AdjFlow::CCentJST_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + grid_movement = config->GetGrid_Movement(); + + Diff_Psi = new su2double [nVar]; Diff_Lapl = new su2double [nVar]; + Velocity_i = new su2double [nDim]; Velocity_j = new su2double [nDim]; + MeanPhi = new su2double [nDim]; + + Param_p = 0.3; + Param_Kappa_2 = config->GetKappa_2nd_AdjFlow(); + Param_Kappa_4 = config->GetKappa_4th_AdjFlow(); + implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); + +} + +CCentJST_AdjFlow::~CCentJST_AdjFlow(void) { + + delete [] Diff_Psi; delete [] Diff_Lapl; + delete [] Velocity_i; delete [] Velocity_j; + delete [] MeanPhi; +} + +void CCentJST_AdjFlow::ComputeResidual (su2double *val_resconv_i, su2double *val_resvisc_i, su2double *val_resconv_j, su2double *val_resvisc_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, + CConfig *config) { + + /*--- Mean Values ---*/ + + MeanPsiRho = 0.5*(Psi_i[0]+Psi_j[0]); + for (iDim = 0; iDim < nDim; iDim++) + MeanPhi[iDim] = 0.5*(Psi_i[iDim+1]+Psi_j[iDim+1]); + MeanPsiE = 0.5*(Psi_i[nVar-1]+Psi_j[nVar-1]); + + /*--- Point i convective residual evaluation ---*/ + + ProjVelocity_i = 0; ProjPhi = 0; ProjPhi_Vel = 0; sq_vel = 0; Area = 0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = U_i[iDim+1] / U_i[0]; + ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; + ProjPhi += MeanPhi[iDim]*Normal[iDim]; + ProjPhi_Vel += MeanPhi[iDim]*Velocity_i[iDim]; + sq_vel += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; + Area += Normal[iDim]*Normal[iDim]; + } + Area = sqrt(Area); + phis1 = ProjPhi + ProjVelocity_i*MeanPsiE; + phis2 = MeanPsiRho + ProjPhi_Vel + Enthalpy_i*MeanPsiE; + + val_resconv_i[0] = ProjVelocity_i*MeanPsiRho - phis2*ProjVelocity_i + Gamma_Minus_One*phis1*sq_vel; + for (iDim = 0; iDim < nDim; iDim++) + val_resconv_i[iDim+1] = ProjVelocity_i*MeanPhi[iDim] + phis2*Normal[iDim] - Gamma_Minus_One*phis1*Velocity_i[iDim]; + val_resconv_i[nVar-1] = ProjVelocity_i*MeanPsiE + Gamma_Minus_One*phis1; + + /*--- Flux contributions due to grid movement at point i ---*/ + + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + val_resconv_i[0] -= ProjGridVel*MeanPsiRho; + for (iDim = 0; iDim < nDim; iDim++) + val_resconv_i[iDim+1] -= ProjGridVel*MeanPhi[iDim]; + val_resconv_i[nVar-1] -= ProjGridVel*MeanPsiE; + } + + /*--- Jacobians of the inviscid flux ---*/ + + if (implicit) { + val_Jacobian_ii[0][0] = 0.0; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_ii[0][jDim+1] = -0.5*ProjVelocity_i*Velocity_i[jDim] + Gamma_Minus_One*sq_vel*0.5*Normal[jDim]; + val_Jacobian_ii[0][nVar-1] = 0.5*ProjVelocity_i*(Gamma_Minus_One*sq_vel - Enthalpy_i); + for (iDim = 0; iDim < nDim; iDim++) { + val_Jacobian_ii[iDim+1][0] = 0.5*Normal[iDim]; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_ii[iDim+1][jDim+1] = 0.5*Normal[iDim]*Velocity_i[jDim] - 0.5*Gamma_Minus_One*Velocity_i[iDim]*Normal[jDim]; + val_Jacobian_ii[iDim+1][iDim+1] += 0.5*ProjVelocity_i; + val_Jacobian_ii[iDim+1][nVar-1] = 0.5*Enthalpy_i*Normal[iDim] - 0.5*Gamma_Minus_One*Velocity_i[iDim]*ProjVelocity_i; + } + val_Jacobian_ii[nVar-1][0] = 0; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_ii[nVar-1][jDim+1] = 0.5*Gamma_Minus_One*Normal[jDim]; + val_Jacobian_ii[nVar-1][nVar-1] = 0.5*Gamma*ProjVelocity_i; + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + val_Jacobian_ij[iVar][jVar] = val_Jacobian_ii[iVar][jVar]; + + /*--- Jacobian contributions due to grid movement at point i ---*/ + + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) { + val_Jacobian_ii[iVar][iVar] -= 0.5*ProjGridVel; + val_Jacobian_ij[iVar][iVar] -= 0.5*ProjGridVel; + } + } + } + + + /*--- Point j convective residual evaluation ---*/ + + ProjVelocity_j = 0; ProjPhi_Vel = 0; sq_vel = 0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_j[iDim] = U_j[iDim+1] / U_j[0]; + ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; + ProjPhi_Vel += MeanPhi[iDim]*Velocity_j[iDim]; + sq_vel += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; + } + + phis1 = ProjPhi + ProjVelocity_j*MeanPsiE; + phis2 = MeanPsiRho + ProjPhi_Vel + Enthalpy_j*MeanPsiE; + + val_resconv_j[0] = -(ProjVelocity_j*MeanPsiRho - phis2*ProjVelocity_j + Gamma_Minus_One*phis1*sq_vel); + for (iDim = 0; iDim < nDim; iDim++) + val_resconv_j[iDim+1] = -(ProjVelocity_j*MeanPhi[iDim] + phis2*Normal[iDim] - Gamma_Minus_One*phis1*Velocity_j[iDim]); + val_resconv_j[nVar-1] = -(ProjVelocity_j*MeanPsiE + Gamma_Minus_One*phis1); + + /*--- Flux contributions due to grid motion at point j ---*/ + + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + val_resconv_j[0] += ProjGridVel*MeanPsiRho; + for (iDim = 0; iDim < nDim; iDim++) + val_resconv_j[iDim+1] += ProjGridVel*MeanPhi[iDim]; + val_resconv_j[nVar-1] += ProjGridVel*MeanPsiE; + } + + /*--- Jacobians of the inviscid flux ---*/ + + if (implicit) { + val_Jacobian_jj[0][0] = 0.0; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_jj[0][jDim+1] = 0.5*ProjVelocity_j*Velocity_j[jDim] - Gamma_Minus_One*sq_vel*0.5*Normal[jDim]; + val_Jacobian_jj[0][nVar-1] = -0.5*ProjVelocity_j*(Gamma_Minus_One*sq_vel - Enthalpy_j); + for (iDim = 0; iDim < nDim; iDim++) { + val_Jacobian_jj[iDim+1][0] = -0.5*Normal[iDim]; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_jj[iDim+1][jDim+1] = -0.5*Normal[iDim]*Velocity_j[jDim] + 0.5*Gamma_Minus_One*Velocity_j[iDim]*Normal[jDim]; + val_Jacobian_jj[iDim+1][iDim+1] -= 0.5*ProjVelocity_j; + val_Jacobian_jj[iDim+1][nVar-1] = -0.5*Enthalpy_j*Normal[iDim] + 0.5*Gamma_Minus_One*Velocity_j[iDim]*ProjVelocity_j; + } + val_Jacobian_jj[nVar-1][0] = 0; + for (jDim = 0; jDim < nDim; jDim++) + val_Jacobian_jj[nVar-1][jDim+1] = -0.5*Gamma_Minus_One*Normal[jDim]; + val_Jacobian_jj[nVar-1][nVar-1] = -0.5*Gamma*ProjVelocity_j; + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + val_Jacobian_ji[iVar][jVar] = val_Jacobian_jj[iVar][jVar]; + + /*--- Jacobian contributions due to grid motion at point j ---*/ + + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) { + val_Jacobian_jj[iVar][iVar] += 0.5*ProjGridVel; + val_Jacobian_ji[iVar][iVar] += 0.5*ProjGridVel; + } + } + } + + /*--- Computes differences btw. variables and Laplacians ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Diff_Lapl[iVar] = Und_Lapl_i[iVar]-Und_Lapl_j[iVar]; + Diff_Psi[iVar] = Psi_i[iVar]-Psi_j[iVar]; + } + + /*--- Adjustment to projected velocity due to grid motion ---*/ + + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + } + ProjVelocity_i -= ProjGridVel; + ProjVelocity_j += ProjGridVel; + } + + /*--- Compute the spectral radius and stretching factor ---*/ + + Local_Lambda_i = (fabs(ProjVelocity_i)+SoundSpeed_i*Area); + Local_Lambda_j = (fabs(ProjVelocity_j)+SoundSpeed_j*Area); + MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); + + Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); + Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); + StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); + + su2double sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); + sc4 = sc2*sc2/4.0; + Epsilon_2 = Param_Kappa_2*0.5*(Sensor_i+Sensor_j)*sc2; + Epsilon_4 = max(0.0, Param_Kappa_4-Epsilon_2)*sc4; + + /*--- Compute viscous residual 1st- & 3rd-order dissipation ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Residual = (Epsilon_2*Diff_Psi[iVar]-Epsilon_4*Diff_Lapl[iVar])*StretchingFactor*MeanLambda; + val_resvisc_i[iVar] = -Residual; + val_resvisc_j[iVar] = Residual; + if (implicit) { + val_Jacobian_ii[iVar][iVar] -= Epsilon_2 + su2double(Neighbor_i+1)*Epsilon_4*StretchingFactor*MeanLambda; + val_Jacobian_ij[iVar][iVar] += Epsilon_2 + su2double(Neighbor_j+1)*Epsilon_4*StretchingFactor*MeanLambda; + val_Jacobian_ji[iVar][iVar] += Epsilon_2 + su2double(Neighbor_i+1)*Epsilon_4*StretchingFactor*MeanLambda; + val_Jacobian_jj[iVar][iVar] -= Epsilon_2 + su2double(Neighbor_j+1)*Epsilon_4*StretchingFactor*MeanLambda; + } + } + +} + + +CUpwRoe_AdjFlow::CUpwRoe_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); + grid_movement = config->GetGrid_Movement(); + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + Residual_Roe = new su2double [nVar]; + RoeVelocity = new su2double [nDim]; + Velocity_i = new su2double [nDim]; + Velocity_j = new su2double [nDim]; + Lambda = new su2double [nVar]; + P_Tensor = new su2double* [nVar]; + invP_Tensor = new su2double* [nVar]; + ProjFlux_i = new su2double*[nVar]; + ProjFlux_j = new su2double*[nVar]; + Proj_ModJac_Tensor = new su2double*[nVar]; + for (iVar = 0; iVar < nVar; iVar++) { + P_Tensor[iVar] = new su2double [nVar]; + invP_Tensor[iVar] = new su2double [nVar]; + ProjFlux_i[iVar] = new su2double[nVar]; + ProjFlux_j[iVar] = new su2double[nVar]; + Proj_ModJac_Tensor[iVar] = new su2double[nVar]; + } + +} + +CUpwRoe_AdjFlow::~CUpwRoe_AdjFlow(void) { + + delete [] Residual_Roe; + delete [] RoeVelocity; + delete [] Velocity_i; + delete [] Velocity_j; + delete [] Lambda; + for (iVar = 0; iVar < nVar; iVar++) { + delete [] P_Tensor[iVar]; + delete [] invP_Tensor[iVar]; + delete [] ProjFlux_i[iVar]; + delete [] ProjFlux_j[iVar]; + delete [] Proj_ModJac_Tensor[iVar]; + } + delete [] P_Tensor; + delete [] invP_Tensor; + delete [] ProjFlux_i; + delete [] ProjFlux_j; + delete [] Proj_ModJac_Tensor; + +} + +void CUpwRoe_AdjFlow::ComputeResidual (su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, + su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { + + /*--- Compute the area ---*/ + + area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + area += Normal[iDim]*Normal[iDim]; + area = sqrt(area); + rarea = 1.0 / area; + + /*--- Components of the normal & unit normal vector of the current face ---*/ + + Sx = Normal[0]; + Sy = Normal[1]; + Sz = 0.0; if (nDim == 3) Sz = Normal[2]; + nx = Sx * rarea; + ny = Sy * rarea; + nz = Sz * rarea; + + /*--- Flow variable states at point i (left, _l) and j (right, _r)---*/ + + rho_l = V_i[nDim+2]; rho_r = V_j[nDim+2]; + u_l = V_i[1]; v_l = V_i[2]; w_l = 0.0; if (nDim == 3) w_l = V_i[3]; + u_r = V_j[1]; v_r = V_j[2]; w_r = 0.0; if (nDim == 3) w_r = V_j[3]; + h_l = V_i[nDim+3]; h_r = V_j[nDim+3]; + + /*--- One-half speed squared ---*/ + + q_l = ONE2 * ((u_l*u_l) + (v_l*v_l) + (w_l*w_l)); + q_r = ONE2 * ((u_r*u_r) + (v_r*v_r) + (w_r*w_r)); + + /*--- Projected velocity ---*/ + + Q_l = (u_l * Sx) + (v_l * Sy) + (w_l * Sz); + Q_r = (u_r * Sx) + (v_r * Sy) + (w_r * Sz); + + /*--- Mean adjoint variables ---*/ + + psi1 = ONE2 * (Psi_i[0] + Psi_j[0]); + psi2 = ONE2 * (Psi_i[1] + Psi_j[1]); + psi3 = ONE2 * (Psi_i[2] + Psi_j[2]); + psi4 = 0.0; if (nDim == 3) psi4 = ONE2 * (Psi_i[3] + Psi_j[3]); + psi5 = ONE2 * (Psi_i[nVar-1] + Psi_j[nVar-1]); + + /*--- Left state ---*/ + + l1psi = (Sx * psi2) + (Sy * psi3) + (Sz * psi4) + (Q_l * psi5); + l2psi = psi1 + (u_l * psi2) + (v_l * psi3) + (w_l * psi4) + (h_l * psi5); + + val_residual_i[0] = Q_l * psi1 - l2psi * Q_l + l1psi * Gamma_Minus_One * q_l; + val_residual_i[1] = Q_l * psi2 + l2psi * Sx - l1psi * Gamma_Minus_One * u_l; + val_residual_i[2] = Q_l * psi3 + l2psi * Sy - l1psi * Gamma_Minus_One * v_l; + if (nDim == 3) val_residual_i[3] = Q_l * psi4 + l2psi * Sz - l1psi * Gamma_Minus_One * w_l; + val_residual_i[nVar-1] = Q_l * psi5 + l1psi * Gamma_Minus_One; + + /*--- Right state ---*/ + + l1psi = (Sx * psi2) + (Sy * psi3) + (Sz * psi4) + (Q_r * psi5); + l2psi = psi1 + (u_r * psi2) + (v_r * psi3) + (w_r * psi4) + (h_r * psi5); + + val_residual_j[0] = -(Q_r * psi1 - l2psi * Q_r + l1psi * Gamma_Minus_One * q_r); + val_residual_j[1] = -(Q_r * psi2 + l2psi * Sx - l1psi * Gamma_Minus_One * u_r); + val_residual_j[2] = -(Q_r * psi3 + l2psi * Sy - l1psi * Gamma_Minus_One * v_r); + if (nDim == 3) val_residual_j[3] = -(Q_r * psi4 + l2psi * Sz - l1psi * Gamma_Minus_One * w_r); + val_residual_j[nVar-1] = -(Q_r * psi5 + l1psi * Gamma_Minus_One); + + + /*--- f_{roe} = P^{-T} |lambda| P^T \delta \psi ---*/ + + psi1_l = Psi_i[0]; + psi2_l = Psi_i[1]; + psi3_l = Psi_i[2]; + psi4_l = 0.0; if (nDim == 3) psi4_l = Psi_i[3]; + psi5_l = Psi_i[nVar-1]; + + psi1_r = Psi_j[0]; + psi2_r = Psi_j[1]; + psi3_r = Psi_j[2]; + psi4_r = 0.0; if (nDim == 3) psi4_r = Psi_j[3]; + psi5_r = Psi_j[nVar-1]; + + /*--- Roe averaging ---*/ + + rrho_l = 1.0 / rho_l; + weight = sqrt(rho_r * rrho_l); + rweight1 = 1.0 / (1.0 + weight); + weight *= rweight1; + + h = h_l * rweight1 + weight * h_r; + u = u_l * rweight1 + weight * u_r; + v = v_l * rweight1 + weight * v_r; + w = w_l * rweight1 + weight * w_r; + + psi1 = ONE2 * (psi1_r - psi1_l); + psi2 = ONE2 * (psi2_r - psi2_l); + psi3 = ONE2 * (psi3_r - psi3_l); + psi4 = ONE2 * (psi4_r - psi4_l); + psi5 = ONE2 * (psi5_r - psi5_l); + + q2 = (u*u) + (v*v) + (w*w); + Q = (u * Sx) + (v * Sy) + (w * Sz); + vn = nx * u + ny * v + nz * w; + cc = Gamma_Minus_One * h - 0.5 * Gamma_Minus_One * q2; + c = sqrt(cc); + + /*--- Contribution to velocity projection due to grid movement ---*/ + + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + Q -= ProjGridVel; + } + + /*--- Eigenvalues from the primal solution ---*/ + + absQ = fabs(Q); + absQp = fabs(Q + c * area); + absQm = fabs(Q - c * area); + + alpha = ONE2 * Gamma_Minus_One * q2 / cc; + beta_u = psi2 + u * psi5; + beta_v = psi3 + v * psi5; + beta_w = psi4 + w * psi5; + eta = Gamma_Minus_One / cc; + l1psi = (nx * psi2) + (ny * psi3) + (nz * psi4) + (vn * psi5); + l2psi = psi1 + (u * psi2) + (v * psi3) + (w * psi4) + (h * psi5); + l1l2p = (l2psi + c * l1psi) * absQp; + l1l2m = (l2psi - c * l1psi) * absQm; + + /*--- adjoint flux computation in the x, y and z coordinate system ---*/ + + Residual_Roe[0] = ((1.0-alpha)*l2psi - (1.0-alpha)*cc/Gamma_Minus_One*psi5 + - u*beta_u*(1.0-(nx*nx)) - v*beta_v*(1.0-(ny*ny)) + - w*beta_w*(1.0-(nz*nz)) + ny*nz*(w*beta_v + v*beta_w) + + nx*nz*(w*beta_u + u*beta_w) + ny*nx*(v*beta_u + u*beta_v) ) * absQ + - ONE2 / c * vn * (l1l2p - l1l2m) + ONE2 * alpha * (l1l2p + l1l2m); + + Residual_Roe[1] = (l2psi*u*eta - u*psi5 + beta_u*(1.0-(nx*nx)) + - nx*(beta_v*ny + beta_w*nz) ) * absQ + ONE2*nx/c * (l1l2p - l1l2m ) + - ONE2*eta*u * (l1l2p + l1l2m ); + + Residual_Roe[2] = (l2psi*v*eta - v*psi5 + beta_v*(1.0-(ny*ny)) + - ny*(beta_w*nz + beta_u*nx) ) * absQ + ONE2*ny/c * (l1l2p - l1l2m ) + - ONE2*eta*v * (l1l2p + l1l2m ); + + if (nDim == 3) Residual_Roe[3] = (l2psi*w*eta - w*psi5 + beta_w*(1.0-(nz*nz)) - nz*(beta_u*nx + beta_v*ny) ) * absQ + + ONE2*nz/c * (l1l2p - l1l2m ) - ONE2*eta*w * (l1l2p + l1l2m ); + + Residual_Roe[nVar-1] = (psi5 - l2psi*eta) * absQ + ONE2*eta*(l1l2p + l1l2m); + + for (iVar = 0; iVar < nVar; iVar++) { + val_residual_i[iVar] += Residual_Roe[iVar]; + val_residual_j[iVar] -= Residual_Roe[iVar]; + } + + /*--- Flux contribution due to grid movement ---*/ + + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) { + val_residual_i[iVar] -= ProjGridVel * 0.5*(Psi_i[iVar]+Psi_j[iVar]); + val_residual_j[iVar] += ProjGridVel * 0.5*(Psi_i[iVar]+Psi_j[iVar]); + } + } + + /*--- Implicit Contributions ---*/ + + if (implicit) { + + /*--- Prepare variables for use in matrix routines ---*/ + + RoeDensity = V_i[nDim+2]*sqrt(V_j[nDim+2]/V_i[nDim+2]); + RoeSoundSpeed = c; + UnitNormal[0] = nx; UnitNormal[1] = ny; if (nDim == 3 ) UnitNormal[2] = nz; + RoeVelocity[0] = u; RoeVelocity[1] = v; if (nDim == 3 ) RoeVelocity[2] = w; + Velocity_i[0] = u_l; Velocity_i[1] = v_l; if (nDim == 3 ) Velocity_i[2] = w_l; + Velocity_j[0] = u_r; Velocity_j[1] = v_r; if (nDim == 3 ) Velocity_j[2] = w_r; + + Pressure_i = V_i[nDim+1]; + Density_i = V_i[nDim+2]; + Enthalpy_i = V_i[nDim+3]; + Energy_i = Enthalpy_i - Pressure_i/Density_i; + + Pressure_j = V_i[nDim+1]; + Density_j = V_i[nDim+2]; + Enthalpy_j = V_i[nDim+3]; + Energy_j = Enthalpy_j - Pressure_j/Density_j; + + /*--- Jacobians of the inviscid flux, scaled by + 0.5 because val_resconv ~ 0.5*(fc_i+fc_j)*Normal ---*/ + + GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5, ProjFlux_i); + GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5, ProjFlux_j); + + /*--- Compute P, inverse P, and store eigenvalues ---*/ + + GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); + GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, P_Tensor); + + /*--- Flow eigenvalues ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + Lambda[iDim] = absQ; + Lambda[nVar-2] = absQp; + Lambda[nVar-1] = absQm; + + /*--- Roe's Flux approximation ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Proj_ModJac_Tensor_ij = 0.0; + + /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ + + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; + Proj_ModJac_Tensor[iVar][jVar] = 0.5*Proj_ModJac_Tensor_ij*area; + } + } + + /*--- Transpose the matrices and store the Jacobians. Note the negative + sign for the ji and jj Jacobians bc the normal direction is flipped. ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + val_Jacobian_ii[jVar][iVar] = ProjFlux_i[iVar][jVar] - Proj_ModJac_Tensor[iVar][jVar]; + val_Jacobian_ij[jVar][iVar] = ProjFlux_i[iVar][jVar] + Proj_ModJac_Tensor[iVar][jVar]; + val_Jacobian_ji[jVar][iVar] = -(ProjFlux_j[iVar][jVar] - Proj_ModJac_Tensor[iVar][jVar]); + val_Jacobian_jj[jVar][iVar] = -(ProjFlux_j[iVar][jVar] + Proj_ModJac_Tensor[iVar][jVar]); + } + } + + /*--- Jacobian contribution due to grid movement ---*/ + + if (grid_movement) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) { + + /*--- Adjust Jacobian main diagonal ---*/ + + val_Jacobian_ii[iVar][iVar] -= 0.5*ProjGridVel; + val_Jacobian_ij[iVar][iVar] -= 0.5*ProjGridVel; + val_Jacobian_ji[iVar][iVar] += 0.5*ProjGridVel; + val_Jacobian_jj[iVar][iVar] += 0.5*ProjGridVel; + } + } + + } +} + +CUpwLin_AdjTurb::CUpwLin_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + Velocity_i = new su2double [nDim]; +} + +CUpwLin_AdjTurb::~CUpwLin_AdjTurb(void) { + delete [] Velocity_i; +} + +void CUpwLin_AdjTurb::ComputeResidual (su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { + bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); + + /*--- Non-conservative term --> -\nabla \psi_\mu B^{cv} + B^{cv} = -v ---*/ + + unsigned short iDim; + su2double proj_conv_flux = 0; + + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = U_i[iDim+1]/U_i[0]; + proj_conv_flux += Velocity_i[iDim]*Normal[iDim]; // projection of convective flux at iPoint + } + su2double psinu0 = TurbPsi_i[0]; + su2double psinu1; + if (proj_conv_flux > 0) + psinu1 = psinu0 + proj_conv_flux; + else + psinu1 = psinu0; + + val_residual[0] = 0.5*( proj_conv_flux*(psinu0+psinu1)-fabs(proj_conv_flux)*(psinu1-psinu0)); + if (implicit) { + val_Jacobian_i[0][0] = 0.5*( proj_conv_flux + fabs(proj_conv_flux)); + } +} + +CUpwSca_AdjTurb::CUpwSca_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + Velocity_i = new su2double [nDim]; + Velocity_j = new su2double [nDim]; +} + +CUpwSca_AdjTurb::~CUpwSca_AdjTurb(void) { + delete [] Velocity_i; + delete [] Velocity_j; +} + +void CUpwSca_AdjTurb::ComputeResidual (su2double *val_residual_i, su2double *val_residual_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { + + bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); + + /*--- Non-conservative term --> -\nabla \psi_\mu B^{cv} + B^{cv} = -\nabla \hat{nu}/\sigma + v ---*/ + + unsigned short iDim; + su2double proj_conv_flux_i = 0, proj_conv_flux_j = 0, proj_conv_flux_ij = 0; + su2double sigma = 2./3.; + + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = U_i[iDim+1]/U_i[0]; + Velocity_j[iDim] = U_j[iDim+1]/U_j[0]; + proj_conv_flux_i += (TurbVar_Grad_i[0][iDim]/sigma - Velocity_i[iDim])*Normal[iDim]; // projection of convective flux at iPoint + proj_conv_flux_j += (TurbVar_Grad_j[0][iDim]/sigma - Velocity_j[iDim])*Normal[iDim]; // projection of convective flux at jPoint + } + proj_conv_flux_ij = 0.5*fabs(proj_conv_flux_i+proj_conv_flux_j); // projection of average convective flux + + val_residual_i[0] = 0.5*( proj_conv_flux_i*(TurbPsi_i[0]+TurbPsi_j[0])-proj_conv_flux_ij*(TurbPsi_j[0]-TurbPsi_i[0])); + val_residual_j[0] = 0.5*(-proj_conv_flux_j*(TurbPsi_j[0]+TurbPsi_i[0])-proj_conv_flux_ij*(TurbPsi_i[0]-TurbPsi_j[0])); + if (implicit) { + val_Jacobian_ii[0][0] = 0.5*( proj_conv_flux_i+proj_conv_flux_ij); + val_Jacobian_ij[0][0] = 0.5*( proj_conv_flux_i-proj_conv_flux_ij); + val_Jacobian_ji[0][0] = 0.5*(-proj_conv_flux_j-proj_conv_flux_ij); + val_Jacobian_jj[0][0] = 0.5*(-proj_conv_flux_j+proj_conv_flux_ij); + } + +} diff --git a/SU2_CFD/src/numerics_adjoint_turbulent.cpp b/SU2_CFD/src/numerics/continuous_adjoint/adj_diffusion.cpp similarity index 55% rename from SU2_CFD/src/numerics_adjoint_turbulent.cpp rename to SU2_CFD/src/numerics/continuous_adjoint/adj_diffusion.cpp index ebf58353b96f..8467f8181f1b 100644 --- a/SU2_CFD/src/numerics_adjoint_turbulent.cpp +++ b/SU2_CFD/src/numerics/continuous_adjoint/adj_diffusion.cpp @@ -1,12 +1,12 @@ /*! - * \file numerics_adjoint_turbulent.cpp - * \brief This file contains all the convective term discretization. - * \author F. Palacios, A. Bueno + * \file adj_diffusion.cpp + * \brief Implementation of adjoint diffusion numerics classes. + * \author F. Palacios, T. Economon * \version 7.0.1 "Blackbird" * * 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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -25,96 +25,268 @@ * License along with SU2. If not, see . */ +#include "../../../include/numerics/continuous_adjoint/adj_diffusion.hpp" -#include "../include/numerics_structure.hpp" -#include +CAvgGrad_AdjFlow::CAvgGrad_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + unsigned short iDim; + + implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); -CUpwLin_AdjTurb::CUpwLin_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; - + Velocity_i = new su2double [nDim]; + Velocity_j = new su2double [nDim]; + Mean_Velocity = new su2double [nDim]; + Mean_GradPhi = new su2double* [nDim]; + for (iDim = 0; iDim < nDim; iDim++) + Mean_GradPhi[iDim] = new su2double [nDim]; + Mean_GradPsiE = new su2double [nDim]; + Edge_Vector = new su2double [nDim]; + } -CUpwLin_AdjTurb::~CUpwLin_AdjTurb(void) { +CAvgGrad_AdjFlow::~CAvgGrad_AdjFlow(void) { delete [] Velocity_i; + delete [] Velocity_j; + delete [] Mean_Velocity; + delete [] Edge_Vector; + delete [] Mean_GradPsiE; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + delete [] Mean_GradPhi[iDim]; } -void CUpwLin_AdjTurb::ComputeResidual (su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); - - /*--- Non-conservative term --> -\nabla \psi_\mu B^{cv} - B^{cv} = -v ---*/ - - unsigned short iDim; - su2double proj_conv_flux = 0; - +void CAvgGrad_AdjFlow::ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, + su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { + unsigned short iDim, jDim; + su2double sq_vel_i, ViscDens_i, XiDens_i; + su2double sq_vel_j, ViscDens_j, XiDens_j; + su2double dist_ij_2, dPhiE_dn; + + su2double Prandtl_Lam = config->GetPrandtl_Lam(); + su2double Prandtl_Turb = config->GetPrandtl_Turb(); + + /*--- States in point i ---*/ + + sq_vel_i = 0.0; for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = U_i[iDim+1]/U_i[0]; - proj_conv_flux += Velocity_i[iDim]*Normal[iDim]; // projection of convective flux at iPoint + Velocity_i[iDim] = V_i[iDim+1]; + sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; } - su2double psinu0 = TurbPsi_i[0]; - su2double psinu1; - if (proj_conv_flux > 0) - psinu1 = psinu0 + proj_conv_flux; - else - psinu1 = psinu0; - - val_residual[0] = 0.5*( proj_conv_flux*(psinu0+psinu1)-fabs(proj_conv_flux)*(psinu1-psinu0)); - if (implicit) { - val_Jacobian_i[0][0] = 0.5*( proj_conv_flux + fabs(proj_conv_flux)); + Pressure_i = V_i[nDim+1]; + Density_i = V_i[nDim+2]; + Enthalpy_i = V_i[nDim+3]; + SoundSpeed_i = sqrt(fabs(Pressure_i*Gamma/Density_i)); + + /*--- Laminar and Eddy viscosity ---*/ + + Laminar_Viscosity_i = V_i[nDim+5]; + Eddy_Viscosity_i = V_i[nDim+6]; + + ViscDens_i = (Laminar_Viscosity_i + Eddy_Viscosity_i) / Density_i; + XiDens_i = Gamma*(Laminar_Viscosity_i/Prandtl_Lam + Eddy_Viscosity_i/Prandtl_Turb) / Density_i; + + /*--- States in point j ---*/ + + sq_vel_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_j[iDim] = V_j[iDim+1]; + sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; } + Pressure_j = V_j[nDim+1]; + Density_j = V_j[nDim+2]; + Enthalpy_j = V_j[nDim+3]; + SoundSpeed_j = sqrt(fabs(Pressure_j*Gamma/Density_j)); + + /*--- Laminar and Eddy viscosity ---*/ + + Laminar_Viscosity_j = V_j[nDim+5]; + Eddy_Viscosity_j = V_j[nDim+6]; + + ViscDens_j = (Laminar_Viscosity_j + Eddy_Viscosity_j) / Density_j; + XiDens_j = Gamma*(Laminar_Viscosity_j/Prandtl_Lam + Eddy_Viscosity_j/Prandtl_Turb) / Density_j; + + /*--- Compute vector going from iPoint to jPoint ---*/ + + dist_ij_2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; + dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; + } + + /*--- Average of the derivatives of the adjoint variables ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + Mean_GradPsiE[iDim] = 0.5*(PsiVar_Grad_i[nVar-1][iDim]+PsiVar_Grad_j[nVar-1][iDim]); + for (jDim = 0; jDim < nDim; jDim++) + Mean_GradPhi[iDim][jDim] = 0.5*(PsiVar_Grad_i[iDim+1][jDim]+PsiVar_Grad_j[iDim+1][jDim]); + } + + dPhiE_dn = 0; + for (iDim = 0; iDim < nDim; iDim++) + dPhiE_dn += Mean_GradPsiE[iDim]*Normal[iDim]; + + /*--- Compute the viscous residual and jacobian ---*/ + + GetAdjViscousFlux_Jac(Pressure_i, Pressure_j, Density_i, Density_j, + ViscDens_i, ViscDens_j, Velocity_i, Velocity_j, sq_vel_i, sq_vel_j, + XiDens_i, XiDens_j, Mean_GradPhi, Mean_GradPsiE, + dPhiE_dn, Normal, Edge_Vector, dist_ij_2, val_residual_i, val_residual_j, + val_Jacobian_ii, val_Jacobian_ij, val_Jacobian_ji, val_Jacobian_jj, + implicit); + } -CUpwSca_AdjTurb::CUpwSca_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - + +CAvgGradCorrected_AdjFlow::CAvgGradCorrected_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); + Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; - + Velocity_i = new su2double [nDim]; Velocity_j = new su2double [nDim]; + Mean_Velocity = new su2double [nDim]; + + Mean_GradPsiVar = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) + Mean_GradPsiVar[iVar] = new su2double [nDim]; + + Edge_Vector = new su2double [nDim]; + Proj_Mean_GradPsiVar_Edge = new su2double [nVar]; + + Mean_GradPhi = new su2double* [nDim]; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Mean_GradPhi[iDim] = new su2double [nDim]; + Mean_GradPsiE = new su2double [nDim]; + } -CUpwSca_AdjTurb::~CUpwSca_AdjTurb(void) { +CAvgGradCorrected_AdjFlow::~CAvgGradCorrected_AdjFlow(void) { + delete [] Velocity_i; delete [] Velocity_j; + delete [] Mean_Velocity; + delete [] Edge_Vector; + delete [] Proj_Mean_GradPsiVar_Edge; + + for (unsigned short iVar = 0; iVar < nVar; iVar++) + delete [] Mean_GradPsiVar[iVar]; + delete [] Mean_GradPsiVar; + + for (unsigned short iDim = 0; iDim < nDim; iDim++) + delete [] Mean_GradPhi[iDim]; + delete [] Mean_GradPhi; + delete [] Mean_GradPsiE; + } -void CUpwSca_AdjTurb::ComputeResidual (su2double *val_residual_i, su2double *val_residual_j, - su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { - - bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); - - /*--- Non-conservative term --> -\nabla \psi_\mu B^{cv} - B^{cv} = -\nabla \hat{nu}/\sigma + v ---*/ - - unsigned short iDim; - su2double proj_conv_flux_i = 0, proj_conv_flux_j = 0, proj_conv_flux_ij = 0; - su2double sigma = 2./3.; - +void CAvgGradCorrected_AdjFlow::ComputeResidual(su2double *val_residual_i, + su2double *val_residual_j, + su2double **val_Jacobian_ii, + su2double **val_Jacobian_ij, + su2double **val_Jacobian_ji, + su2double **val_Jacobian_jj, + CConfig *config) { + + unsigned short iVar, iDim, jDim; + su2double Density_i, sq_vel_i, Pressure_i, ViscDens_i, XiDens_i; + su2double Density_j, sq_vel_j, Pressure_j, ViscDens_j, XiDens_j; + su2double dist_ij_2, dPhiE_dn; + + su2double Prandtl_Lam = config->GetPrandtl_Lam(); + su2double Prandtl_Turb = config->GetPrandtl_Turb(); + + /*--- States in point i ---*/ + + sq_vel_i = 0.0; for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = U_i[iDim+1]/U_i[0]; - Velocity_j[iDim] = U_j[iDim+1]/U_j[0]; - proj_conv_flux_i += (TurbVar_Grad_i[0][iDim]/sigma - Velocity_i[iDim])*Normal[iDim]; // projection of convective flux at iPoint - proj_conv_flux_j += (TurbVar_Grad_j[0][iDim]/sigma - Velocity_j[iDim])*Normal[iDim]; // projection of convective flux at jPoint + Velocity_i[iDim] = V_i[iDim+1]; + sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; } - proj_conv_flux_ij = 0.5*fabs(proj_conv_flux_i+proj_conv_flux_j); // projection of average convective flux - - val_residual_i[0] = 0.5*( proj_conv_flux_i*(TurbPsi_i[0]+TurbPsi_j[0])-proj_conv_flux_ij*(TurbPsi_j[0]-TurbPsi_i[0])); - val_residual_j[0] = 0.5*(-proj_conv_flux_j*(TurbPsi_j[0]+TurbPsi_i[0])-proj_conv_flux_ij*(TurbPsi_i[0]-TurbPsi_j[0])); - if (implicit) { - val_Jacobian_ii[0][0] = 0.5*( proj_conv_flux_i+proj_conv_flux_ij); - val_Jacobian_ij[0][0] = 0.5*( proj_conv_flux_i-proj_conv_flux_ij); - val_Jacobian_ji[0][0] = 0.5*(-proj_conv_flux_j-proj_conv_flux_ij); - val_Jacobian_jj[0][0] = 0.5*(-proj_conv_flux_j+proj_conv_flux_ij); + Pressure_i = V_i[nDim+1]; + Density_i = V_i[nDim+2]; + Enthalpy_i = V_i[nDim+3]; + + /*--- Laminar and Eddy viscosity ---*/ + + Laminar_Viscosity_i = V_i[nDim+5]; + Eddy_Viscosity_i = V_i[nDim+6]; + + ViscDens_i = (Laminar_Viscosity_i + Eddy_Viscosity_i) / Density_i; + XiDens_i = Gamma*(Laminar_Viscosity_i/Prandtl_Lam + + Eddy_Viscosity_i/Prandtl_Turb) / Density_i; + + /*--- States in point j ---*/ + + sq_vel_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_j[iDim] = V_j[iDim+1]; + sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; + } + Pressure_j = V_j[nDim+1]; + Density_j = V_j[nDim+2]; + Enthalpy_j = V_j[nDim+3]; + + /*--- Laminar and Eddy viscosity ---*/ + + Laminar_Viscosity_j = V_j[nDim+5]; + Eddy_Viscosity_j = V_j[nDim+6]; + + ViscDens_j = (Laminar_Viscosity_j + Eddy_Viscosity_j) / Density_j; + XiDens_j = Gamma*(Laminar_Viscosity_j/Prandtl_Lam + + Eddy_Viscosity_j/Prandtl_Turb) / Density_j; + + /*--- Compute vector going from iPoint to jPoint ---*/ + + dist_ij_2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Mean_Velocity[iDim] = 0.5*(Velocity_i[iDim]+Velocity_j[iDim]); + Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; + dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; + } + + /*--- Mean gradient approximation. Projection of the mean gradient in the direction of the edge, weiss correction ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Proj_Mean_GradPsiVar_Edge[iVar] = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Mean_GradPsiVar[iVar][iDim] = 0.5*(PsiVar_Grad_i[iVar][iDim] + PsiVar_Grad_j[iVar][iDim]); + Proj_Mean_GradPsiVar_Edge[iVar] += Mean_GradPsiVar[iVar][iDim]*Edge_Vector[iDim]; + } + for (iDim = 0; iDim < nDim; iDim++) + Mean_GradPsiVar[iVar][iDim] -= (Proj_Mean_GradPsiVar_Edge[iVar] - + (Psi_j[iVar]-Psi_i[iVar]))*Edge_Vector[iDim]/dist_ij_2; } - + + /*--- Average of the derivatives of the adjoint variables ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + Mean_GradPsiE[iDim] = Mean_GradPsiVar[nVar-1][iDim]; + for (jDim = 0; jDim < nDim; jDim++) + Mean_GradPhi[iDim][jDim] = Mean_GradPsiVar[iDim+1][jDim]; + } + + dPhiE_dn = 0; + for (iDim = 0; iDim < nDim; iDim++) + dPhiE_dn += Mean_GradPsiE[iDim]*Normal[iDim]; + + /*--- Compute the viscous residual and jacobian ---*/ + + GetAdjViscousFlux_Jac(Pressure_i, Pressure_j, Density_i, Density_j, + ViscDens_i, ViscDens_j, Velocity_i, Velocity_j, sq_vel_i, sq_vel_j, + XiDens_i, XiDens_j, Mean_GradPhi, Mean_GradPsiE, + dPhiE_dn, Normal, Edge_Vector, dist_ij_2, val_residual_i, val_residual_j, + val_Jacobian_ii, val_Jacobian_ij, val_Jacobian_ji, val_Jacobian_jj, + implicit); + } -CAvgGradCorrected_AdjTurb::CAvgGradCorrected_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - + +CAvgGrad_AdjTurb::CAvgGrad_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; Edge_Vector = new su2double [nDim]; @@ -126,7 +298,7 @@ CAvgGradCorrected_AdjTurb::CAvgGradCorrected_AdjTurb(unsigned short val_nDim, un Mean_GradTurbPsi[iVar] = new su2double [nDim]; } -CAvgGradCorrected_AdjTurb::~CAvgGradCorrected_AdjTurb(void) { +CAvgGrad_AdjTurb::~CAvgGrad_AdjTurb(void) { delete [] Edge_Vector; delete [] Proj_Mean_GradTurbPsi_Kappa; delete [] Proj_Mean_GradTurbPsi_Edge; @@ -137,22 +309,22 @@ CAvgGradCorrected_AdjTurb::~CAvgGradCorrected_AdjTurb(void) { delete [] Mean_GradTurbPsi; } -void CAvgGradCorrected_AdjTurb::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, - su2double **val_Jacobian_j, CConfig *config) { - +void CAvgGrad_AdjTurb::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, CConfig *config) { + bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); - + su2double sigma = 2./3.; su2double nu_i, nu_j, nu_e; su2double dist_ij_2 = 0; su2double proj_vector_ij = 0; unsigned short iVar, iDim; - + /*--- Compute mean effective viscosity ---*/ nu_i = Laminar_Viscosity_i/U_i[0]; nu_j = Laminar_Viscosity_j/U_j[0]; nu_e = 0.5*(nu_i+nu_j+TurbVar_i[0]+TurbVar_j[0])/sigma; - + /*--- Compute vector going from iPoint to jPoint ---*/ for (iDim = 0; iDim < nDim; iDim++) { Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; @@ -160,51 +332,47 @@ void CAvgGradCorrected_AdjTurb::ComputeResidual(su2double *val_residual, su2doub proj_vector_ij += Edge_Vector[iDim]*Normal[iDim]; } proj_vector_ij = proj_vector_ij/dist_ij_2; - + /*--- Mean gradient approximation ---*/ for (iVar = 0; iVar < nVar; iVar++) { Proj_Mean_GradTurbPsi_Edge[iVar] = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Mean_GradTurbPsi[iVar][iDim] = 0.5*(TurbPsi_Grad_i[iVar][iDim] + TurbPsi_Grad_j[iVar][iDim]); - Proj_Mean_GradTurbPsi_Edge[iVar] += Mean_GradTurbPsi[iVar][iDim]*Edge_Vector[iDim]; } - - for (iDim = 0; iDim < nDim; iDim++) - Mean_GradTurbPsi[iVar][iDim] -= (Proj_Mean_GradTurbPsi_Edge[iVar] - (TurbPsi_j[iVar]-TurbPsi_i[iVar]))*Edge_Vector[iDim]/dist_ij_2; - + /*--- Projection of the corrected gradient ---*/ Proj_Mean_GradTurbPsi_Corrected[iVar] = 0.0; for (iDim = 0; iDim < nDim; iDim++) Proj_Mean_GradTurbPsi_Corrected[iVar] += Mean_GradTurbPsi[iVar][iDim]*Normal[iDim]; } - + val_residual[0] = -nu_e*Proj_Mean_GradTurbPsi_Corrected[0]; - + if (implicit) { val_Jacobian_i[0][0] = nu_e*proj_vector_ij; val_Jacobian_j[0][0] = -nu_e*proj_vector_ij; } - + } -void CAvgGradCorrected_AdjTurb::ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, +void CAvgGrad_AdjTurb::ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { - + bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); - + su2double sigma = 2./3.; su2double nu_i, nu_j, nu_e_i, nu_e_j; su2double dist_ij_2 = 0; su2double proj_vector_ij = 0; unsigned short iVar, iDim; - + /*--- Compute mean effective viscosity ---*/ nu_i = Laminar_Viscosity_i/U_i[0]; nu_j = Laminar_Viscosity_j/U_j[0]; nu_e_i = (nu_i+TurbVar_i[0])/sigma; nu_e_j = (nu_j+TurbVar_j[0])/sigma; - + /*--- Compute vector going from iPoint to jPoint ---*/ for (iDim = 0; iDim < nDim; iDim++) { Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; @@ -212,39 +380,34 @@ void CAvgGradCorrected_AdjTurb::ComputeResidual(su2double *val_residual_i, su2do proj_vector_ij += Edge_Vector[iDim]*Normal[iDim]; } proj_vector_ij = proj_vector_ij/dist_ij_2; // to normalize vectors - + /*--- Mean gradient approximation ---*/ for (iVar = 0; iVar < nVar; iVar++) { Proj_Mean_GradTurbPsi_Edge[iVar] = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Mean_GradTurbPsi[iVar][iDim] = 0.5*(TurbPsi_Grad_i[iVar][iDim] + TurbPsi_Grad_j[iVar][iDim]); - Proj_Mean_GradTurbPsi_Edge[iVar] += Mean_GradTurbPsi[iVar][iDim]*Edge_Vector[iDim]; } - - for (iDim = 0; iDim < nDim; iDim++) - Mean_GradTurbPsi[iVar][iDim] -= (Proj_Mean_GradTurbPsi_Edge[iVar] - - (TurbPsi_j[iVar]-TurbPsi_i[iVar]))*Edge_Vector[iDim]/dist_ij_2; - + /*--- Projection of the corrected gradient ---*/ Proj_Mean_GradTurbPsi_Corrected[iVar] = 0.0; for (iDim = 0; iDim < nDim; iDim++) Proj_Mean_GradTurbPsi_Corrected[iVar] += Mean_GradTurbPsi[iVar][iDim]*Normal[iDim]; } - + val_residual_i[0] = -nu_e_i*Proj_Mean_GradTurbPsi_Corrected[0]; val_residual_j[0] = nu_e_j*Proj_Mean_GradTurbPsi_Corrected[0]; - + if (implicit) { val_Jacobian_ii[0][0] = nu_e_i*proj_vector_ij; val_Jacobian_ij[0][0] = -nu_e_i*proj_vector_ij; val_Jacobian_ji[0][0] = -nu_e_j*proj_vector_ij; val_Jacobian_jj[0][0] = nu_e_j*proj_vector_ij; } - + } -CAvgGrad_AdjTurb::CAvgGrad_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - +CAvgGradCorrected_AdjTurb::CAvgGradCorrected_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; Edge_Vector = new su2double [nDim]; @@ -256,7 +419,7 @@ CAvgGrad_AdjTurb::CAvgGrad_AdjTurb(unsigned short val_nDim, unsigned short val_n Mean_GradTurbPsi[iVar] = new su2double [nDim]; } -CAvgGrad_AdjTurb::~CAvgGrad_AdjTurb(void) { +CAvgGradCorrected_AdjTurb::~CAvgGradCorrected_AdjTurb(void) { delete [] Edge_Vector; delete [] Proj_Mean_GradTurbPsi_Kappa; delete [] Proj_Mean_GradTurbPsi_Edge; @@ -267,22 +430,22 @@ CAvgGrad_AdjTurb::~CAvgGrad_AdjTurb(void) { delete [] Mean_GradTurbPsi; } -void CAvgGrad_AdjTurb::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, - su2double **val_Jacobian_j, CConfig *config) { - +void CAvgGradCorrected_AdjTurb::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, CConfig *config) { + bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); - + su2double sigma = 2./3.; su2double nu_i, nu_j, nu_e; su2double dist_ij_2 = 0; su2double proj_vector_ij = 0; unsigned short iVar, iDim; - + /*--- Compute mean effective viscosity ---*/ nu_i = Laminar_Viscosity_i/U_i[0]; nu_j = Laminar_Viscosity_j/U_j[0]; nu_e = 0.5*(nu_i+nu_j+TurbVar_i[0]+TurbVar_j[0])/sigma; - + /*--- Compute vector going from iPoint to jPoint ---*/ for (iDim = 0; iDim < nDim; iDim++) { Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; @@ -290,47 +453,51 @@ void CAvgGrad_AdjTurb::ComputeResidual(su2double *val_residual, su2double **val_ proj_vector_ij += Edge_Vector[iDim]*Normal[iDim]; } proj_vector_ij = proj_vector_ij/dist_ij_2; - + /*--- Mean gradient approximation ---*/ for (iVar = 0; iVar < nVar; iVar++) { Proj_Mean_GradTurbPsi_Edge[iVar] = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Mean_GradTurbPsi[iVar][iDim] = 0.5*(TurbPsi_Grad_i[iVar][iDim] + TurbPsi_Grad_j[iVar][iDim]); + Proj_Mean_GradTurbPsi_Edge[iVar] += Mean_GradTurbPsi[iVar][iDim]*Edge_Vector[iDim]; } - + + for (iDim = 0; iDim < nDim; iDim++) + Mean_GradTurbPsi[iVar][iDim] -= (Proj_Mean_GradTurbPsi_Edge[iVar] - (TurbPsi_j[iVar]-TurbPsi_i[iVar]))*Edge_Vector[iDim]/dist_ij_2; + /*--- Projection of the corrected gradient ---*/ Proj_Mean_GradTurbPsi_Corrected[iVar] = 0.0; for (iDim = 0; iDim < nDim; iDim++) Proj_Mean_GradTurbPsi_Corrected[iVar] += Mean_GradTurbPsi[iVar][iDim]*Normal[iDim]; } - + val_residual[0] = -nu_e*Proj_Mean_GradTurbPsi_Corrected[0]; - + if (implicit) { val_Jacobian_i[0][0] = nu_e*proj_vector_ij; val_Jacobian_j[0][0] = -nu_e*proj_vector_ij; } - + } -void CAvgGrad_AdjTurb::ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, +void CAvgGradCorrected_AdjTurb::ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { - + bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); - + su2double sigma = 2./3.; su2double nu_i, nu_j, nu_e_i, nu_e_j; su2double dist_ij_2 = 0; su2double proj_vector_ij = 0; unsigned short iVar, iDim; - + /*--- Compute mean effective viscosity ---*/ nu_i = Laminar_Viscosity_i/U_i[0]; nu_j = Laminar_Viscosity_j/U_j[0]; nu_e_i = (nu_i+TurbVar_i[0])/sigma; nu_e_j = (nu_j+TurbVar_j[0])/sigma; - + /*--- Compute vector going from iPoint to jPoint ---*/ for (iDim = 0; iDim < nDim; iDim++) { Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; @@ -338,201 +505,33 @@ void CAvgGrad_AdjTurb::ComputeResidual(su2double *val_residual_i, su2double *val proj_vector_ij += Edge_Vector[iDim]*Normal[iDim]; } proj_vector_ij = proj_vector_ij/dist_ij_2; // to normalize vectors - + /*--- Mean gradient approximation ---*/ for (iVar = 0; iVar < nVar; iVar++) { Proj_Mean_GradTurbPsi_Edge[iVar] = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Mean_GradTurbPsi[iVar][iDim] = 0.5*(TurbPsi_Grad_i[iVar][iDim] + TurbPsi_Grad_j[iVar][iDim]); + Proj_Mean_GradTurbPsi_Edge[iVar] += Mean_GradTurbPsi[iVar][iDim]*Edge_Vector[iDim]; } - + + for (iDim = 0; iDim < nDim; iDim++) + Mean_GradTurbPsi[iVar][iDim] -= (Proj_Mean_GradTurbPsi_Edge[iVar] - + (TurbPsi_j[iVar]-TurbPsi_i[iVar]))*Edge_Vector[iDim]/dist_ij_2; + /*--- Projection of the corrected gradient ---*/ Proj_Mean_GradTurbPsi_Corrected[iVar] = 0.0; for (iDim = 0; iDim < nDim; iDim++) Proj_Mean_GradTurbPsi_Corrected[iVar] += Mean_GradTurbPsi[iVar][iDim]*Normal[iDim]; } - + val_residual_i[0] = -nu_e_i*Proj_Mean_GradTurbPsi_Corrected[0]; val_residual_j[0] = nu_e_j*Proj_Mean_GradTurbPsi_Corrected[0]; - + if (implicit) { val_Jacobian_ii[0][0] = nu_e_i*proj_vector_ij; val_Jacobian_ij[0][0] = -nu_e_i*proj_vector_ij; val_Jacobian_ji[0][0] = -nu_e_j*proj_vector_ij; val_Jacobian_jj[0][0] = nu_e_j*proj_vector_ij; } - -} - -CSourcePieceWise_AdjTurb::CSourcePieceWise_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Velocity = new su2double [nDim]; - tau = new su2double* [nDim]; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - tau[iDim] = new su2double [nDim]; -} - -CSourcePieceWise_AdjTurb::~CSourcePieceWise_AdjTurb(void) { - delete [] Velocity; - - for (unsigned short iDim = 0; iDim < nDim; iDim++) - delete [] tau[iDim]; - delete [] tau; -} - -void CSourcePieceWise_AdjTurb::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - unsigned short iDim, jDim; - - bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); - su2double Prandtl_Turb = config->GetPrandtl_Turb(); - - val_residual[0] = 0.0; - if (implicit) - val_Jacobian_i[0][0] = 0.0; - - if (dist_i > 0.0) { - - /*--- Computation of Vorticity and Divergence of velocity ---*/ - su2double div_vel = 0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity[iDim] = U_i[iDim+1]/U_i[0]; - div_vel += PrimVar_Grad_i[iDim+1][iDim]; - } - - su2double Vorticity = (PrimVar_Grad_i[2][0]-PrimVar_Grad_i[1][1])*(PrimVar_Grad_i[2][0]-PrimVar_Grad_i[1][1]); - if (nDim == 3) - Vorticity += ( (PrimVar_Grad_i[3][1]-PrimVar_Grad_i[2][2])*(PrimVar_Grad_i[3][1]-PrimVar_Grad_i[2][2]) + - (PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0])*(PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0]) ); - Vorticity = sqrt(Vorticity); - - /*--- FIRST PART: -Bs*TurbPsi_i ---*/ - /*--- CLOUSURE CONSTANTS ---*/ - su2double cv1 = 7.1; - su2double cv1_3 = cv1*cv1*cv1; - su2double k = 0.41; - su2double k2 = k*k; - su2double cb1 = 0.1355; - su2double cw2 = 0.3; - su2double cw3_6 = pow(2.0,6.0); - su2double sigma = 2./3.; - su2double cb2 = 0.622; - su2double cw1 = cb1/k2+(1+cb2)/sigma; - - su2double nu, Ji, fv1, fv2, Shat, dist_0_2, Ji_2, Ji_3, one_o_oneplusJifv1; - su2double r, g, g_6, glim, fw; - su2double dTs_nuhat, dTs_Shat, dShat_nuhat, dTs_fw, dfw_g, dg_r, dr_nuhat, dr_Shat; - su2double dShat_fv2, dfv2_fv1, dfv1_Ji, dJi_nuhat, dfv2_Ji; - su2double Bs; - - dist_0_2 = dist_i*dist_i; - nu = Laminar_Viscosity_i/U_i[0]; - Ji = TurbVar_i[0]/nu; - Ji_2 = Ji*Ji; - Ji_3 = Ji_2*Ji; - fv1 = Ji_3/(Ji_3+cv1_3); - one_o_oneplusJifv1 = 1.0/(1.0+Ji*fv1); - fv2 = 1.0 - Ji*one_o_oneplusJifv1; - Shat = max(Vorticity + TurbVar_i[0]*fv2/(k2*dist_0_2), TURB_EPS); - - // r = TurbVar_i[0]/(Shat*k2*dist_0_2); - r = min(TurbVar_i[0]/(Shat*k2*dist_0_2),10.); - g = r + cw2*(pow(r,6.)-r); - g_6 = pow(g,6.); - glim = pow((1+cw3_6)/(g_6+cw3_6),1./6.); - fw = g*glim; - - dTs_nuhat = cb1*Shat-2.0*cw1*fw*TurbVar_i[0]/dist_0_2; - dTs_Shat = cb1*TurbVar_i[0]; - dTs_fw = -cw1*TurbVar_i[0]*TurbVar_i[0]/dist_0_2; - dfw_g = glim*cw3_6/(g_6+cw3_6); - dg_r = 1.0 + cw2*(6.0*pow(r,5.0)-1.0); - dr_nuhat = 1.0/(Shat*k2*dist_0_2); - dr_Shat = -dr_nuhat*TurbVar_i[0]/Shat; - - dShat_nuhat = fv2/(k2*dist_0_2); - dShat_fv2 = TurbVar_i[0]/(k2*dist_0_2); - dfv2_fv1 = Ji_2*one_o_oneplusJifv1*one_o_oneplusJifv1; - dfv1_Ji = 3.0*cv1_3*Ji_2/((Ji_3+cv1_3)*(Ji_3+cv1_3)); - dJi_nuhat = 1.0/nu; - dfv2_Ji = -one_o_oneplusJifv1*one_o_oneplusJifv1; - dShat_nuhat += dShat_fv2*(dfv2_fv1*dfv1_Ji+dfv2_Ji)*dJi_nuhat; - - Bs = dTs_nuhat; // nu_hat term - Bs += dTs_Shat*dShat_nuhat; // S_hat term - Bs += dTs_fw*dfw_g*dg_r*(dr_nuhat+dr_Shat*dShat_nuhat); // fw terms - - val_residual[0] = -Bs*TurbPsi_i[0]*Volume; - - if (implicit) - val_Jacobian_i[0][0] = -Bs*Volume; - - /*---SECOND PART: \partial_nu_hat mu^k F^{vk} cdot \grad Psi ---*/ - su2double dEddyVisc_nuhat; - if (!config->GetFrozen_Visc_Cont()) - dEddyVisc_nuhat = U_i[0]*fv1*(1.0 + 3.0*cv1_3/(Ji_3+cv1_3)); - else - dEddyVisc_nuhat = 0; - - for (iDim = 0; iDim < nDim; iDim++) { - for (jDim = 0; jDim < nDim; jDim++) - tau[iDim][jDim] = PrimVar_Grad_i[iDim+1][jDim] + PrimVar_Grad_i[jDim+1][iDim]; - tau[iDim][iDim] -= TWO3*div_vel; - } - - su2double Gas_Constant = config->GetGas_ConstantND(); - su2double Cp = (Gamma/Gamma_Minus_One)*Gas_Constant; - su2double tau_gradphi = 0.0, vel_tau_gradpsi5 = 0.0, gradT_gradpsi5 = 0.0; - - for (iDim = 0; iDim < nDim; iDim++) { - gradT_gradpsi5 += PrimVar_Grad_i[0][iDim]*PsiVar_Grad_i[nVar-1][iDim]; - for (jDim = 0; jDim < nDim; jDim++) { - tau_gradphi += tau[iDim][jDim]*PsiVar_Grad_i[iDim+1][jDim]; - vel_tau_gradpsi5 += Velocity[iDim]*tau[iDim][jDim]*PsiVar_Grad_i[nVar-1][jDim]; - } - } - val_residual[0] += (tau_gradphi + vel_tau_gradpsi5 + Cp/Prandtl_Turb*gradT_gradpsi5)*dEddyVisc_nuhat*Volume; - - } -} -CSourceConservative_AdjTurb::CSourceConservative_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - -} - -CSourceConservative_AdjTurb::~CSourceConservative_AdjTurb(void) { -} - -void CSourceConservative_AdjTurb::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - /*--- SOURCE term --> \nabla ( \psi_\mu \B7 E^{s} ) - E^{s} = 2 c_{b2}/\sigma \nabla \hat{nu} ---*/ - - unsigned short iDim; - bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); - - su2double cb2 = 0.622; - su2double sigma = 2./3.; - su2double coeff = 2.0*cb2/sigma; - su2double E_ij, proj_TurbVar_Grad_i, proj_TurbVar_Grad_j; - - E_ij = 0.0; proj_TurbVar_Grad_i = 0.0; proj_TurbVar_Grad_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - proj_TurbVar_Grad_i += coeff*TurbVar_Grad_i[0][iDim]*Normal[iDim]; - proj_TurbVar_Grad_j += coeff*TurbVar_Grad_j[0][iDim]*Normal[iDim]; - E_ij += 0.5*(TurbPsi_i[0]*proj_TurbVar_Grad_i + TurbPsi_j[0]*proj_TurbVar_Grad_j); - } - - val_residual[0] = E_ij; - - if (implicit) { - val_Jacobian_i[0][0] = 0.5*proj_TurbVar_Grad_i; - val_Jacobian_j[0][0] = 0.5*proj_TurbVar_Grad_j; - } - } diff --git a/SU2_CFD/src/numerics/continuous_adjoint/adj_sources.cpp b/SU2_CFD/src/numerics/continuous_adjoint/adj_sources.cpp new file mode 100644 index 000000000000..8c0b67dcb354 --- /dev/null +++ b/SU2_CFD/src/numerics/continuous_adjoint/adj_sources.cpp @@ -0,0 +1,782 @@ +/*! + * \file adj_sources.cpp + * \brief Implementation of adjoint source numerics classes. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/numerics/continuous_adjoint/adj_sources.hpp" + +CSourceAxisymmetric_AdjFlow::CSourceAxisymmetric_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { } + +CSourceAxisymmetric_AdjFlow::~CSourceAxisymmetric_AdjFlow(void) { } + +void CSourceAxisymmetric_AdjFlow::ComputeResidual(su2double *val_residual, su2double **Jacobian_ii, CConfig *config) { + + su2double yinv; + su2double Jacobian_Axisymmetric[4][4]; + + if (Coord_i[1] > 0.0) yinv = 1.0/Coord_i[1]; + else yinv = 0.0; + + Jacobian_Axisymmetric[0][0] = 0; + Jacobian_Axisymmetric[0][1] = 0; + Jacobian_Axisymmetric[0][2] = 1.; + Jacobian_Axisymmetric[0][3] = 0; + + Jacobian_Axisymmetric[1][0] = -U_i[1]*U_i[2]/(U_i[0]*U_i[0]); + Jacobian_Axisymmetric[1][1] = U_i[2]/U_i[0]; + Jacobian_Axisymmetric[1][2] = U_i[1]/U_i[0]; + Jacobian_Axisymmetric[1][3] = 0; + + Jacobian_Axisymmetric[2][0] = -U_i[2]*U_i[2]/(U_i[0]*U_i[0]); + Jacobian_Axisymmetric[2][1] = 0; + Jacobian_Axisymmetric[2][2] = 2*U_i[2]/U_i[0]; + Jacobian_Axisymmetric[2][3] = 0; + + Jacobian_Axisymmetric[3][0] = -Gamma*U_i[2]*U_i[3]/(U_i[0]*U_i[0]) + (Gamma-1)*U_i[2]*(U_i[1]*U_i[1]+U_i[2]*U_i[2])/(U_i[0]*U_i[0]*U_i[0]); + Jacobian_Axisymmetric[3][1] = -(Gamma-1)*U_i[2]*U_i[1]/(U_i[0]*U_i[0]); + Jacobian_Axisymmetric[3][2] = Gamma*U_i[3]/U_i[0] - 1/2*(Gamma-1)*( (U_i[1]*U_i[1]+U_i[2]*U_i[2])/(U_i[0]*U_i[0]) + 2*U_i[2]*U_i[2]/(U_i[0]*U_i[0]) ); + Jacobian_Axisymmetric[3][3] = Gamma*U_i[2]/U_i[0]; + + for (int iVar=0; iVar<4; iVar++) + for (int jVar=0; jVar<4; jVar++) + Jacobian_Axisymmetric[iVar][jVar] *= yinv*Volume; + + /* -- Residual = transpose(Jacobian) * psi --*/ + for (int iVar = 0; iVar < nVar; iVar++) { + val_residual[iVar] = 0.0; + for (int jVar = 0; jVar < nVar; jVar++) { + val_residual[iVar] += Jacobian_Axisymmetric[jVar][iVar]*Psi_i[jVar]; + Jacobian_ii[iVar][jVar] = Jacobian_Axisymmetric[jVar][iVar]; + } + } +} + +CSourceConservative_AdjFlow::CSourceConservative_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + Velocity = new su2double [nDim]; + Residual_i = new su2double [nVar]; + Residual_j = new su2double [nVar]; + Mean_Residual = new su2double [nVar]; + + Mean_PrimVar_Grad = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) + Mean_PrimVar_Grad[iVar] = new su2double [nDim]; +} + +CSourceConservative_AdjFlow::~CSourceConservative_AdjFlow(void) { + delete [] Mean_Residual; + delete [] Residual_j; + delete [] Residual_i; + delete [] Velocity; + + for (unsigned short iVar = 0; iVar < nVar; iVar++) + delete [] Mean_PrimVar_Grad[iVar]; + delete [] Mean_PrimVar_Grad; +} + +void CSourceConservative_AdjFlow::ComputeResidual (su2double *val_residual, CConfig *config) { + unsigned short iDim, jDim, iVar; + su2double rho, nu, Ji, fv1, fv2, Omega, Shat, dist_sq, Ji_2, Ji_3, one_o_oneplusJifv1; + su2double r, g, g_6, glim, dfw_g, dg_r, dr_nuhat, dr_Shat, Ms_coeff, invOmega; + + su2double cv1_3 = 7.1*7.1*7.1; + su2double k2 = 0.41*0.41; + su2double cb1 = 0.1355; + su2double cw2 = 0.3; + su2double cw3_6 = pow(2.0,6.0); + su2double sigma = 2./3.; + su2double cb2 = 0.622; + su2double cw1 = cb1/k2+(1+cb2)/sigma; + + for (iVar = 0; iVar < nVar; iVar++) { + Residual_i[iVar] = 0.0; + Residual_j[iVar] = 0.0; + } + + /*--- iPoint ---*/ + + /*--- Density and velocities ---*/ + + rho = U_i[0]; + for (iDim = 0; iDim < nDim; iDim++) + Velocity[iDim] = U_i[iDim+1]/rho; + + /*--- Vorticity ---*/ + + Omega = (PrimVar_Grad_i[1][1]-PrimVar_Grad_i[2][0])*(PrimVar_Grad_i[1][1]-PrimVar_Grad_i[2][0]); + if (nDim == 3) Omega += (PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0])*(PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0]) + + (PrimVar_Grad_i[2][2]-PrimVar_Grad_i[3][1])*(PrimVar_Grad_i[2][2]-PrimVar_Grad_i[3][1]); + Omega = sqrt(Omega); + invOmega = 1.0/(Omega + TURB_EPS); + + /*--- Compute Ms_coeff -> coming from partial derivatives ---*/ + + Ms_coeff = 0.0; + if (dist_i > 0) { + dist_sq = dist_i*dist_i; + nu = Laminar_Viscosity_i/rho; + Ji = TurbVar_i[0]/nu; + Ji_2 = Ji*Ji; + Ji_3 = Ji_2*Ji; + fv1 = Ji_3/(Ji_3+cv1_3); + one_o_oneplusJifv1 = 1.0/(1.0+Ji*fv1); + fv2 = 1.0 - Ji*one_o_oneplusJifv1; + Shat = max(Omega + TurbVar_i[0]*fv2/(k2*dist_sq), TURB_EPS); + + r = min(TurbVar_i[0]/(Shat*k2*dist_sq),10.); + g = r + cw2*(pow(r,6.)-r); + g_6 = pow(g,6.); + glim = pow((1+cw3_6)/(g_6+cw3_6),1./6.); + + dfw_g = glim*cw3_6/(g_6+cw3_6); + dg_r = 1.0 + cw2*(6.0*pow(r,5.0)-1.0); + dr_nuhat = 1.0/(Shat*k2*dist_sq); + dr_Shat = -dr_nuhat*TurbVar_i[0]/Shat; + + Ms_coeff = (cb1*TurbVar_i[0]-cw1*TurbVar_i[0]*TurbVar_i[0]/dist_sq*dfw_g*dg_r*dr_Shat); + } + Ms_coeff *= TurbPsi_i[0]*invOmega/rho; + + /*--- Compute residual of iPoint ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + for (jDim = 0; jDim < nDim; jDim++) { + Residual_i[0] -= Ms_coeff*(Velocity[jDim]*PrimVar_Grad_i[jDim+1][iDim]*Normal[iDim] - + Velocity[jDim]*PrimVar_Grad_i[iDim+1][jDim]*Normal[iDim]); + Residual_i[iDim+1] += Ms_coeff*(PrimVar_Grad_i[iDim+1][jDim]*Normal[jDim] - + PrimVar_Grad_i[jDim+1][iDim]*Normal[jDim]); + } + } + + /*--- jPoint ---*/ + + /*--- Density and velocities ---*/ + + rho = U_j[0]; + for (iDim = 0; iDim < nDim; iDim++) + Velocity[iDim] = U_j[iDim+1]/rho; + + /*--- Vorticity ---*/ + + Omega = (PrimVar_Grad_j[1][1]-PrimVar_Grad_j[2][0])*(PrimVar_Grad_j[1][1]-PrimVar_Grad_j[2][0]); + if (nDim == 3) Omega += (PrimVar_Grad_j[1][2]-PrimVar_Grad_j[3][0])*(PrimVar_Grad_j[1][2]-PrimVar_Grad_j[3][0]) + + (PrimVar_Grad_j[2][2]-PrimVar_Grad_j[3][1])*(PrimVar_Grad_j[2][2]-PrimVar_Grad_j[3][1]); + Omega = sqrt(Omega); + invOmega = 1.0/(Omega + TURB_EPS); + + /*--- Compute Ms_coeff -> coming from partial derivatives ---*/ + + Ms_coeff = 0.0; + if (dist_j > 0) { + dist_sq = dist_j*dist_j; + nu = Laminar_Viscosity_j/rho; + Ji = TurbVar_j[0]/nu; + Ji_2 = Ji*Ji; + Ji_3 = Ji_2*Ji; + fv1 = Ji_3/(Ji_3+cv1_3); + one_o_oneplusJifv1 = 1.0/(1.0+Ji*fv1); + fv2 = 1.0 - Ji*one_o_oneplusJifv1; + Shat = max(Omega + TurbVar_j[0]*fv2/(k2*dist_sq), TURB_EPS); + + r = min(TurbVar_j[0]/(Shat*k2*dist_sq),10.); + g = r + cw2*(pow(r,6.)-r); + g_6 = pow(g,6.); + glim = pow((1+cw3_6)/(g_6+cw3_6),1./6.); + + dfw_g = glim*cw3_6/(g_6+cw3_6); + dg_r = 1.0 + cw2*(6.0*pow(r,5.0)-1.0); + dr_nuhat = 1.0/(Shat*k2*dist_sq); + dr_Shat = -dr_nuhat*TurbVar_j[0]/Shat; + + Ms_coeff = (cb1*TurbVar_j[0]-cw1*TurbVar_j[0]*TurbVar_j[0]/dist_sq*dfw_g*dg_r*dr_Shat); + } + Ms_coeff *= TurbPsi_j[0]*invOmega/rho; + + /*--- Compute residual of jPoint ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + for (jDim = 0; jDim < nDim; jDim++) { + Residual_j[0] -= Ms_coeff*(Velocity[jDim]*PrimVar_Grad_j[jDim+1][iDim]*Normal[iDim] - + Velocity[jDim]*PrimVar_Grad_j[iDim+1][jDim]*Normal[iDim]); + Residual_j[iDim+1] += Ms_coeff*(PrimVar_Grad_j[iDim+1][jDim]*Normal[jDim] - + PrimVar_Grad_j[jDim+1][iDim]*Normal[jDim]); + } + } + + /*--- Compute the mean residual ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + val_residual[iVar] = 0.5*(Residual_i[iVar] + Residual_j[iVar]); + +} + +CSourceRotatingFrame_AdjFlow::CSourceRotatingFrame_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : + CNumerics(val_nDim, val_nVar, config) { } + +CSourceRotatingFrame_AdjFlow::~CSourceRotatingFrame_AdjFlow(void) { } + +void CSourceRotatingFrame_AdjFlow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) { + + unsigned short iDim, iVar, jVar; + su2double Omega[3] = {0,0,0}, Phi[3] = {0,0,0}; + bool implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); + + /*--- Retrieve the angular velocity vector from config. ---*/ + + for (iDim = 0; iDim < 3; iDim++){ + Omega[iDim] = config->GetRotation_Rate(iDim)/config->GetOmega_Ref(); + } + + /*--- Get the adjoint velocity vector at the current node. ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + Phi[iDim] = Psi_i[iDim+1]; + + /*--- Compute the source term as the Jacobian of the rotating frame + source term multiplied by the adjoint state and the dual cell volume. ---*/ + + if (nDim == 2) { + val_residual[0] = 0.0; + val_residual[1] = Omega[2]*Phi[1]*Volume; + val_residual[2] = -Omega[2]*Phi[0]*Volume; + val_residual[3] = 0.0; + } else { + val_residual[0] = 0.0; + val_residual[1] = (Omega[2]*Phi[1] - Omega[1]*Phi[2])*Volume; + val_residual[2] = (Omega[0]*Phi[2] - Omega[2]*Phi[0])*Volume; + val_residual[3] = (Omega[1]*Phi[0] - Omega[0]*Phi[1])*Volume; + val_residual[4] = 0.0; + } + + /*--- Calculate the source term Jacobian ---*/ + + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + val_Jacobian_i[iVar][jVar] = 0.0; + if (nDim == 2) { + val_Jacobian_i[1][2] = Omega[2]*Volume; + val_Jacobian_i[2][1] = -Omega[2]*Volume; + } else { + val_Jacobian_i[1][2] = Omega[2]*Volume; + val_Jacobian_i[1][3] = -Omega[1]*Volume; + val_Jacobian_i[2][1] = -Omega[2]*Volume; + val_Jacobian_i[2][3] = Omega[0]*Volume; + val_Jacobian_i[3][1] = Omega[1]*Volume; + val_Jacobian_i[3][2] = -Omega[0]*Volume; + } + } + +} + +CSourceViscous_AdjFlow::CSourceViscous_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : + CNumerics(val_nDim, val_nVar, config) { + unsigned short iDim; + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + Velocity = new su2double [nVar]; + GradDensity = new su2double [nDim]; + GradInvDensity = new su2double [nDim]; + dPoDensity2 = new su2double [nDim]; + alpha = new su2double [nDim]; + beta = new su2double [nDim]; + Sigma_5_vec = new su2double [nDim]; + + GradVel_o_Rho = new su2double* [nDim]; + sigma = new su2double* [nDim]; + Sigma_phi = new su2double* [nDim]; + Sigma_5_Tensor = new su2double* [nDim]; + Sigma = new su2double* [nDim]; + + for (iDim = 0; iDim < nDim; iDim++) { + GradVel_o_Rho[iDim] = new su2double [nDim]; + sigma[iDim] = new su2double [nDim]; + Sigma_phi[iDim] = new su2double [nDim]; + Sigma_5_Tensor[iDim] = new su2double [nDim]; + Sigma[iDim] = new su2double [nDim]; + } + +} + +CSourceViscous_AdjFlow::~CSourceViscous_AdjFlow(void) { + unsigned short iDim; + + for (iDim = 0; iDim < nDim; iDim++) { + delete [] GradVel_o_Rho[iDim]; + delete [] sigma[iDim]; + delete [] Sigma_phi[iDim]; + delete [] Sigma_5_Tensor[iDim]; + delete [] Sigma[iDim]; + } + + delete [] GradVel_o_Rho; + delete [] sigma; + delete [] Sigma_phi; + delete [] Sigma_5_Tensor; + delete [] Sigma; + + delete [] Velocity; + delete [] GradDensity; + delete [] GradInvDensity; + delete [] dPoDensity2; + delete [] alpha; + delete [] beta; + delete [] Sigma_5_vec; + +} + +void CSourceViscous_AdjFlow::ComputeResidual (su2double *val_residual, CConfig *config) { + + unsigned short iDim, jDim; + +// su2double Temperature = V_i[0]; + su2double Pressure = V_i[nDim+1]; + su2double Density = V_i[nDim+2]; +// su2double Enthalpy = V_i[nDim+3]; + su2double Laminar_Viscosity = V_i[nDim+5]; + su2double Eddy_Viscosity = V_i[nDim+6]; + +// su2double Energy = Enthalpy - Pressure/Density; + su2double invDensity = 1.0/Density; + su2double invDensitysq = invDensity*invDensity; + su2double invDensitycube = invDensitysq*invDensity; + su2double Prandtl_Lam = config->GetPrandtl_Lam(); + su2double Prandtl_Turb = config->GetPrandtl_Turb(); + su2double mu_tot_1 = Laminar_Viscosity + Eddy_Viscosity; + su2double mu_tot_2 = Laminar_Viscosity/Prandtl_Lam + Eddy_Viscosity/Prandtl_Turb; +// su2double Gas_Constant = config->GetGas_ConstantND(); + + /*--- Required gradients of the flow variables, point j ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + + /*--- Gradient density ---*/ + + GradDensity[iDim] = PrimVar_Grad_i[nDim+2][iDim]; + + /*--- Gradient (1/rho) ---*/ + + GradInvDensity[iDim] = -GradDensity[iDim]*invDensitysq; + + /*--- Computation of the derivatives of P/(Density^2) ---*/ + + dPoDensity2[iDim] = (PrimVar_Grad_i[nVar-1][iDim]*Density - 2.0*GradDensity[iDim]*Pressure)*invDensitycube; + + /*--- Abbreviations: alpha, beta, sigma_5_vec ---*/ + + alpha[iDim] = Gamma*mu_tot_2*GradInvDensity[iDim]; + beta[iDim] = Gamma*mu_tot_2*dPoDensity2[iDim]/Gamma_Minus_One; + Sigma_5_vec[iDim] = Gamma*mu_tot_2*PsiVar_Grad_i[nVar-1][iDim]; + + } + + /*--- Definition of tensors and derivatives of velocity over density ---*/ + + su2double div_vel = 0.0, div_phi = 0.0, vel_gradpsi5 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + div_vel += PrimVar_Grad_i[iDim+1][iDim]; + div_phi += PsiVar_Grad_i[iDim+1][iDim]; + vel_gradpsi5 += V_i[iDim+1]*PsiVar_Grad_i[nVar-1][iDim]; + for (jDim = 0; jDim < nDim; jDim++) { + sigma[iDim][jDim] = mu_tot_1*(PrimVar_Grad_i[iDim+1][jDim]+PrimVar_Grad_i[jDim+1][iDim]); + Sigma_phi[iDim][jDim] = mu_tot_1*(PsiVar_Grad_i[iDim+1][jDim]+PsiVar_Grad_i[jDim+1][iDim]); + Sigma_5_Tensor[iDim][jDim] = mu_tot_1*(V_i[jDim+1]*PsiVar_Grad_i[nVar-1][iDim]+V_i[iDim+1]*PsiVar_Grad_i[nVar-1][jDim]); + GradVel_o_Rho[iDim][jDim] = (PrimVar_Grad_i[iDim+1][jDim]*Density - V_i[iDim+1]*GradDensity[jDim])*invDensitysq; + } + } + + for (iDim = 0; iDim < nDim; iDim++) { + sigma[iDim][iDim] -= TWO3*mu_tot_1*div_vel; + Sigma_phi[iDim][iDim] -= TWO3*mu_tot_1*div_phi; + Sigma_5_Tensor[iDim][iDim] -= TWO3*mu_tot_1*vel_gradpsi5; + } + + for (iDim = 0; iDim < nDim; iDim++) { + for (jDim = 0; jDim < nDim; jDim++) { + Sigma[iDim][jDim] = Sigma_phi[iDim][jDim] + Sigma_5_Tensor[iDim][jDim]; + } + } + + /*--- Vector-Tensors products ---*/ + + su2double gradT_gradpsi5 = 0.0, sigma_gradpsi = 0.0, vel_sigma_gradpsi5 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + gradT_gradpsi5 += PrimVar_Grad_i[0][iDim]*PsiVar_Grad_i[nVar-1][iDim]; + for (jDim = 0; jDim < nDim; jDim++) { + sigma_gradpsi += sigma[iDim][jDim]*PsiVar_Grad_i[jDim+1][iDim]; + vel_sigma_gradpsi5 += V_i[iDim+1]*sigma[iDim][jDim]*PsiVar_Grad_i[nVar-1][jDim]; + } + } + + /*--- Residuals ---*/ + + su2double alpha_gradpsi5 = 0.0, beta_gradpsi5 = 0.0, Sigma_gradvel_o_rho = 0.0, Sigma5_vel_gradvel = 0.0, sq_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + alpha_gradpsi5 += alpha[iDim]*PsiVar_Grad_i[nVar-1][iDim]; + beta_gradpsi5 += beta[iDim]*PsiVar_Grad_i[nVar-1][iDim]; + for (jDim = 0; jDim < nDim; jDim++) { + Sigma_gradvel_o_rho += Sigma[iDim][jDim]*GradVel_o_Rho[iDim][jDim]; + Sigma5_vel_gradvel += Sigma_5_vec[iDim]*(V_i[jDim+1]*PrimVar_Grad_i[jDim+1][iDim]); + } + sq_vel += V_i[iDim+1]*V_i[iDim+1]; + } + + val_residual[0] = (-vel_sigma_gradpsi5*invDensity + 0.5*sq_vel*alpha_gradpsi5 - + beta_gradpsi5) * Volume; + for (iDim = 0; iDim < nDim; iDim++) { + val_residual[iDim+1] = 0.0; + for (jDim = 0; jDim < nDim; jDim++) { + val_residual[iDim+1] += (sigma[iDim][jDim]*PsiVar_Grad_i[nVar-1][jDim]*invDensity - V_i[iDim+1]*alpha[jDim]*PsiVar_Grad_i[nVar-1][jDim]) * Volume; + } + } + val_residual[nVar-1] = alpha_gradpsi5 * Volume; + +// val_residual[0] += (Sigma5_vel_gradvel*invDensity - Sigma_gradvel_o_rho) * Volume; +// for (iDim = 0; iDim < nDim; iDim++) { +// for (jDim = 0; jDim < nDim; jDim++) { +// val_residual[iDim+1] += (Sigma[iDim][jDim]*GradInvDensity[jDim] - +// Sigma_5_vec[jDim]*PrimVar_Grad_i[iDim+1][jDim]*invDensity) * Volume; +// } +// } + + /*--- Laminar viscosity sensitivity for NS ---*/ + + if (config->GetKind_Solver() != ADJ_RANS) { + +// su2double Temperature_Ref = config->GetTemperature_Ref(); +// su2double Temperature_Dim = Temperature*Temperature_Ref; +// +// su2double S = 0.0; +// if (config->GetSystemMeasurements() == SI) { S = 110.4; } +// if (config->GetSystemMeasurements() == US) { S = 198.72; } +// su2double dVisc_T = ((Laminar_Viscosity)/(2.0*Temperature_Dim*(Temperature_Dim + S)))*(Temperature_Dim + 3.0*S)*Temperature_Ref; +// +// su2double Cp = (Gamma/Gamma_Minus_One)*Gas_Constant; +// su2double kappa_psi = (sigma_gradpsi + vel_sigma_gradpsi5)/mu_tot_1; +// su2double theta = (kappa_psi + Cp/Prandtl_Lam*gradT_gradpsi5)*dVisc_T*Gamma_Minus_One/(Gas_Constant*Density); +// +// val_residual[0] += (theta*(sq_vel-Energy))*Volume; +// for (iDim = 0; iDim < nDim; iDim++) +// val_residual[iDim+1] -= theta*V_i[iDim+1]*Volume; +// val_residual[nVar-1] += theta*Volume; + + } + +// /*--- Coupling terms coming from the continuous adjoint turbulent equations ---*/ +// +// if ((config->GetKind_Solver() == ADJ_RANS) && (!config->GetFrozen_Visc_Cont())) { +// +// /*--- Closure constants ---*/ +// +// su2double cv1_3 = 7.1*7.1*7.1; +// su2double k2 = 0.41*0.41; +// su2double cb1 = 0.1355; +// su2double cw2 = 0.3; +// su2double cw3_6 = pow(2.0,6.0); +// su2double sigma = 2./3.; +// su2double cb2 = 0.622; +// su2double cw1 = cb1/k2+(1+cb2)/sigma; +// +// su2double nu, Ji, Ji_2, Ji_3, fv1; +// nu = Laminar_Viscosity/Density; +// Ji = TurbVar_i[0]/nu; +// Ji_2 = Ji*Ji; +// Ji_3 = Ji_2*Ji; +// fv1 = Ji_3/(Ji_3+cv1_3); +// +// /*--- Contributions due to variation of viscosities ---*/ +// +// su2double Temperature_Ref = config->GetTemperature_Ref(); +// su2double Temperature_Dim = Temperature*Temperature_Ref; +// +// su2double S = 0.0; +// if (config->GetSystemMeasurements() == SI) { S = 110.4; } +// if (config->GetSystemMeasurements() == US) { S = 198.72; } +// su2double dVisc_T = ((Laminar_Viscosity)/(2.0*Temperature_Dim*(Temperature_Dim + S)))*(Temperature_Dim + 3.0*S)*Temperature_Ref; +// +// su2double Cp = (Gamma/Gamma_Minus_One)*Gas_Constant; +// su2double kappa_psi = (sigma_gradpsi + vel_sigma_gradpsi5)/mu_tot_1 + Cp/Prandtl_Turb*gradT_gradpsi5; +// su2double cv1_const = 3.0*cv1_3/(Ji_3+cv1_3); +// su2double theta = (kappa_psi*(1.0-Eddy_Viscosity/Laminar_Viscosity*cv1_const) - +// Cp/Prandtl_Turb*gradT_gradpsi5*(1.0-Prandtl_Turb/Prandtl_Lam))*dVisc_T*Gamma_Minus_One/(Gas_Constant*Density); +// su2double xi = kappa_psi*(1.0+cv1_const)*Eddy_Viscosity/Density; +// +// val_residual[0] += (theta*(sq_vel-Energy) + xi)*Volume; +// for (iDim = 0; iDim < nDim; iDim++) +// val_residual[iDim+1] -= theta*V_i[iDim+1]*Volume; +// val_residual[nVar-1] += theta*Volume; +// +// /*--- Coupling residuals ---*/ +// +// if (dist_i > 0.0) { +// su2double fv2, Omega, Shat, dist_0_2, one_o_oneplusJifv1; +// su2double r, g, g_6, glim, fw; +// su2double dfw_g, dg_r, dr_nuhat, dr_Shat; +// su2double dShat_fv2, dfv2_fv1, dfv1_Ji, dJi_nu, dJi_nuhat, dfv2_Ji; +// +// /*--- Vorticity ---*/ +// Omega = (PrimVar_Grad_i[1][1]-PrimVar_Grad_i[2][0])*(PrimVar_Grad_i[1][1]-PrimVar_Grad_i[2][0]); +// if (nDim == 3) Omega += (PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0])*(PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0]) + +// (PrimVar_Grad_i[2][2]-PrimVar_Grad_i[3][1])*(PrimVar_Grad_i[2][2]-PrimVar_Grad_i[3][1]); +// Omega = sqrt(Omega); +// +// dist_0_2 = dist_i*dist_i; +// one_o_oneplusJifv1 = 1.0/(1.0+Ji*fv1); +// fv2 = 1.0 - Ji*one_o_oneplusJifv1; +// Shat = max(Omega + TurbVar_i[0]*fv2/(k2*dist_0_2), TURB_EPS); +// +// r = min(TurbVar_i[0]/(Shat*k2*dist_0_2), 10.); +// g = r + cw2*(pow(r,6.)-r); +// g_6 = pow(g,6.); +// glim = pow((1+cw3_6)/(g_6+cw3_6),1./6.); +// fw = g*glim; +// +// dfw_g = glim*cw3_6/(g_6+cw3_6); +// dg_r = 1.0 + cw2*(6.0*pow(r,5.0)-1.0); +// dr_nuhat = 1.0/(Shat*k2*dist_0_2); +// dr_Shat = -dr_nuhat*TurbVar_i[0]/Shat; +// +// dShat_fv2 = TurbVar_i[0]/(k2*dist_0_2); +// dfv2_fv1 = Ji_2*one_o_oneplusJifv1*one_o_oneplusJifv1; +// dfv1_Ji = 3.0*cv1_3*Ji_2/((Ji_3+cv1_3)*(Ji_3+cv1_3)); +// dJi_nuhat = 1.0/nu; +// dJi_nu = -Ji/nu; +// dfv2_Ji = -one_o_oneplusJifv1*one_o_oneplusJifv1; +// +// /*--- Terms 1 & 2: -Fcv\B7nabla(TurbPsi_i) - Fs\B7TurbPsi_i ---*/ +// +// su2double gradTurbVar_gradTurbPsi = 0, vel_gradTurbPsi = 0; +// for (iDim = 0; iDim < nDim; iDim++) { +// gradTurbVar_gradTurbPsi += TurbVar_Grad_i[0][iDim]*TurbPsi_Grad_i[0][iDim]; +// vel_gradTurbPsi += V_i[iDim+1]*TurbPsi_Grad_i[0][iDim]; +// } +// +// su2double alpha_coeff = Gamma_Minus_One/(Gas_Constant*Density)*dVisc_T; +// su2double beta_coeff = alpha_coeff*(sq_vel-Energy)-Laminar_Viscosity_i/Density; +// su2double Fs_coeff = TurbPsi_i[0]*(cb1*TurbVar_i[0]-cw1*TurbVar_i[0]*TurbVar_i[0]/dist_0_2*dfw_g*dg_r*dr_Shat)* +// dShat_fv2*(dfv2_Ji+dfv2_fv1*dfv1_Ji)*dJi_nu; +// su2double Gamma = Fs_coeff - gradTurbVar_gradTurbPsi/sigma; +// +// val_residual[0] -= (Gamma*beta_coeff - TurbVar_i[0]*vel_gradTurbPsi)/Density*Volume; +// for (iDim = 0; iDim < nDim; iDim++) +// val_residual[iDim+1] += (Gamma*alpha_coeff*V_i[iDim+1] - TurbVar_i[0]*TurbPsi_Grad_i[0][iDim])/Density*Volume; +// val_residual[nVar-1] -= (Gamma*alpha_coeff)/Density*Volume; +// +// // this should improve stability (when commented): +// /*--- Terms 3: -partial{T^s}_GradVel x GradN ---*/ +// // su2double Ms_coeff = (cb1*TurbVar_i[0]-cw1*TurbVar_i[0]*TurbVar_i[0]/dist_0_2*dfw_g*dg_r*dr_Shat); +// // Ms_coeff *= TurbPsi_i[0]/(Omega + TURB_EPS); +// // +// // for (iDim = 0; iDim < nDim; iDim++) { +// // for (jDim = 0; jDim < nDim; jDim++) { +// // val_residual[0] += Ms_coeff*(PrimVar_Grad_i[iDim+1][jDim]-PrimVar_Grad_i[jDim+1][iDim])* +// // GradVel_o_Rho[iDim][jDim]*dV; +// // val_residual[iDim+1] -= Ms_coeff*(PrimVar_Grad_i[iDim+1][jDim]-PrimVar_Grad_i[jDim+1][iDim])* +// // GradInvDensity[jDim]*dV; +// // } +// // } +// +// } +// } + +} + +CSourceConservative_AdjTurb::CSourceConservative_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + +} + +CSourceConservative_AdjTurb::~CSourceConservative_AdjTurb(void) { +} + +void CSourceConservative_AdjTurb::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { + + /*--- SOURCE term --> \nabla ( \psi_\mu \B7 E^{s} ) + E^{s} = 2 c_{b2}/\sigma \nabla \hat{nu} ---*/ + + unsigned short iDim; + bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); + + su2double cb2 = 0.622; + su2double sigma = 2./3.; + su2double coeff = 2.0*cb2/sigma; + su2double E_ij, proj_TurbVar_Grad_i, proj_TurbVar_Grad_j; + + E_ij = 0.0; proj_TurbVar_Grad_i = 0.0; proj_TurbVar_Grad_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + proj_TurbVar_Grad_i += coeff*TurbVar_Grad_i[0][iDim]*Normal[iDim]; + proj_TurbVar_Grad_j += coeff*TurbVar_Grad_j[0][iDim]*Normal[iDim]; + E_ij += 0.5*(TurbPsi_i[0]*proj_TurbVar_Grad_i + TurbPsi_j[0]*proj_TurbVar_Grad_j); + } + + val_residual[0] = E_ij; + + if (implicit) { + val_Jacobian_i[0][0] = 0.5*proj_TurbVar_Grad_i; + val_Jacobian_j[0][0] = 0.5*proj_TurbVar_Grad_j; + } +} + + +CSourcePieceWise_AdjTurb::CSourcePieceWise_AdjTurb(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + Velocity = new su2double [nDim]; + tau = new su2double* [nDim]; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + tau[iDim] = new su2double [nDim]; +} + +CSourcePieceWise_AdjTurb::~CSourcePieceWise_AdjTurb(void) { + delete [] Velocity; + + for (unsigned short iDim = 0; iDim < nDim; iDim++) + delete [] tau[iDim]; + delete [] tau; +} + +void CSourcePieceWise_AdjTurb::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { + unsigned short iDim, jDim; + + bool implicit = (config->GetKind_TimeIntScheme_AdjTurb() == EULER_IMPLICIT); + su2double Prandtl_Turb = config->GetPrandtl_Turb(); + + val_residual[0] = 0.0; + if (implicit) + val_Jacobian_i[0][0] = 0.0; + + if (dist_i > 0.0) { + + /*--- Computation of Vorticity and Divergence of velocity ---*/ + su2double div_vel = 0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity[iDim] = U_i[iDim+1]/U_i[0]; + div_vel += PrimVar_Grad_i[iDim+1][iDim]; + } + + su2double Vorticity = (PrimVar_Grad_i[2][0]-PrimVar_Grad_i[1][1])*(PrimVar_Grad_i[2][0]-PrimVar_Grad_i[1][1]); + if (nDim == 3) + Vorticity += ( (PrimVar_Grad_i[3][1]-PrimVar_Grad_i[2][2])*(PrimVar_Grad_i[3][1]-PrimVar_Grad_i[2][2]) + + (PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0])*(PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0]) ); + Vorticity = sqrt(Vorticity); + + /*--- FIRST PART: -Bs*TurbPsi_i ---*/ + /*--- CLOUSURE CONSTANTS ---*/ + su2double cv1 = 7.1; + su2double cv1_3 = cv1*cv1*cv1; + su2double k = 0.41; + su2double k2 = k*k; + su2double cb1 = 0.1355; + su2double cw2 = 0.3; + su2double cw3_6 = pow(2.0,6.0); + su2double sigma = 2./3.; + su2double cb2 = 0.622; + su2double cw1 = cb1/k2+(1+cb2)/sigma; + + su2double nu, Ji, fv1, fv2, Shat, dist_0_2, Ji_2, Ji_3, one_o_oneplusJifv1; + su2double r, g, g_6, glim, fw; + su2double dTs_nuhat, dTs_Shat, dShat_nuhat, dTs_fw, dfw_g, dg_r, dr_nuhat, dr_Shat; + su2double dShat_fv2, dfv2_fv1, dfv1_Ji, dJi_nuhat, dfv2_Ji; + su2double Bs; + + dist_0_2 = dist_i*dist_i; + nu = Laminar_Viscosity_i/U_i[0]; + Ji = TurbVar_i[0]/nu; + Ji_2 = Ji*Ji; + Ji_3 = Ji_2*Ji; + fv1 = Ji_3/(Ji_3+cv1_3); + one_o_oneplusJifv1 = 1.0/(1.0+Ji*fv1); + fv2 = 1.0 - Ji*one_o_oneplusJifv1; + Shat = max(Vorticity + TurbVar_i[0]*fv2/(k2*dist_0_2), TURB_EPS); + + // r = TurbVar_i[0]/(Shat*k2*dist_0_2); + r = min(TurbVar_i[0]/(Shat*k2*dist_0_2),10.); + g = r + cw2*(pow(r,6.)-r); + g_6 = pow(g,6.); + glim = pow((1+cw3_6)/(g_6+cw3_6),1./6.); + fw = g*glim; + + dTs_nuhat = cb1*Shat-2.0*cw1*fw*TurbVar_i[0]/dist_0_2; + dTs_Shat = cb1*TurbVar_i[0]; + dTs_fw = -cw1*TurbVar_i[0]*TurbVar_i[0]/dist_0_2; + dfw_g = glim*cw3_6/(g_6+cw3_6); + dg_r = 1.0 + cw2*(6.0*pow(r,5.0)-1.0); + dr_nuhat = 1.0/(Shat*k2*dist_0_2); + dr_Shat = -dr_nuhat*TurbVar_i[0]/Shat; + + dShat_nuhat = fv2/(k2*dist_0_2); + dShat_fv2 = TurbVar_i[0]/(k2*dist_0_2); + dfv2_fv1 = Ji_2*one_o_oneplusJifv1*one_o_oneplusJifv1; + dfv1_Ji = 3.0*cv1_3*Ji_2/((Ji_3+cv1_3)*(Ji_3+cv1_3)); + dJi_nuhat = 1.0/nu; + dfv2_Ji = -one_o_oneplusJifv1*one_o_oneplusJifv1; + dShat_nuhat += dShat_fv2*(dfv2_fv1*dfv1_Ji+dfv2_Ji)*dJi_nuhat; + + Bs = dTs_nuhat; // nu_hat term + Bs += dTs_Shat*dShat_nuhat; // S_hat term + Bs += dTs_fw*dfw_g*dg_r*(dr_nuhat+dr_Shat*dShat_nuhat); // fw terms + + val_residual[0] = -Bs*TurbPsi_i[0]*Volume; + + if (implicit) + val_Jacobian_i[0][0] = -Bs*Volume; + + /*---SECOND PART: \partial_nu_hat mu^k F^{vk} cdot \grad Psi ---*/ + su2double dEddyVisc_nuhat; + if (!config->GetFrozen_Visc_Cont()) + dEddyVisc_nuhat = U_i[0]*fv1*(1.0 + 3.0*cv1_3/(Ji_3+cv1_3)); + else + dEddyVisc_nuhat = 0; + + for (iDim = 0; iDim < nDim; iDim++) { + for (jDim = 0; jDim < nDim; jDim++) + tau[iDim][jDim] = PrimVar_Grad_i[iDim+1][jDim] + PrimVar_Grad_i[jDim+1][iDim]; + tau[iDim][iDim] -= TWO3*div_vel; + } + + su2double Gas_Constant = config->GetGas_ConstantND(); + su2double Cp = (Gamma/Gamma_Minus_One)*Gas_Constant; + su2double tau_gradphi = 0.0, vel_tau_gradpsi5 = 0.0, gradT_gradpsi5 = 0.0; + + for (iDim = 0; iDim < nDim; iDim++) { + gradT_gradpsi5 += PrimVar_Grad_i[0][iDim]*PsiVar_Grad_i[nVar-1][iDim]; + for (jDim = 0; jDim < nDim; jDim++) { + tau_gradphi += tau[iDim][jDim]*PsiVar_Grad_i[iDim+1][jDim]; + vel_tau_gradpsi5 += Velocity[iDim]*tau[iDim][jDim]*PsiVar_Grad_i[nVar-1][jDim]; + } + } + val_residual[0] += (tau_gradphi + vel_tau_gradpsi5 + Cp/Prandtl_Turb*gradT_gradpsi5)*dEddyVisc_nuhat*Volume; + + } +} diff --git a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp index 11baa46308e6..b95fb52ea7bb 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEAElasticity.cpp @@ -1,13 +1,12 @@ /*! * \file CFEAElasticity.cpp - * \brief This file contains the routines for setting the tangent matrix and - * residual of a FEM linear elastic structural problem. + * \brief Base class for all elasticity problems. * \author R. Sanchez * \version 7.0.1 "Blackbird" * * 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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -31,7 +30,7 @@ CFEAElasticity::CFEAElasticity(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CNumerics() { + const CConfig *config) : CNumerics() { nDim = val_nDim; nVar = val_nVar; @@ -167,19 +166,19 @@ CFEAElasticity::~CFEAElasticity(void) { delete [] GradNi_Ref_Mat; delete [] GradNi_Curr_Mat; - if (DV_Val != nullptr) delete[] DV_Val; + delete[] DV_Val; - if (FAux_Dead_Load != nullptr) delete [] FAux_Dead_Load; + delete [] FAux_Dead_Load; - if (E_i != nullptr) delete [] E_i; - if (Nu_i != nullptr) delete [] Nu_i; - if (Rho_s_i != nullptr) delete [] Rho_s_i; - if (Rho_s_DL_i != nullptr) delete [] Rho_s_DL_i; - if (Ni_Vec != nullptr) delete [] Ni_Vec; + delete [] E_i; + delete [] Nu_i; + delete [] Rho_s_i; + delete [] Rho_s_DL_i; + delete [] Ni_Vec; } -void CFEAElasticity::Compute_Mass_Matrix(CElement *element, CConfig *config) { +void CFEAElasticity::Compute_Mass_Matrix(CElement *element, const CConfig *config) { /*--- Initialize values for the material model considered ---*/ SetElement_Properties(element, config); @@ -231,7 +230,7 @@ void CFEAElasticity::Compute_Mass_Matrix(CElement *element, CConfig *config) { } -void CFEAElasticity::Compute_Dead_Load(CElement *element, CConfig *config) { +void CFEAElasticity::Compute_Dead_Load(CElement *element, const CConfig *config) { /*--- Initialize values for the material model considered ---*/ SetElement_Properties(element, config); @@ -283,7 +282,7 @@ void CFEAElasticity::Compute_Dead_Load(CElement *element, CConfig *config) { } -void CFEAElasticity::SetElement_Properties(const CElement *element, CConfig *config) { +void CFEAElasticity::SetElement_Properties(const CElement *element, const CConfig *config) { /*--- These variables are set as preaccumulation inputs in Compute_Tangent_Matrix and Compute_NodalStress_Term, if you add variables here be sure to register them in those routines too. ---*/ @@ -312,7 +311,7 @@ void CFEAElasticity::SetElement_Properties(const CElement *element, CConfig *con } -void CFEAElasticity::ReadDV(CConfig *config) { +void CFEAElasticity::ReadDV(const CConfig *config) { int rank = SU2_MPI::GetRank(); bool master_node = false; diff --git a/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp index 37549738ea7c..f29f07f00956 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEALinearElasticity.cpp @@ -1,12 +1,12 @@ /*! * \file CFEALinearElasticity.cpp - * \brief This file contains the routines for setting the FEM elastic structural problem. + * \brief Classes for linear elasticity problems. * \author R. Sanchez * \version 7.0.1 "Blackbird" * * 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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -29,14 +29,14 @@ CFEALinearElasticity::CFEALinearElasticity(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CFEAElasticity(val_nDim, val_nVar, config) { + const CConfig *config) : CFEAElasticity(val_nDim, val_nVar, config) { if (nDim == 2) nodalDisplacement.resize(NNODES_2D,nDim); else nodalDisplacement.resize(NNODES_3D,nDim); } -void CFEALinearElasticity::Compute_Tangent_Matrix(CElement *element, CConfig *config) { +void CFEALinearElasticity::Compute_Tangent_Matrix(CElement *element, const CConfig *config) { unsigned short iVar, jVar, kVar; unsigned short iGauss, nGauss; @@ -196,7 +196,7 @@ void CFEALinearElasticity::Compute_Tangent_Matrix(CElement *element, CConfig *co } -void CFEALinearElasticity::Compute_Constitutive_Matrix(CElement *element_container, CConfig *config) { +void CFEALinearElasticity::Compute_Constitutive_Matrix(CElement *element_container, const CConfig *config) { /*--- Compute the D Matrix (for plane stress and 2-D)---*/ @@ -234,7 +234,7 @@ void CFEALinearElasticity::Compute_Constitutive_Matrix(CElement *element_contain } -void CFEALinearElasticity::Compute_Averaged_NodalStress(CElement *element, CConfig *config) { +void CFEALinearElasticity::Compute_Averaged_NodalStress(CElement *element, const CConfig *config) { unsigned short iVar, jVar; unsigned short iGauss, nGauss; @@ -342,3 +342,67 @@ void CFEALinearElasticity::Compute_Averaged_NodalStress(CElement *element, CConf } } + + +CFEAMeshElasticity::CFEAMeshElasticity(unsigned short val_nDim, unsigned short val_nVar, + unsigned long val_nElem, CConfig *config) : + CFEALinearElasticity() { + DV_Val = NULL; + FAux_Dead_Load = NULL; + Rho_s_i = NULL; + Rho_s_DL_i = NULL; + Nu_i = NULL; + + nDim = val_nDim; + nVar = val_nVar; + + unsigned long iVar; + + E = config->GetDeform_ElasticityMod(); + Nu = config->GetDeform_PoissonRatio(); + Compute_Lame_Parameters(); + + switch (config->GetDeform_Stiffness_Type()) { + case INVERSE_VOLUME: + case SOLID_WALL_DISTANCE: + element_based = true; + Nu = config->GetDeform_Coeff(); + break; + case CONSTANT_STIFFNESS: + element_based = false; + break; + } + + E_i = NULL; + if (element_based){ + E_i = new su2double[val_nElem]; + for (iVar = 0; iVar < val_nElem; iVar++){ + E_i[iVar] = E; + } + } + + KAux_ab = new su2double* [nDim]; + for (iVar = 0; iVar < nDim; iVar++) { + KAux_ab[iVar] = new su2double[nDim]; + } + + unsigned short nStrain = (nDim==2) ? DIM_STRAIN_2D : DIM_STRAIN_3D; + unsigned short nNodes = (nDim==2) ? NNODES_2D : NNODES_3D; + + Ba_Mat = new su2double* [nStrain]; + Bb_Mat = new su2double* [nStrain]; + D_Mat = new su2double* [nStrain]; + Ni_Vec = new su2double [nNodes]; + GradNi_Ref_Mat = new su2double* [nNodes]; + GradNi_Curr_Mat = new su2double* [nNodes]; + for (iVar = 0; iVar < nStrain; iVar++) { + Ba_Mat[iVar] = new su2double[nDim]; + Bb_Mat[iVar] = new su2double[nDim]; + D_Mat[iVar] = new su2double[nStrain]; + } + for (iVar = 0; iVar < nNodes; iVar++) { + GradNi_Ref_Mat[iVar] = new su2double[nDim]; + GradNi_Curr_Mat[iVar] = new su2double[nDim]; + } + +} diff --git a/SU2_CFD/src/numerics/elasticity/CFEAMeshElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEAMeshElasticity.cpp deleted file mode 100644 index c88af379a8d1..000000000000 --- a/SU2_CFD/src/numerics/elasticity/CFEAMeshElasticity.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/*! - * \file CFEAMeshElasticity.cpp - * \brief This file contains the routines for setting the mesh pseudo-elastic problem. - * \author Ruben Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - -#include "../../../include/numerics/elasticity/CFEAMeshElasticity.hpp" - - -CFEAMeshElasticity::CFEAMeshElasticity(unsigned short val_nDim, unsigned short val_nVar, - unsigned long val_nElem, CConfig *config) : - CFEALinearElasticity() { - DV_Val = NULL; - FAux_Dead_Load = NULL; - Rho_s_i = NULL; - Rho_s_DL_i = NULL; - Nu_i = NULL; - - nDim = val_nDim; - nVar = val_nVar; - - unsigned long iVar; - - E = config->GetDeform_ElasticityMod(); - Nu = config->GetDeform_PoissonRatio(); - Compute_Lame_Parameters(); - - switch (config->GetDeform_Stiffness_Type()) { - case INVERSE_VOLUME: - case SOLID_WALL_DISTANCE: - element_based = true; - Nu = config->GetDeform_Coeff(); - break; - case CONSTANT_STIFFNESS: - element_based = false; - break; - } - - E_i = NULL; - if (element_based){ - E_i = new su2double[val_nElem]; - for (iVar = 0; iVar < val_nElem; iVar++){ - E_i[iVar] = E; - } - } - - KAux_ab = new su2double* [nDim]; - for (iVar = 0; iVar < nDim; iVar++) { - KAux_ab[iVar] = new su2double[nDim]; - } - - unsigned short nStrain = (nDim==2) ? DIM_STRAIN_2D : DIM_STRAIN_3D; - unsigned short nNodes = (nDim==2) ? NNODES_2D : NNODES_3D; - - Ba_Mat = new su2double* [nStrain]; - Bb_Mat = new su2double* [nStrain]; - D_Mat = new su2double* [nStrain]; - Ni_Vec = new su2double [nNodes]; - GradNi_Ref_Mat = new su2double* [nNodes]; - GradNi_Curr_Mat = new su2double* [nNodes]; - for (iVar = 0; iVar < nStrain; iVar++) { - Ba_Mat[iVar] = new su2double[nDim]; - Bb_Mat[iVar] = new su2double[nDim]; - D_Mat[iVar] = new su2double[nStrain]; - } - for (iVar = 0; iVar < nNodes; iVar++) { - GradNi_Ref_Mat[iVar] = new su2double[nDim]; - GradNi_Curr_Mat[iVar] = new su2double[nDim]; - } - -} diff --git a/SU2_CFD/src/numerics/elasticity/CFEANonlinearElasticity.cpp b/SU2_CFD/src/numerics/elasticity/CFEANonlinearElasticity.cpp index 0cfb1b868d19..0625fec4c887 100644 --- a/SU2_CFD/src/numerics/elasticity/CFEANonlinearElasticity.cpp +++ b/SU2_CFD/src/numerics/elasticity/CFEANonlinearElasticity.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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -30,7 +30,7 @@ CFEANonlinearElasticity::CFEANonlinearElasticity(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CFEAElasticity(val_nDim, val_nVar, config) { + const CConfig *config) : CFEAElasticity(val_nDim, val_nVar, config) { nearly_incompressible = (config->GetMaterialCompressibility() == NEARLY_INCOMPRESSIBLE_MAT); @@ -88,7 +88,7 @@ CFEANonlinearElasticity::CFEANonlinearElasticity(unsigned short val_nDim, unsign if (maxwell_stress == true) { - su2double *Electric_Field_Dir = config->Get_Electric_Field_Dir(); + const su2double *Electric_Field_Dir = config->Get_Electric_Field_Dir(); unsigned short iVar, iDim; su2double ref_Efield_mod; @@ -217,7 +217,7 @@ CFEANonlinearElasticity::~CFEANonlinearElasticity(void) { } -void CFEANonlinearElasticity::Compute_Tangent_Matrix(CElement *element, CConfig *config) { +void CFEANonlinearElasticity::Compute_Tangent_Matrix(CElement *element, const CConfig *config) { unsigned short iVar, jVar, kVar; unsigned short iGauss, nGauss; @@ -468,7 +468,7 @@ void CFEANonlinearElasticity::Compute_Tangent_Matrix(CElement *element, CConfig } -void CFEANonlinearElasticity::Compute_NodalStress_Term(CElement *element, CConfig *config) { +void CFEANonlinearElasticity::Compute_NodalStress_Term(CElement *element, const CConfig *config) { unsigned short iVar, jVar, kVar; unsigned short iGauss, nGauss; @@ -599,7 +599,7 @@ void CFEANonlinearElasticity::Compute_NodalStress_Term(CElement *element, CConfi } -void CFEANonlinearElasticity::Add_MaxwellStress(CElement *element, CConfig *config) { +void CFEANonlinearElasticity::Add_MaxwellStress(CElement *element, const CConfig *config) { // Adds the Maxwell stress to the output of the stress Sxx, Syy, Szz, SVM... @@ -630,7 +630,7 @@ void CFEANonlinearElasticity::Add_MaxwellStress(CElement *element, CConfig *conf } -void CFEANonlinearElasticity::SetElectric_Properties(const CElement *element, CConfig *config) { +void CFEANonlinearElasticity::SetElectric_Properties(const CElement *element, const CConfig *config) { // Set the modulus of the electric field in the current element /*--- These variables are set as preaccumulation inputs in Compute_Tangent_Matrix and @@ -745,7 +745,7 @@ void CFEANonlinearElasticity::Assign_cijkl_D_Mat(void) { } -void CFEANonlinearElasticity::Compute_Averaged_NodalStress(CElement *element, CConfig *config) { +void CFEANonlinearElasticity::Compute_Averaged_NodalStress(CElement *element, const CConfig *config) { unsigned short iVar, jVar, kVar; unsigned short iGauss, nGauss; diff --git a/SU2_CFD/src/numerics/elasticity/CFEM_DielectricElastomer.cpp b/SU2_CFD/src/numerics/elasticity/CFEM_DielectricElastomer.cpp deleted file mode 100644 index 3af19ccf2b8f..000000000000 --- a/SU2_CFD/src/numerics/elasticity/CFEM_DielectricElastomer.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/*! - * \file CFEM_DielectricElastomer.cpp - * \brief This file contains the routines for setting the tangent matrix and residual - * of a FEM nonlinear elastic structural problem. - * \author R. Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - -#include "../../../include/numerics/elasticity/CFEM_DielectricElastomer.hpp" - - -CFEM_DielectricElastomer::CFEM_DielectricElastomer(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CFEANonlinearElasticity(val_nDim, val_nVar, config) {} - - -void CFEM_DielectricElastomer::Compute_Constitutive_Matrix(CElement *element, CConfig *config) { - - /*--- This reduces performance by now, but it is temporal ---*/ - - if (nDim == 2){ - D_Mat[0][0] = 0.0; D_Mat[0][1] = 0.0; D_Mat[0][2] = 0.0; - D_Mat[1][0] = 0.0; D_Mat[1][1] = 0.0; D_Mat[1][2] = 0.0; - D_Mat[2][0] = 0.0; D_Mat[2][1] = 0.0; D_Mat[2][2] = 0.0; - } - else { - D_Mat[0][0] = 0.0; D_Mat[0][1] = 0.0; D_Mat[0][2] = 0.0; D_Mat[0][3] = 0.0; D_Mat[0][4] = 0.0; D_Mat[0][5] = 0.0; - D_Mat[1][0] = 0.0; D_Mat[1][1] = 0.0; D_Mat[1][2] = 0.0; D_Mat[1][3] = 0.0; D_Mat[1][4] = 0.0; D_Mat[1][5] = 0.0; - D_Mat[2][0] = 0.0; D_Mat[2][1] = 0.0; D_Mat[2][2] = 0.0; D_Mat[2][3] = 0.0; D_Mat[2][4] = 0.0; D_Mat[2][5] = 0.0; - D_Mat[3][0] = 0.0; D_Mat[3][1] = 0.0; D_Mat[3][2] = 0.0; D_Mat[3][3] = 0.0; D_Mat[3][4] = 0.0; D_Mat[3][5] = 0.0; - D_Mat[4][0] = 0.0; D_Mat[4][1] = 0.0; D_Mat[4][2] = 0.0; D_Mat[4][3] = 0.0; D_Mat[4][4] = 0.0; D_Mat[4][5] = 0.0; - D_Mat[5][0] = 0.0; D_Mat[5][1] = 0.0; D_Mat[5][2] = 0.0; D_Mat[5][3] = 0.0; D_Mat[5][4] = 0.0; D_Mat[5][5] = 0.0; - } - - -} - -void CFEM_DielectricElastomer::Compute_Stress_Tensor(CElement *element, CConfig *config) { - - unsigned short iDim, jDim; - - su2double E0 = 0.0, E1 = 0.0, E2 = 0.0; - su2double E0_2 = 0.0, E1_2 = 0.0, E2_2 = 0.0; - su2double E_2 = 0.0; - - Compute_FmT_Mat(); - - for (iDim = 0; iDim < nDim; iDim++){ - EField_Curr_Unit[iDim] = 0.0; - for (jDim = 0; jDim < nDim; jDim++){ - EField_Curr_Unit[iDim] += FmT_Mat[iDim][jDim] * EField_Ref_Unit[jDim]; - } - } - - E0 = EFieldMod_Ref*EField_Curr_Unit[0]; E0_2 = pow(E0,2); - E1 = EFieldMod_Ref*EField_Curr_Unit[1]; E1_2 = pow(E1,2); - if (nDim == 3) {E2 = EFieldMod_Ref*EField_Curr_Unit[2]; E2_2 = pow(E2,2);} - - E_2 = E0_2+E1_2+E2_2; - - Stress_Tensor[0][0] = ke_DE*(E0_2-0.5*E_2); Stress_Tensor[0][1] = ke_DE*E0*E1; Stress_Tensor[0][2] = ke_DE*E0*E2; - Stress_Tensor[1][0] = ke_DE*E1*E0; Stress_Tensor[1][1] = ke_DE*(E1_2-0.5*E_2); Stress_Tensor[1][2] = ke_DE*E1*E2; - Stress_Tensor[2][0] = ke_DE*E2*E0; Stress_Tensor[2][1] = ke_DE*E2*E1; Stress_Tensor[2][2] = ke_DE*(E2_2-0.5*E_2); - - -} - diff --git a/SU2_CFD/src/numerics/elasticity/CFEM_IdealDE.cpp b/SU2_CFD/src/numerics/elasticity/CFEM_IdealDE.cpp deleted file mode 100644 index 721a488798bd..000000000000 --- a/SU2_CFD/src/numerics/elasticity/CFEM_IdealDE.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/*! - * \file CFEM_IdealDE.cpp - * \brief Definition of ideal dielectric elastomer. - * \author R. Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - -#include "../../../include/numerics/elasticity/CFEM_IdealDE.hpp" - - -CFEM_IdealDE::CFEM_IdealDE(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CFEANonlinearElasticity(val_nDim, val_nVar, config) { - - /* -- The formulation adopted for this material model has been described by: - * -- - * -- Zhao, X. and Suo, Z., Method to analyze programmable deformation of - * -- dielectric elastomer layers, Applied Physics Letters 93, 251902 (2008). - * -- - * -- http://imechanica.org/node/4234 - */ - - trbbar = 0.0; - Eg = 0.0; - Eg23 = 0.0; - Ek = 0.0; - Pr = 0.0; - -} - -void CFEM_IdealDE::Compute_Plane_Stress_Term(CElement *element, CConfig *config) { - - SU2_MPI::Error("This material model cannot (yet) be used for plane stress.", CURRENT_FUNCTION); - -} - -void CFEM_IdealDE::Compute_Constitutive_Matrix(CElement *element, CConfig *config) { - - /* -- Zhao, X. and Suo, Z. (2008) (full reference in class constructor). ---*/ - - if (nDim == 2){ - - D_Mat[0][0] = Eg23*(b_Mat_Iso[0][0]+trbbar)+Ek; - D_Mat[1][1] = Eg23*(b_Mat_Iso[1][1]+trbbar)+Ek; - - D_Mat[0][1] = -Eg23*(b_Mat_Iso[0][0]+b_Mat_Iso[1][1]-trbbar)+Ek; - D_Mat[1][0] = -Eg23*(b_Mat_Iso[0][0]+b_Mat_Iso[1][1]-trbbar)+Ek; - - D_Mat[0][2] = Eg23*b_Mat_Iso[0][1]/2.0; - D_Mat[2][0] = Eg23*b_Mat_Iso[0][1]/2.0; - - D_Mat[1][2] = Eg23*b_Mat_Iso[0][1]/2.0; - D_Mat[2][1] = Eg23*b_Mat_Iso[0][1]/2.0; - - D_Mat[2][2] = Eg*(b_Mat_Iso[0][0]+b_Mat_Iso[1][1])/2.0; - - } - else { - SU2_MPI::Error("This material model cannot be used for 3D yet.", CURRENT_FUNCTION); - } - -} - -void CFEM_IdealDE::Compute_Stress_Tensor(CElement *element, CConfig *config) { - - /* -- Zhao, X. and Suo, Z. (2008) (full reference in class constructor). ---*/ - - unsigned short iVar, jVar; - su2double dij = 0.0; - - /*--- Compute the isochoric deformation gradient Fbar and left Cauchy-Green tensor bbar ---*/ - Compute_Isochoric_F_b(); - - // Stress terms - - trbbar = (b_Mat_Iso[0][0] + b_Mat_Iso[1][1] + b_Mat_Iso[2][2]) / 3.0; - Eg = Mu / J_F; - Ek = Kappa * (2.0 * J_F - 1.0); - Pr = Kappa * (J_F - 1.0); - Eg23 = 2.0 * Eg / 3.0; - - // Stress tensor - - for (iVar = 0; iVar < 3; iVar++){ - for (jVar = 0; jVar < 3; jVar++){ - if (iVar == jVar) dij = 1.0; - else if (iVar != jVar) dij = 0.0; - Stress_Tensor[iVar][jVar] = Eg * ( b_Mat_Iso[iVar][jVar] - dij * trbbar) + dij * Pr ; - } - } - -} - diff --git a/SU2_CFD/src/numerics/elasticity/CFEM_Knowles_NearInc.cpp b/SU2_CFD/src/numerics/elasticity/CFEM_Knowles_NearInc.cpp deleted file mode 100644 index aeb6ec365219..000000000000 --- a/SU2_CFD/src/numerics/elasticity/CFEM_Knowles_NearInc.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/*! - * \file CFEM_Knowles_NearInc.cpp - * \brief FE numerics for nearly incompressible Knowles material model. - * \author R. Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - -#include "../../../include/numerics/elasticity/CFEM_Knowles_NearInc.hpp" - - -CFEM_Knowles_NearInc::CFEM_Knowles_NearInc(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CFEANonlinearElasticity(val_nDim, val_nVar, config) { - - /* -- The formulation adopted for this material model has been described by: - * -- - * -- Suchocki, C., A Finite Element Implementation of Knowles stored-energy function: - * -- theory, coding and applications, Archive of Mechanical Engineering, Vol. 58, pp. 319-346 (2011). - * -- - * -- DOI: 10.2478/v10180-011-0021-7 - */ - - Bk = config->GetKnowles_B(); - Nk = config->GetKnowles_N(); - - trbbar = 0.0; - Ek = 0.0; - Pr = 0.0; - -} - -void CFEM_Knowles_NearInc::Compute_Plane_Stress_Term(CElement *element, CConfig *config) { - - SU2_MPI::Error("This material model cannot (yet) be used for plane stress.",CURRENT_FUNCTION); - -} - -void CFEM_Knowles_NearInc::Compute_Constitutive_Matrix(CElement *element, CConfig *config) { - - /* -- Suchocki (2011) (full reference in class constructor). ---*/ - - /*--- Computation of the tensor cijkl ---*/ - - unsigned short iVar, jVar, kVar, lVar; - - for (iVar = 0; iVar < 3; iVar++){ - for (jVar = 0; jVar < 3; jVar++){ - for (kVar = 0; kVar < 3; kVar++){ - for (lVar = 0; lVar < 3; lVar++){ - cijkl[iVar][jVar][kVar][lVar] = - term1 * ((1.0/2.0)*( deltaij(iVar,kVar)*b_Mat_Iso[jVar][lVar] - +deltaij(jVar,lVar)*b_Mat_Iso[iVar][kVar] - +deltaij(iVar,lVar)*b_Mat_Iso[jVar][kVar] - +deltaij(jVar,kVar)*b_Mat_Iso[iVar][lVar]) - +(2.0/3.0)*(trbbar*deltaij(iVar,jVar)*deltaij(kVar,lVar) - -b_Mat_Iso[iVar][jVar]*deltaij(kVar,lVar) - -deltaij(iVar,jVar)*b_Mat_Iso[kVar][lVar])) - +term2 * ( b_Mat_Iso[iVar][jVar]*b_Mat_Iso[kVar][lVar] - - trbbar*(b_Mat_Iso[iVar][jVar]*deltaij(kVar,lVar) - +deltaij(iVar,jVar)*b_Mat_Iso[kVar][lVar]) - + pow(trbbar,2.0) * deltaij(iVar,jVar) * deltaij(kVar,lVar)) - +Kappa * (2.0 * J_F - 1.0) * deltaij(iVar,jVar) * deltaij(kVar,lVar); - - } - } - } - } - - /*--- Reorganizing the tensor into the matrix D ---*/ - - Assign_cijkl_D_Mat(); - - -} - -void CFEM_Knowles_NearInc::Compute_Stress_Tensor(CElement *element, CConfig *config) { - - /* -- Suchocki (2011) (full reference in class constructor). ---*/ - - unsigned short iVar, jVar; - - /*--- Compute the isochoric deformation gradient Fbar and left Cauchy-Green tensor bbar ---*/ - Compute_Isochoric_F_b(); - - trbbar = (b_Mat_Iso[0][0] + b_Mat_Iso[1][1] + b_Mat_Iso[2][2]) / 3.0; - term1 = (Mu / J_F) * pow((1 + (Bk / Nk) * (3.0 * trbbar - 3.0)), (Nk-1.0)); - term2 = 2.0 * (Mu / J_F) * (Bk * (Nk - 1.0) / Nk) * - pow((1.0 + (Bk / Nk) * (3.0 * trbbar - 3.0)), (Nk-2.0)); - - Ek = Kappa * (2.0 * J_F - 1.0); - Pr = Kappa * (J_F - 1.0); - - for (iVar = 0; iVar < 3; iVar++){ - for (jVar = 0; jVar < 3; jVar++){ - Stress_Tensor[iVar][jVar] = term1 * (b_Mat_Iso[iVar][jVar] - deltaij(iVar,jVar)*trbbar) + - deltaij(iVar,jVar) * Pr; - } - } - -} - diff --git a/SU2_CFD/src/numerics/elasticity/CFEM_NeoHookean_Comp.cpp b/SU2_CFD/src/numerics/elasticity/CFEM_NeoHookean_Comp.cpp deleted file mode 100644 index 18de92c0de0f..000000000000 --- a/SU2_CFD/src/numerics/elasticity/CFEM_NeoHookean_Comp.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/*! - * \file CFEM_NeoHookean_Comp.cpp - * \brief Definition of Neo-Hookean compressible material. - * \author R. Sanchez - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - -#include "../../../include/numerics/elasticity/CFEM_NeoHookean_Comp.hpp" - - -CFEM_NeoHookean_Comp::CFEM_NeoHookean_Comp(unsigned short val_nDim, - unsigned short val_nVar, - CConfig *config) : - CFEANonlinearElasticity(val_nDim, val_nVar, config) { -} - -void CFEM_NeoHookean_Comp::Compute_Plane_Stress_Term(CElement *element, CConfig *config) { - - su2double j_red = 1.0; - su2double fx = 0.0, fpx = 1.0; - su2double xkm1 = 1.0, xk = 1.0; - su2double cte = 0.0; - - unsigned short iNR, nNR; - su2double NRTOL; - - // Maximum number of iterations and tolerance (relative) - nNR = 10; - NRTOL = 1E-25; - - // j_red: reduced jacobian, for the 2x2 submatrix of F - j_red = F_Mat[0][0] * F_Mat[1][1] - F_Mat[1][0] * F_Mat[0][1]; - // cte: constant term in the NR method - cte = Lambda*log(j_red) - Mu; - - // f(f33) = mu*f33^2 + lambda*ln(f33) + (lambda*ln(j_red)-mu) = 0 - // f'(f33) = 2*mu*f33 + lambda/f33 - - for (iNR = 0; iNR < nNR; iNR++) { - fx = Mu*pow(xk,2.0) + Lambda*log(xk) + cte; - fpx = 2*Mu*xk + (Lambda / xk); - xkm1 = xk - fx / fpx; - if (((xkm1 - xk) / xk) < NRTOL) break; - xk = xkm1; - } - - f33 = xkm1; - -} - -void CFEM_NeoHookean_Comp::Compute_Constitutive_Matrix(CElement *element, CConfig *config) { - - su2double Mu_p = 0.0, Lambda_p = 0.0; - - /*--- This can be done in a better way ---*/ - if (J_F != 0.0) { - Mu_p = (Mu - Lambda*log(J_F))/J_F; - Lambda_p = Lambda/J_F; - } - - /*--- Assuming plane strain ---*/ - - su2double Lbd_2Mu = Lambda_p + 2.0 * Mu_p; - - if (nDim == 2) { - D_Mat[0][0] = Lbd_2Mu; D_Mat[0][1] = Lambda_p; D_Mat[0][2] = 0.0; - D_Mat[1][0] = Lambda_p; D_Mat[1][1] = Lbd_2Mu; D_Mat[1][2] = 0.0; - D_Mat[2][0] = 0.0; D_Mat[2][1] = 0.0; D_Mat[2][2] = Mu_p; - } - else { - D_Mat[0][0] = Lbd_2Mu; D_Mat[0][1] = Lambda_p; D_Mat[0][2] = Lambda_p; D_Mat[0][3] = 0.0; D_Mat[0][4] = 0.0; D_Mat[0][5] = 0.0; - D_Mat[1][0] = Lambda_p; D_Mat[1][1] = Lbd_2Mu; D_Mat[1][2] = Lambda_p; D_Mat[1][3] = 0.0; D_Mat[1][4] = 0.0; D_Mat[1][5] = 0.0; - D_Mat[2][0] = Lambda_p; D_Mat[2][1] = Lambda_p; D_Mat[2][2] = Lbd_2Mu; D_Mat[2][3] = 0.0; D_Mat[2][4] = 0.0; D_Mat[2][5] = 0.0; - D_Mat[3][0] = 0.0; D_Mat[3][1] = 0.0; D_Mat[3][2] = 0.0; D_Mat[3][3] = Mu_p; D_Mat[3][4] = 0.0; D_Mat[3][5] = 0.0; - D_Mat[4][0] = 0.0; D_Mat[4][1] = 0.0; D_Mat[4][2] = 0.0; D_Mat[4][3] = 0.0; D_Mat[4][4] = Mu_p; D_Mat[4][5] = 0.0; - D_Mat[5][0] = 0.0; D_Mat[5][1] = 0.0; D_Mat[5][2] = 0.0; D_Mat[5][3] = 0.0; D_Mat[5][4] = 0.0; D_Mat[5][5] = Mu_p; - } - -} - -void CFEM_NeoHookean_Comp::Compute_Stress_Tensor(CElement *element, CConfig *config) { - - unsigned short iVar,jVar; - su2double Mu_J = 0.0, Lambda_J = 0.0; - - /*--- This can be done in a better way ---*/ - if (J_F != 0.0) { - Mu_J = Mu/J_F; - Lambda_J = Lambda/J_F; - } - - for (iVar = 0; iVar < 3; iVar++) { - for (jVar = 0; jVar < 3; jVar++) { - su2double dij = deltaij(iVar,jVar); - Stress_Tensor[iVar][jVar] = Mu_J * (b_Mat[iVar][jVar] - dij) + Lambda_J * log(J_F) * dij; - } - } - -} - diff --git a/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp b/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp new file mode 100644 index 000000000000..c526ff8f71b6 --- /dev/null +++ b/SU2_CFD/src/numerics/elasticity/nonlinear_models.cpp @@ -0,0 +1,346 @@ +/*! + * \file nonlinear_models.cpp + * \brief Definition of nonlinear constitutive models. + * \author R. Sanchez + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/numerics/elasticity/nonlinear_models.hpp" + + +CFEM_NeoHookean_Comp::CFEM_NeoHookean_Comp(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig *config) : + CFEANonlinearElasticity(val_nDim, val_nVar, config) { +} + +void CFEM_NeoHookean_Comp::Compute_Plane_Stress_Term(CElement *element, const CConfig *config) { + + su2double j_red = 1.0; + su2double fx = 0.0, fpx = 1.0; + su2double xkm1 = 1.0, xk = 1.0; + su2double cte = 0.0; + + unsigned short iNR, nNR; + su2double NRTOL; + + // Maximum number of iterations and tolerance (relative) + nNR = 10; + NRTOL = 1E-25; + + // j_red: reduced jacobian, for the 2x2 submatrix of F + j_red = F_Mat[0][0] * F_Mat[1][1] - F_Mat[1][0] * F_Mat[0][1]; + // cte: constant term in the NR method + cte = Lambda*log(j_red) - Mu; + + // f(f33) = mu*f33^2 + lambda*ln(f33) + (lambda*ln(j_red)-mu) = 0 + // f'(f33) = 2*mu*f33 + lambda/f33 + + for (iNR = 0; iNR < nNR; iNR++) { + fx = Mu*pow(xk,2.0) + Lambda*log(xk) + cte; + fpx = 2*Mu*xk + (Lambda / xk); + xkm1 = xk - fx / fpx; + if (((xkm1 - xk) / xk) < NRTOL) break; + xk = xkm1; + } + + f33 = xkm1; + +} + +void CFEM_NeoHookean_Comp::Compute_Constitutive_Matrix(CElement *element, const CConfig *config) { + + su2double Mu_p = 0.0, Lambda_p = 0.0; + + /*--- This can be done in a better way ---*/ + if (J_F != 0.0) { + Mu_p = (Mu - Lambda*log(J_F))/J_F; + Lambda_p = Lambda/J_F; + } + + /*--- Assuming plane strain ---*/ + + su2double Lbd_2Mu = Lambda_p + 2.0 * Mu_p; + + if (nDim == 2) { + D_Mat[0][0] = Lbd_2Mu; D_Mat[0][1] = Lambda_p; D_Mat[0][2] = 0.0; + D_Mat[1][0] = Lambda_p; D_Mat[1][1] = Lbd_2Mu; D_Mat[1][2] = 0.0; + D_Mat[2][0] = 0.0; D_Mat[2][1] = 0.0; D_Mat[2][2] = Mu_p; + } + else { + D_Mat[0][0] = Lbd_2Mu; D_Mat[0][1] = Lambda_p; D_Mat[0][2] = Lambda_p; D_Mat[0][3] = 0.0; D_Mat[0][4] = 0.0; D_Mat[0][5] = 0.0; + D_Mat[1][0] = Lambda_p; D_Mat[1][1] = Lbd_2Mu; D_Mat[1][2] = Lambda_p; D_Mat[1][3] = 0.0; D_Mat[1][4] = 0.0; D_Mat[1][5] = 0.0; + D_Mat[2][0] = Lambda_p; D_Mat[2][1] = Lambda_p; D_Mat[2][2] = Lbd_2Mu; D_Mat[2][3] = 0.0; D_Mat[2][4] = 0.0; D_Mat[2][5] = 0.0; + D_Mat[3][0] = 0.0; D_Mat[3][1] = 0.0; D_Mat[3][2] = 0.0; D_Mat[3][3] = Mu_p; D_Mat[3][4] = 0.0; D_Mat[3][5] = 0.0; + D_Mat[4][0] = 0.0; D_Mat[4][1] = 0.0; D_Mat[4][2] = 0.0; D_Mat[4][3] = 0.0; D_Mat[4][4] = Mu_p; D_Mat[4][5] = 0.0; + D_Mat[5][0] = 0.0; D_Mat[5][1] = 0.0; D_Mat[5][2] = 0.0; D_Mat[5][3] = 0.0; D_Mat[5][4] = 0.0; D_Mat[5][5] = Mu_p; + } + +} + +void CFEM_NeoHookean_Comp::Compute_Stress_Tensor(CElement *element, const CConfig *config) { + + unsigned short iVar,jVar; + su2double Mu_J = 0.0, Lambda_J = 0.0; + + /*--- This can be done in a better way ---*/ + if (J_F != 0.0) { + Mu_J = Mu/J_F; + Lambda_J = Lambda/J_F; + } + + for (iVar = 0; iVar < 3; iVar++) { + for (jVar = 0; jVar < 3; jVar++) { + su2double dij = deltaij(iVar,jVar); + Stress_Tensor[iVar][jVar] = Mu_J * (b_Mat[iVar][jVar] - dij) + Lambda_J * log(J_F) * dij; + } + } + +} + +CFEM_Knowles_NearInc::CFEM_Knowles_NearInc(unsigned short val_nDim, unsigned short val_nVar, + const CConfig *config) : CFEANonlinearElasticity(val_nDim, val_nVar, config) { + + /* -- The formulation adopted for this material model has been described by: + * -- + * -- Suchocki, C., A Finite Element Implementation of Knowles stored-energy function: + * -- theory, coding and applications, Archive of Mechanical Engineering, Vol. 58, pp. 319-346 (2011). + * -- + * -- DOI: 10.2478/v10180-011-0021-7 + */ + + Bk = config->GetKnowles_B(); + Nk = config->GetKnowles_N(); + + trbbar = 0.0; + Ek = 0.0; + Pr = 0.0; + +} + +void CFEM_Knowles_NearInc::Compute_Plane_Stress_Term(CElement *element, const CConfig *config) { + + SU2_MPI::Error("This material model cannot (yet) be used for plane stress.",CURRENT_FUNCTION); + +} + +void CFEM_Knowles_NearInc::Compute_Constitutive_Matrix(CElement *element, const CConfig *config) { + + /* -- Suchocki (2011) (full reference in class constructor). ---*/ + + /*--- Computation of the tensor cijkl ---*/ + + unsigned short iVar, jVar, kVar, lVar; + + for (iVar = 0; iVar < 3; iVar++){ + for (jVar = 0; jVar < 3; jVar++){ + for (kVar = 0; kVar < 3; kVar++){ + for (lVar = 0; lVar < 3; lVar++){ + cijkl[iVar][jVar][kVar][lVar] = + term1 * ((1.0/2.0)*( deltaij(iVar,kVar)*b_Mat_Iso[jVar][lVar] + +deltaij(jVar,lVar)*b_Mat_Iso[iVar][kVar] + +deltaij(iVar,lVar)*b_Mat_Iso[jVar][kVar] + +deltaij(jVar,kVar)*b_Mat_Iso[iVar][lVar]) + +(2.0/3.0)*(trbbar*deltaij(iVar,jVar)*deltaij(kVar,lVar) + -b_Mat_Iso[iVar][jVar]*deltaij(kVar,lVar) + -deltaij(iVar,jVar)*b_Mat_Iso[kVar][lVar])) + +term2 * ( b_Mat_Iso[iVar][jVar]*b_Mat_Iso[kVar][lVar] + - trbbar*(b_Mat_Iso[iVar][jVar]*deltaij(kVar,lVar) + +deltaij(iVar,jVar)*b_Mat_Iso[kVar][lVar]) + + pow(trbbar,2.0) * deltaij(iVar,jVar) * deltaij(kVar,lVar)) + +Kappa * (2.0 * J_F - 1.0) * deltaij(iVar,jVar) * deltaij(kVar,lVar); + + } + } + } + } + + /*--- Reorganizing the tensor into the matrix D ---*/ + + Assign_cijkl_D_Mat(); + + +} + +void CFEM_Knowles_NearInc::Compute_Stress_Tensor(CElement *element, const CConfig *config) { + + /* -- Suchocki (2011) (full reference in class constructor). ---*/ + + unsigned short iVar, jVar; + + /*--- Compute the isochoric deformation gradient Fbar and left Cauchy-Green tensor bbar ---*/ + Compute_Isochoric_F_b(); + + trbbar = (b_Mat_Iso[0][0] + b_Mat_Iso[1][1] + b_Mat_Iso[2][2]) / 3.0; + term1 = (Mu / J_F) * pow((1 + (Bk / Nk) * (3.0 * trbbar - 3.0)), (Nk-1.0)); + term2 = 2.0 * (Mu / J_F) * (Bk * (Nk - 1.0) / Nk) * + pow((1.0 + (Bk / Nk) * (3.0 * trbbar - 3.0)), (Nk-2.0)); + + Ek = Kappa * (2.0 * J_F - 1.0); + Pr = Kappa * (J_F - 1.0); + + for (iVar = 0; iVar < 3; iVar++){ + for (jVar = 0; jVar < 3; jVar++){ + Stress_Tensor[iVar][jVar] = term1 * (b_Mat_Iso[iVar][jVar] - deltaij(iVar,jVar)*trbbar) + + deltaij(iVar,jVar) * Pr; + } + } + +} + +CFEM_DielectricElastomer::CFEM_DielectricElastomer(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config) : + CFEANonlinearElasticity(val_nDim, val_nVar, config) { + +} + +void CFEM_DielectricElastomer::Compute_Constitutive_Matrix(CElement *element, const CConfig *config) { + + /*--- This reduces performance by now, but it is temporal ---*/ + + if (nDim == 2){ + D_Mat[0][0] = 0.0; D_Mat[0][1] = 0.0; D_Mat[0][2] = 0.0; + D_Mat[1][0] = 0.0; D_Mat[1][1] = 0.0; D_Mat[1][2] = 0.0; + D_Mat[2][0] = 0.0; D_Mat[2][1] = 0.0; D_Mat[2][2] = 0.0; + } + else { + D_Mat[0][0] = 0.0; D_Mat[0][1] = 0.0; D_Mat[0][2] = 0.0; D_Mat[0][3] = 0.0; D_Mat[0][4] = 0.0; D_Mat[0][5] = 0.0; + D_Mat[1][0] = 0.0; D_Mat[1][1] = 0.0; D_Mat[1][2] = 0.0; D_Mat[1][3] = 0.0; D_Mat[1][4] = 0.0; D_Mat[1][5] = 0.0; + D_Mat[2][0] = 0.0; D_Mat[2][1] = 0.0; D_Mat[2][2] = 0.0; D_Mat[2][3] = 0.0; D_Mat[2][4] = 0.0; D_Mat[2][5] = 0.0; + D_Mat[3][0] = 0.0; D_Mat[3][1] = 0.0; D_Mat[3][2] = 0.0; D_Mat[3][3] = 0.0; D_Mat[3][4] = 0.0; D_Mat[3][5] = 0.0; + D_Mat[4][0] = 0.0; D_Mat[4][1] = 0.0; D_Mat[4][2] = 0.0; D_Mat[4][3] = 0.0; D_Mat[4][4] = 0.0; D_Mat[4][5] = 0.0; + D_Mat[5][0] = 0.0; D_Mat[5][1] = 0.0; D_Mat[5][2] = 0.0; D_Mat[5][3] = 0.0; D_Mat[5][4] = 0.0; D_Mat[5][5] = 0.0; + } + + +} + +void CFEM_DielectricElastomer::Compute_Stress_Tensor(CElement *element, const CConfig *config) { + + unsigned short iDim, jDim; + + su2double E0 = 0.0, E1 = 0.0, E2 = 0.0; + su2double E0_2 = 0.0, E1_2 = 0.0, E2_2 = 0.0; + su2double E_2 = 0.0; + + Compute_FmT_Mat(); + + for (iDim = 0; iDim < nDim; iDim++){ + EField_Curr_Unit[iDim] = 0.0; + for (jDim = 0; jDim < nDim; jDim++){ + EField_Curr_Unit[iDim] += FmT_Mat[iDim][jDim] * EField_Ref_Unit[jDim]; + } + } + + E0 = EFieldMod_Ref*EField_Curr_Unit[0]; E0_2 = pow(E0,2); + E1 = EFieldMod_Ref*EField_Curr_Unit[1]; E1_2 = pow(E1,2); + if (nDim == 3) {E2 = EFieldMod_Ref*EField_Curr_Unit[2]; E2_2 = pow(E2,2);} + + E_2 = E0_2+E1_2+E2_2; + + Stress_Tensor[0][0] = ke_DE*(E0_2-0.5*E_2); Stress_Tensor[0][1] = ke_DE*E0*E1; Stress_Tensor[0][2] = ke_DE*E0*E2; + Stress_Tensor[1][0] = ke_DE*E1*E0; Stress_Tensor[1][1] = ke_DE*(E1_2-0.5*E_2); Stress_Tensor[1][2] = ke_DE*E1*E2; + Stress_Tensor[2][0] = ke_DE*E2*E0; Stress_Tensor[2][1] = ke_DE*E2*E1; Stress_Tensor[2][2] = ke_DE*(E2_2-0.5*E_2); + +} + +CFEM_IdealDE::CFEM_IdealDE(unsigned short val_nDim, unsigned short val_nVar, + const CConfig *config) : CFEANonlinearElasticity(val_nDim, val_nVar, config) { + + /* -- The formulation adopted for this material model has been described by: + * -- + * -- Zhao, X. and Suo, Z., Method to analyze programmable deformation of + * -- dielectric elastomer layers, Applied Physics Letters 93, 251902 (2008). + * -- + * -- http://imechanica.org/node/4234 + */ + + trbbar = 0.0; + Eg = 0.0; + Eg23 = 0.0; + Ek = 0.0; + Pr = 0.0; + +} + +void CFEM_IdealDE::Compute_Plane_Stress_Term(CElement *element, const CConfig *config) { + + SU2_MPI::Error("This material model cannot (yet) be used for plane stress.", CURRENT_FUNCTION); + +} + +void CFEM_IdealDE::Compute_Constitutive_Matrix(CElement *element, const CConfig *config) { + + /* -- Zhao, X. and Suo, Z. (2008) (full reference in class constructor). ---*/ + + if (nDim == 2){ + + D_Mat[0][0] = Eg23*(b_Mat_Iso[0][0]+trbbar)+Ek; + D_Mat[1][1] = Eg23*(b_Mat_Iso[1][1]+trbbar)+Ek; + + D_Mat[0][1] = -Eg23*(b_Mat_Iso[0][0]+b_Mat_Iso[1][1]-trbbar)+Ek; + D_Mat[1][0] = -Eg23*(b_Mat_Iso[0][0]+b_Mat_Iso[1][1]-trbbar)+Ek; + + D_Mat[0][2] = Eg23*b_Mat_Iso[0][1]/2.0; + D_Mat[2][0] = Eg23*b_Mat_Iso[0][1]/2.0; + + D_Mat[1][2] = Eg23*b_Mat_Iso[0][1]/2.0; + D_Mat[2][1] = Eg23*b_Mat_Iso[0][1]/2.0; + + D_Mat[2][2] = Eg*(b_Mat_Iso[0][0]+b_Mat_Iso[1][1])/2.0; + + } + else { + SU2_MPI::Error("This material model cannot be used for 3D yet.", CURRENT_FUNCTION); + } + +} + +void CFEM_IdealDE::Compute_Stress_Tensor(CElement *element, const CConfig *config) { + + /* -- Zhao, X. and Suo, Z. (2008) (full reference in class constructor). ---*/ + + unsigned short iVar, jVar; + su2double dij = 0.0; + + /*--- Compute the isochoric deformation gradient Fbar and left Cauchy-Green tensor bbar ---*/ + Compute_Isochoric_F_b(); + + // Stress terms + + trbbar = (b_Mat_Iso[0][0] + b_Mat_Iso[1][1] + b_Mat_Iso[2][2]) / 3.0; + Eg = Mu / J_F; + Ek = Kappa * (2.0 * J_F - 1.0); + Pr = Kappa * (J_F - 1.0); + Eg23 = 2.0 * Eg / 3.0; + + // Stress tensor + + for (iVar = 0; iVar < 3; iVar++){ + for (jVar = 0; jVar < 3; jVar++){ + if (iVar == jVar) dij = 1.0; + else if (iVar != jVar) dij = 0.0; + Stress_Tensor[iVar][jVar] = Eg * ( b_Mat_Iso[iVar][jVar] - dij * trbbar) + dij * Pr ; + } + } + +} diff --git a/SU2_CFD/src/numerics/flow/convection/ausm_slau.cpp b/SU2_CFD/src/numerics/flow/convection/ausm_slau.cpp new file mode 100644 index 000000000000..0e168597fdd0 --- /dev/null +++ b/SU2_CFD/src/numerics/flow/convection/ausm_slau.cpp @@ -0,0 +1,969 @@ +/*! + * \file ausm_slau.cpp + * \brief Implementations of the AUSM-family of schemes. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../../include/numerics/flow/convection/ausm_slau.hpp" + +CUpwAUSMPLUS_SLAU_Base_Flow::CUpwAUSMPLUS_SLAU_Base_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CNumerics(val_nDim, val_nVar, config) { + + if (config->GetDynamic_Grid() && (SU2_MPI::GetRank() == MASTER_NODE)) + cout << "WARNING: Grid velocities are NOT yet considered in AUSM-type schemes." << endl; + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + UseAccurateJacobian = config->GetUse_Accurate_Jacobians(); + HasAnalyticalDerivatives = false; + FinDiffStep = 1e-4; + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + psi_i = new su2double [nVar]; + psi_j = new su2double [nVar]; + + Flux = new su2double [nVar]; + Lambda = new su2double [nVar]; + Epsilon = new su2double [nVar]; + P_Tensor = new su2double* [nVar]; + invP_Tensor = new su2double* [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + P_Tensor[iVar] = new su2double [nVar]; + invP_Tensor[iVar] = new su2double [nVar]; + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CUpwAUSMPLUS_SLAU_Base_Flow::~CUpwAUSMPLUS_SLAU_Base_Flow(void) { + + delete [] psi_i; + delete [] psi_j; + + delete [] Flux; + delete [] Lambda; + delete [] Epsilon; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] P_Tensor[iVar]; + delete [] invP_Tensor[iVar]; + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] P_Tensor; + delete [] invP_Tensor; + delete [] Jacobian_i; + delete [] Jacobian_j; + +} + +void CUpwAUSMPLUS_SLAU_Base_Flow::ComputeMassAndPressureFluxes(const CConfig* config, su2double &mdot, su2double &pressure) +{ + /*--- For schemes that fit in the general form of AUSM+up and SLAU schemes you can inherit from this class + and implement only the specifics, which should be the face mass flux (per unit area) and the face pressure. + For implicit solution methods this class can either approximate the flux Jacobians (using those of the Roe + scheme) or compute accurate ones. This is done either numerically, differentiating "mdot" and "pressure" + using 1st order finite differences, or analytically if you use this function to set the values of + "dmdot_dVi/j", "dpres_dVi/j" and set "HasAnalyticalDerivatives" to true in the ctor of the derived class. + For accurate numerical differentiation "mdot" and "pressure" can be functions of, at most, the velocities, + pressures, densities, and enthalpies at nodes i/j. This is also the order expected for the partial derivatives + of "mdot" and "pressure" in "d?_dVi/j" (in case they are known analytically, see the AUSM+up implementation). + ---*/ +} + +void CUpwAUSMPLUS_SLAU_Base_Flow::ApproximateJacobian(su2double **val_Jacobian_i, su2double **val_Jacobian_j) { + + unsigned short iDim, iVar, jVar, kVar; + su2double R, RoeDensity, RoeEnthalpy, RoeSoundSpeed, ProjVelocity, sq_vel, Energy_i, Energy_j; + + Energy_i = Enthalpy_i - Pressure_i/Density_i; + Energy_j = Enthalpy_j - Pressure_j/Density_j; + + /*--- Mean Roe variables iPoint and jPoint ---*/ + + R = sqrt(fabs(Density_j/Density_i)); + RoeDensity = R*Density_i; + ProjVelocity = 0.0; + sq_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); + ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; + sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; + } + RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); + RoeSoundSpeed = sqrt(fabs((Gamma-1)*(RoeEnthalpy-0.5*sq_vel))); + + /*--- Compute P and Lambda (do it with the Normal) ---*/ + + GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, P_Tensor); + + /*--- Flow eigenvalues and Entropy correctors ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + Lambda[iDim] = ProjVelocity; + Lambda[nVar-2] = ProjVelocity + RoeSoundSpeed; + Lambda[nVar-1] = ProjVelocity - RoeSoundSpeed; + + /*--- Compute inverse P ---*/ + GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); + + /*--- Jacobians of the inviscid flux, scale = 0.5 because val_residual ~ 0.5*(fc_i+fc_j)*Normal ---*/ + GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5, val_Jacobian_i); + GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5, val_Jacobian_j); + + /*--- Roe's Flux approximation ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + su2double Proj_ModJac_Tensor_ij = 0.0; + /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*fabs(Lambda[kVar])*invP_Tensor[kVar][jVar]; + val_Jacobian_i[iVar][jVar] += 0.5*Proj_ModJac_Tensor_ij*Area; + val_Jacobian_j[iVar][jVar] -= 0.5*Proj_ModJac_Tensor_ij*Area; + } + } + +} + +void CUpwAUSMPLUS_SLAU_Base_Flow::AccurateJacobian(const CConfig* config, su2double **val_Jacobian_i, su2double **val_Jacobian_j) { + + /*--- Compute Jacobians using a mixed (numerical/analytical) formulation ---*/ + + unsigned short iDim, iVar, jVar; + + /*--- If not computed analytically, numerically differentiate the fluxes wrt primitives ---*/ + + if (!HasAnalyticalDerivatives) { + + /*--- Create arrays of pointers to the primitive variables so + we can loop through and perturb them in a general way. ---*/ + + su2double *primitives_i[6], *primitives_j[6]; + + for (iDim = 0; iDim < nDim; ++iDim) { + primitives_i[iDim] = &Velocity_i[iDim]; + primitives_j[iDim] = &Velocity_j[iDim]; + } + primitives_i[ nDim ] = &Pressure_i; primitives_j[ nDim ] = &Pressure_j; + primitives_i[nDim+1] = &Density_i; primitives_j[nDim+1] = &Density_j; + primitives_i[nDim+2] = &Enthalpy_i; primitives_j[nDim+2] = &Enthalpy_j; + + /*--- Initialize the gradient arrays with the negative of the quantity, + then for forward finite differences we add to it and divide. ---*/ + + for (iVar = 0; iVar < 6; ++iVar) { + dmdot_dVi[iVar] = -MassFlux; dpres_dVi[iVar] = -Pressure; + dmdot_dVj[iVar] = -MassFlux; dpres_dVj[iVar] = -Pressure; + } + + for (iVar = 0; iVar < nDim+3; ++iVar) { + /*--- Perturb side i ---*/ + su2double epsilon = FinDiffStep * max(1.0, fabs(*primitives_i[iVar])); + *primitives_i[iVar] += epsilon; + ComputeMassAndPressureFluxes(config, MassFlux, Pressure); + dmdot_dVi[iVar] += MassFlux; dpres_dVi[iVar] += Pressure; + dmdot_dVi[iVar] /= epsilon; dpres_dVi[iVar] /= epsilon; + *primitives_i[iVar] -= epsilon; + + /*--- Perturb side j ---*/ + epsilon = FinDiffStep * max(1.0, fabs(*primitives_j[iVar])); + *primitives_j[iVar] += epsilon; + ComputeMassAndPressureFluxes(config, MassFlux, Pressure); + dmdot_dVj[iVar] += MassFlux; dpres_dVj[iVar] += Pressure; + dmdot_dVj[iVar] /= epsilon; dpres_dVj[iVar] /= epsilon; + *primitives_j[iVar] -= epsilon; + } + } + + /*--- Differentiation of fluxes wrt conservatives assuming ideal gas ---*/ + + su2double dmdot_dUi[5], dmdot_dUj[5], dpres_dUi[5], dpres_dUj[5]; + su2double sq_veli = 0.0, sq_velj = 0.0, dHi_drhoi = 0.0, dHj_drhoj = 0.0; + su2double oneOnRhoi = 1.0/Density_i, oneOnRhoj = 1.0/Density_j; + + for (jVar = 0; jVar < nVar; ++jVar) { + + /*--- Partial derivatives of the primitives wrt conservative "jVar" ---*/ + su2double dVi_dUi[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + su2double dVj_dUj[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; + + if (jVar == 0) { // Density + for (iDim = 0; iDim < nDim; ++iDim) { + // -u,v,w / rho + dVi_dUi[iDim] = -Velocity_i[iDim] * oneOnRhoi; + dVj_dUj[iDim] = -Velocity_j[iDim] * oneOnRhoj; + // ||V||^2 + sq_veli += Velocity_i[iDim] * Velocity_i[iDim]; + sq_velj += Velocity_j[iDim] * Velocity_j[iDim]; + } + dVi_dUi[nDim] = 0.5*Gamma_Minus_One*sq_veli; + dVj_dUj[nDim] = 0.5*Gamma_Minus_One*sq_velj; + + dVi_dUi[nDim+1] = dVj_dUj[nDim+1] = 1.0; + + dHi_drhoi = 0.5*(Gamma-2.0)*sq_veli - Gamma*Pressure_i/((Gamma-1.0)*Density_i); + dHj_drhoj = 0.5*(Gamma-2.0)*sq_velj - Gamma*Pressure_j/((Gamma-1.0)*Density_j); + dVi_dUi[nDim+2] = dHi_drhoi * oneOnRhoi; + dVj_dUj[nDim+2] = dHj_drhoj * oneOnRhoj; + } + else if (jVar == nVar-1) { // rho*Energy + dVi_dUi[nDim] = dVj_dUj[nDim] = Gamma_Minus_One; + dVi_dUi[nDim+2] = Gamma * oneOnRhoi; + dVj_dUj[nDim+2] = Gamma * oneOnRhoj; + } + else { // Momentum + dVi_dUi[jVar-1] = oneOnRhoi; + dVj_dUj[jVar-1] = oneOnRhoj; + + dVi_dUi[nDim] = -Gamma_Minus_One*Velocity_i[jVar-1]; + dVj_dUj[nDim] = -Gamma_Minus_One*Velocity_j[jVar-1]; + + dVi_dUi[nDim+2] = dVi_dUi[nDim] * oneOnRhoi; + dVj_dUj[nDim+2] = dVj_dUj[nDim] * oneOnRhoj; + } + + /*--- Dot product to complete chain rule ---*/ + dmdot_dUi[jVar] = 0.0; dpres_dUi[jVar] = 0.0; + dmdot_dUj[jVar] = 0.0; dpres_dUj[jVar] = 0.0; + for (iVar = 0; iVar < 6; ++iVar) { + dmdot_dUi[jVar] += dmdot_dVi[iVar]*dVi_dUi[iVar]; + dpres_dUi[jVar] += dpres_dVi[iVar]*dVi_dUi[iVar]; + dmdot_dUj[jVar] += dmdot_dVj[iVar]*dVj_dUj[iVar]; + dpres_dUj[jVar] += dpres_dVj[iVar]*dVj_dUj[iVar]; + } + } + + /*--- Assemble final Jacobians (assuming phi = |mdot|) ---*/ + + su2double mdot_hat, psi_hat[5]; + + if (MassFlux > 0.0) { + mdot_hat = Area*MassFlux*oneOnRhoi; + for (iVar = 0; iVar < nVar; ++iVar) psi_hat[iVar] = Area*psi_i[iVar]; + } + else { + mdot_hat = Area*MassFlux*oneOnRhoj; + for (iVar = 0; iVar < nVar; ++iVar) psi_hat[iVar] = Area*psi_j[iVar]; + } + + /*--- Contribution from the mass flux derivatives ---*/ + for (iVar = 0; iVar < nVar; ++iVar) { + for (jVar = 0; jVar < nVar; ++jVar) { + val_Jacobian_i[iVar][jVar] = psi_hat[iVar] * dmdot_dUi[jVar]; + val_Jacobian_j[iVar][jVar] = psi_hat[iVar] * dmdot_dUj[jVar]; + } + } + + /*--- Contribution from the pressure derivatives ---*/ + for (iDim = 0; iDim < nDim; ++iDim) { + for (jVar = 0; jVar < nVar; ++jVar) { + val_Jacobian_i[iDim+1][jVar] += Normal[iDim] * dpres_dUi[jVar]; + val_Jacobian_j[iDim+1][jVar] += Normal[iDim] * dpres_dUj[jVar]; + } + } + + /*--- Contributions from the derivatives of PSI wrt the conservatives ---*/ + if (MassFlux > 0.0) { + /*--- Velocity terms ---*/ + for (iDim = 0; iDim < nDim; ++iDim) { + val_Jacobian_i[iDim+1][0] -= mdot_hat*Velocity_i[iDim]; + val_Jacobian_i[iDim+1][iDim+1] += mdot_hat; + val_Jacobian_i[nVar-1][iDim+1] -= mdot_hat*Gamma_Minus_One*Velocity_i[iDim]; + } + /*--- Energy terms ---*/ + val_Jacobian_i[nVar-1][0] += mdot_hat*dHi_drhoi; + val_Jacobian_i[nVar-1][nVar-1] += mdot_hat*Gamma; + } + else { + /*--- Velocity terms ---*/ + for (iDim = 0; iDim < nDim; ++iDim) { + val_Jacobian_j[iDim+1][0] -= mdot_hat*Velocity_j[iDim]; + val_Jacobian_j[iDim+1][iDim+1] += mdot_hat; + val_Jacobian_j[nVar-1][iDim+1] -= mdot_hat*Gamma_Minus_One*Velocity_j[iDim]; + } + /*--- Energy terms ---*/ + val_Jacobian_j[nVar-1][0] += mdot_hat*dHj_drhoj; + val_Jacobian_j[nVar-1][nVar-1] += mdot_hat*Gamma; + } + +} + +CNumerics::ResidualType<> CUpwAUSMPLUS_SLAU_Base_Flow::ComputeResidual(const CConfig* config) { + + unsigned short iDim, iVar; + + /*--- Space to start preaccumulation ---*/ + + AD::StartPreacc(); + AD::SetPreaccIn(Normal, nDim); + AD::SetPreaccIn(V_i, nDim+4); + AD::SetPreaccIn(V_j, nDim+4); + + /*--- Variables for the general form and primitives for mass flux and pressure calculation. ---*/ + /*--- F_{1/2} = ||A|| ( 0.5 * mdot * (psi_i+psi_j) - 0.5 * |mdot| * (psi_i-psi_j) + N * pf ) ---*/ + + psi_i[0] = 1.0; psi_j[0] = 1.0; + + for (iDim = 0; iDim < nDim; iDim++) { + /*--- Velocities ---*/ + Velocity_i[iDim] = psi_i[iDim+1] = V_i[iDim+1]; + Velocity_j[iDim] = psi_j[iDim+1] = V_j[iDim+1]; + } + + /*--- Pressure and Density ---*/ + Pressure_i = V_i[nDim+1]; Pressure_j = V_j[nDim+1]; + Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; + + /*--- Enthalpy ---*/ + Enthalpy_i = psi_i[nVar-1] = V_i[nDim+3]; + Enthalpy_j = psi_j[nVar-1] = V_j[nDim+3]; + + /*--- Face area (norm or the normal vector) ---*/ + + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Area += Normal[iDim]*Normal[iDim]; + Area = sqrt(Area); + + /*-- Unit Normal ---*/ + for (iDim = 0; iDim < nDim; iDim++) + UnitNormal[iDim] = Normal[iDim]/Area; + + /*--- Mass and pressure fluxes defined by derived classes ---*/ + + ComputeMassAndPressureFluxes(config, MassFlux, Pressure); + DissFlux = fabs(MassFlux); + + Flux[0] = MassFlux; + + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = 0.5*MassFlux*(psi_i[iDim+1]+psi_j[iDim+1]) + + 0.5*DissFlux*(psi_i[iDim+1]-psi_j[iDim+1]) + + UnitNormal[iDim]*Pressure; + + Flux[nVar-1] = 0.5*MassFlux*(psi_i[nVar-1]+psi_j[nVar-1]) + + 0.5*DissFlux*(psi_i[nVar-1]-psi_j[nVar-1]); + + for (iVar = 0; iVar < nVar; iVar++) Flux[iVar] *= Area; + + /*--- Space to end preaccumulation ---*/ + + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + /*--- If required, compute Jacobians, either approximately (Roe) or numerically ---*/ + + if (implicit) { + if (UseAccurateJacobian) + AccurateJacobian(config, Jacobian_i, Jacobian_j); + else + ApproximateJacobian(Jacobian_i, Jacobian_j); + } + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} + +CUpwAUSMPLUSUP_Flow::CUpwAUSMPLUSUP_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CUpwAUSMPLUS_SLAU_Base_Flow(val_nDim, val_nVar, config) { + + HasAnalyticalDerivatives = true; + Minf = config->GetMach(); + Kp = 0.25; + Ku = 0.75; + sigma = 1.0; + + if (Minf < EPS) + SU2_MPI::Error("AUSM+Up requires a reference Mach number (\"MACH_NUMBER\") greater than 0.", CURRENT_FUNCTION); +} + +void CUpwAUSMPLUSUP_Flow::ComputeMassAndPressureFluxes(const CConfig* config, su2double &mdot, su2double &pressure) { + + /*--- Projected velocities ---*/ + + su2double ProjVelocity_i = 0.0, ProjVelocity_j = 0.0; + + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; + } + + /*--- Compute interface speed of sound (aF) ---*/ + + su2double astarL = sqrt(2.0*(Gamma-1.0)/(Gamma+1.0)*Enthalpy_i); + su2double astarR = sqrt(2.0*(Gamma-1.0)/(Gamma+1.0)*Enthalpy_j); + + su2double ahatL = astarL*astarL/max(astarL, ProjVelocity_i); + su2double ahatR = astarR*astarR/max(astarR,-ProjVelocity_j); + + su2double aF = min(ahatL,ahatR); + + /*--- Left and right pressures and Mach numbers ---*/ + + su2double mLP, betaLP, mRM, betaRM; + + su2double mL = ProjVelocity_i/aF; + su2double mR = ProjVelocity_j/aF; + + su2double MFsq = 0.5*(mL*mL+mR*mR); + su2double param1 = max(MFsq, Minf*Minf); + su2double Mrefsq = min(1.0, param1); + + su2double fa = 2.0*sqrt(Mrefsq)-Mrefsq; + + su2double alpha = 3.0/16.0*(-4.0+5.0*fa*fa); + su2double beta = 1.0/8.0; + + if (fabs(mL) <= 1.0) { + su2double p1 = 0.25*(mL+1.0)*(mL+1.0); + su2double p2 = (mL*mL-1.0)*(mL*mL-1.0); + + mLP = p1 + beta*p2; + betaLP = p1*(2.0-mL) + alpha*mL*p2; + } + else { + mLP = 0.5*(mL+fabs(mL)); + betaLP = mLP/mL; + } + + if (fabs(mR) <= 1.0) { + su2double p1 = 0.25*(mR-1.0)*(mR-1.0); + su2double p2 = (mR*mR-1.0)*(mR*mR-1.0); + + mRM = -p1 - beta*p2; + betaRM = p1*(2.0+mR) - alpha*mR*p2; + } + else { + mRM = 0.5*(mR-fabs(mR)); + betaRM = mRM/mR; + } + + /*--- Pressure and velocity diffusion terms ---*/ + + su2double rhoF = 0.5*(Density_i+Density_j); + su2double Mp = -(Kp/fa)*max((1.0-sigma*MFsq),0.0)*(Pressure_j-Pressure_i)/(rhoF*aF*aF); + + su2double Pu = -Ku*fa*betaLP*betaRM*2.0*rhoF*aF*(ProjVelocity_j-ProjVelocity_i); + + /*--- Finally the fluxes ---*/ + + su2double mF = mLP + mRM + Mp; + mdot = aF * (max(mF,0.0)*Density_i + min(mF,0.0)*Density_j); + + pressure = betaLP*Pressure_i + betaRM*Pressure_j + Pu; + + if (!implicit || !UseAccurateJacobian) return; + + /*--- Analytical differentiation of the face mass flux and + pressure (in reverse mode, "?_b" denotes dmot_d?). ---*/ + + /*--- limited mean Mach number (used in division...) ---*/ + su2double MF = max(numeric_limits::epsilon(),sqrt(MFsq)); + + for (int outVar=0; outVar<2; ++outVar) { + + su2double aF_b = 0.0, mF_b = 0.0, MF_b = 0.0, rhoF_b = 0.0, fa_b = 0.0, alpha_b = 0.0, + rho_i_b = 0.0, rho_j_b = 0.0, p_i_b = 0.0, p_j_b = 0.0, Vn_i_b = 0.0, Vn_j_b = 0.0, + mR_b = 0.0, mL_b = 0.0, betaLP_b = 0.0, betaRM_b = 0.0, tmp = 0.0; + + if (outVar==0) { + /*--- mdot = ... ---*/ + if (mF > 0.0) { + aF_b += mF*Density_i; + mF_b += aF*Density_i; + rho_i_b += mF*aF; + } + else { + aF_b += mF*Density_j; + mF_b += aF*Density_j; + rho_j_b += mF*aF; + } + + /*--- Mp = ... ---*/ + if (sigma*MFsq < 1.0) { + rhoF_b -= Mp/rhoF * mF_b; + fa_b -= Mp/fa * mF_b; + aF_b -= 2.0*Mp/aF * mF_b; + MF_b += 2.0*sigma*MF*(Kp/fa)*(Pressure_j-Pressure_i)/(rhoF*aF*aF) * mF_b; + tmp = -(Kp/fa)*(1.0-sigma*MFsq)/(rhoF*aF*aF); + p_i_b -= tmp * mF_b; + p_j_b += tmp * mF_b; + } + + /*--- rhoF = ... ---*/ + rho_i_b += 0.5*rhoF_b; rho_j_b += 0.5*rhoF_b; + + /*--- mRM = ... ---*/ + if (fabs(mR) < 1.0) mR_b += (1.0-mR)*(0.5+4.0*beta*mR*(mR+1.0)) * mF_b; + else if (mR <=-1.0) mR_b += mF_b; + + /*--- mLP = ... ---*/ + if (fabs(mL) < 1.0) mL_b += (1.0+mL)*(0.5+4.0*beta*mL*(mL-1.0)) * mF_b; + else if (mL >= 1.0) mL_b += mF_b; + } + else { + /*--- pressure = ... ---*/ + p_i_b += betaLP; betaLP_b += Pressure_i; + p_j_b += betaRM; betaRM_b += Pressure_j; + + /*--- Pu = ... ---*/ + rhoF_b += Pu/rhoF; + fa_b += Pu/fa; + aF_b += Pu/aF; + tmp = -Ku*fa*2.0*rhoF*aF*(ProjVelocity_j-ProjVelocity_i); + betaLP_b += tmp*betaRM; + betaRM_b += tmp*betaLP; + tmp = -Ku*fa*betaLP*betaRM*2.0*rhoF*aF; + Vn_i_b -= tmp; + Vn_j_b += tmp; + + /*--- rhoF = ... ---*/ + rho_i_b += 0.5*rhoF_b; rho_j_b += 0.5*rhoF_b; + + /*--- betaRM = ... ---*/ + if (fabs(mR) < 1.0) { + tmp = mR*mR-1.0; + mR_b += tmp*(0.75-alpha*(5.0*tmp+4.0)) * betaRM_b; + alpha_b -= mR*tmp*tmp * betaRM_b; + } + + /*--- betaLP = ... ---*/ + if (fabs(mL) < 1.0) { + tmp = mL*mL-1.0; + mL_b -= tmp*(0.75-alpha*(5.0*tmp+4.0)) * betaLP_b; + alpha_b += mL*tmp*tmp * betaLP_b; + } + + /*--- alpha = ... ---*/ + fa_b += 1.875*fa * alpha_b; + } + + /*--- steps shared by both ---*/ + /*--- fa = ... ---*/ + su2double Mref_b = 2.0*(1.0-sqrt(Mrefsq)) * fa_b; + + /*--- Mrefsq = ... ---*/ + if (MF < 1.0 && MF > Minf) MF_b += Mref_b; + + /*--- MFsq = ... ---*/ + mL_b += 0.5*mL/MF * MF_b; mR_b += 0.5*mR/MF * MF_b; + + /*--- mL/R = ... ---*/ + Vn_i_b += mL_b/aF; Vn_j_b += mR_b/aF; + aF_b -= (mL*mL_b+mR*mR_b)/aF; + + /*--- aF,ahat,astar = f(H_i,H_j) ---*/ + su2double astar_b = aF_b, H_i_b, H_j_b; + + if (ahatL < ahatR) { + if (astarL <= ProjVelocity_i) { + tmp = astarL/ProjVelocity_i; + astar_b *= 2.0*tmp; + Vn_i_b -= tmp*tmp * aF_b; + } + H_i_b = sqrt(0.5*(Gamma-1.0)/((Gamma+1.0)*Enthalpy_i)) * astar_b; + H_j_b = 0.0; + } + else { + if (astarR <= -ProjVelocity_j) { + tmp = -astarR/ProjVelocity_j; + astar_b *= 2.0*tmp; + Vn_j_b += tmp*tmp * aF_b; + } + H_j_b = sqrt(0.5*(Gamma-1.0)/((Gamma+1.0)*Enthalpy_j)) * astar_b; + H_i_b = 0.0; + } + + /*--- store derivatives ---*/ + su2double *target_i = (outVar==0 ? dmdot_dVi : dpres_dVi), + *target_j = (outVar==0 ? dmdot_dVj : dpres_dVj); + target_i[5] = target_j[5] = 0.0; + + /*--- ProjVelocity = ... ---*/ + for (unsigned short iDim = 0; iDim < nDim; ++iDim) { + target_i[iDim] = UnitNormal[iDim] * Vn_i_b; + target_j[iDim] = UnitNormal[iDim] * Vn_j_b; + } + target_i[ nDim ] = p_i_b; target_j[ nDim ] = p_j_b; + target_i[nDim+1] = rho_i_b; target_j[nDim+1] = rho_j_b; + target_i[nDim+2] = H_i_b; target_j[nDim+2] = H_j_b; + } +} + +CUpwAUSMPLUSUP2_Flow::CUpwAUSMPLUSUP2_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CUpwAUSMPLUS_SLAU_Base_Flow(val_nDim, val_nVar, config) { + + Minf = config->GetMach(); + Kp = 0.25; + sigma = 1.0; + + if (Minf < EPS) + SU2_MPI::Error("AUSM+Up2 requires a reference Mach number (\"MACH_NUMBER\") greater than 0.", CURRENT_FUNCTION); +} + +void CUpwAUSMPLUSUP2_Flow::ComputeMassAndPressureFluxes(const CConfig* config, su2double &mdot, su2double &pressure) { + + /*--- Projected velocities and squared magnitude ---*/ + + su2double ProjVelocity_i = 0.0, ProjVelocity_j = 0.0, sq_vel = 0.0; + + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; + + sq_vel += 0.5*(Velocity_i[iDim]*Velocity_i[iDim] + Velocity_j[iDim]*Velocity_j[iDim]); + } + + /*--- Compute interface speed of sound (aF) ---*/ + + su2double astarL = sqrt(2.0*(Gamma-1.0)/(Gamma+1.0)*Enthalpy_i); + su2double astarR = sqrt(2.0*(Gamma-1.0)/(Gamma+1.0)*Enthalpy_j); + + su2double ahatL = astarL*astarL/max(astarL, ProjVelocity_i); + su2double ahatR = astarR*astarR/max(astarR,-ProjVelocity_j); + + su2double aF = min(ahatL,ahatR); + + /*--- Left and right pressure functions and Mach numbers ---*/ + + su2double mLP, pLP, mRM, pRM; + + su2double mL = ProjVelocity_i/aF; + su2double mR = ProjVelocity_j/aF; + + su2double MFsq = 0.5*(mL*mL+mR*mR); + su2double param1 = max(MFsq, Minf*Minf); + su2double Mrefsq = min(1.0, param1); + + su2double fa = 2.0*sqrt(Mrefsq)-Mrefsq; + + su2double alpha = 3.0/16.0*(-4.0+5.0*fa*fa); + su2double beta = 1.0/8.0; + + if (fabs(mL) <= 1.0) { + su2double p1 = 0.25*(mL+1.0)*(mL+1.0); + su2double p2 = (mL*mL-1.0)*(mL*mL-1.0); + + mLP = p1 + beta*p2; + pLP = p1*(2.0-mL) + alpha*mL*p2; + } + else { + mLP = 0.5*(mL+fabs(mL)); + pLP = mLP/mL; + } + + if (fabs(mR) <= 1.0) { + su2double p1 = 0.25*(mR-1.0)*(mR-1.0); + su2double p2 = (mR*mR-1.0)*(mR*mR-1.0); + + mRM = -p1 - beta*p2; + pRM = p1*(2.0+mR) - alpha*mR*p2; + } + else { + mRM = 0.5*(mR-fabs(mR)); + pRM = mRM/mR; + } + + /*--- Mass flux with pressure diffusion term ---*/ + + su2double rhoF = 0.5*(Density_i+Density_j); + su2double Mp = -(Kp/fa)*max((1.0-sigma*MFsq),0.0)*(Pressure_j-Pressure_i)/(rhoF*aF*aF); + + su2double mF = mLP + mRM + Mp; + mdot = aF * (max(mF,0.0)*Density_i + min(mF,0.0)*Density_j); + + /*--- Modified pressure flux ---*/ + + pressure = 0.5*(Pressure_j+Pressure_i) + 0.5*(pLP-pRM)*(Pressure_i-Pressure_j) + sqrt(sq_vel)*(pLP+pRM-1.0)*rhoF*aF; + +} + +CUpwSLAU_Flow::CUpwSLAU_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config, bool val_low_dissipation) : + CUpwAUSMPLUS_SLAU_Base_Flow(val_nDim, val_nVar, config) { + + slau_low_diss = val_low_dissipation; + slau2 = false; +} + +CUpwSLAU2_Flow::CUpwSLAU2_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config, bool val_low_dissipation) : + CUpwSLAU_Flow(val_nDim, val_nVar, config, val_low_dissipation) { + + /*--- The difference between SLAU and SLAU2 is minimal, so we derive from SLAU and set this flag + so that the ComputeMassAndPressureFluxes function modifies the pressure according to SLAU2. + This is safe since this constructor is guaranteed to execute after SLAU's one. ---*/ + slau2 = true; +} + +void CUpwSLAU_Flow::ComputeMassAndPressureFluxes(const CConfig* config, su2double &mdot, su2double &pressure) { + + /*--- Project velocities and speed of sound ---*/ + + su2double ProjVelocity_i = 0.0, ProjVelocity_j = 0.0, sq_veli = 0.0, sq_velj = 0.0; + + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; + + sq_veli += Velocity_i[iDim]*Velocity_i[iDim]; + sq_velj += Velocity_j[iDim]*Velocity_j[iDim]; + } + + su2double Energy_i = Enthalpy_i - Pressure_i/Density_i; + SoundSpeed_i = sqrt(fabs(Gamma*Gamma_Minus_One*(Energy_i-0.5*sq_veli))); + + su2double Energy_j = Enthalpy_j - Pressure_j/Density_j; + SoundSpeed_j = sqrt(fabs(Gamma*Gamma_Minus_One*(Energy_j-0.5*sq_velj))); + + /*--- Compute interface speed of sound (aF), and left/right Mach number ---*/ + + su2double aF = 0.5 * (SoundSpeed_i + SoundSpeed_j); + su2double mL = ProjVelocity_i/aF; + su2double mR = ProjVelocity_j/aF; + + /*--- Smooth function of the local Mach number---*/ + + su2double Mach_tilde = min(1.0, (1.0/aF) * sqrt(0.5*(sq_veli+sq_velj))); + su2double Chi = pow((1.0 - Mach_tilde),2.0); + su2double f_rho = -max(min(mL,0.0),-1.0) * min(max(mR,0.0),1.0); + + /*--- Mean normal velocity with density weighting ---*/ + + su2double Vn_Mag = (Density_i*fabs(ProjVelocity_i) + Density_j*fabs(ProjVelocity_j)) / (Density_i + Density_j); + su2double Vn_MagL= (1.0 - f_rho)*Vn_Mag + f_rho*fabs(ProjVelocity_i); + su2double Vn_MagR= (1.0 - f_rho)*Vn_Mag + f_rho*fabs(ProjVelocity_j); + + /*--- Mass flux function ---*/ + + mdot = 0.5 * (Density_i*(ProjVelocity_i+Vn_MagL) + Density_j*(ProjVelocity_j-Vn_MagR) - (Chi/aF)*(Pressure_j-Pressure_i)); + + /*--- Pressure function ---*/ + + su2double BetaL, BetaR, Dissipation_ij; + + if (fabs(mL) < 1.0) BetaL = 0.25*(2.0-mL)*pow((mL+1.0),2.0); + else if (mL >= 0) BetaL = 1.0; + else BetaL = 0.0; + + if (fabs(mR) < 1.0) BetaR = 0.25*(2.0+mR)*pow((mR-1.0),2.0); + else if (mR >= 0) BetaR = 0.0; + else BetaR = 1.0; + + if (slau_low_diss) + Dissipation_ij = GetRoe_Dissipation(Dissipation_i, Dissipation_j, Sensor_i, Sensor_j, config); + else + Dissipation_ij = 1.0; + + pressure = 0.5*(Pressure_i+Pressure_j) + 0.5*(BetaL-BetaR)*(Pressure_i-Pressure_j); + + if (!slau2) pressure += Dissipation_ij*(1.0-Chi)*(BetaL+BetaR-1.0)*0.5*(Pressure_i+Pressure_j); + else pressure += Dissipation_ij*sqrt(0.5*(sq_veli+sq_velj))*(BetaL+BetaR-1.0)*aF*0.5*(Density_i+Density_j); + +} + +CUpwAUSM_Flow::CUpwAUSM_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : CNumerics(val_nDim, val_nVar, config) { + + if (config->GetDynamic_Grid() && (SU2_MPI::GetRank() == MASTER_NODE)) + cout << "WARNING: Grid velocities are NOT yet considered in AUSM-type schemes." << endl; + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + Flux = new su2double [nVar]; + Diff_U = new su2double [nVar]; + delta_wave = new su2double [nVar]; + ProjFlux_i = new su2double [nVar]; + ProjFlux_j = new su2double [nVar]; + Lambda = new su2double [nVar]; + Epsilon = new su2double [nVar]; + P_Tensor = new su2double* [nVar]; + invP_Tensor = new su2double* [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + P_Tensor[iVar] = new su2double [nVar]; + invP_Tensor[iVar] = new su2double [nVar]; + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CUpwAUSM_Flow::~CUpwAUSM_Flow(void) { + + delete [] Flux; + delete [] Diff_U; + delete [] delta_wave; + delete [] ProjFlux_i; + delete [] ProjFlux_j; + delete [] Lambda; + delete [] Epsilon; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] P_Tensor[iVar]; + delete [] invP_Tensor[iVar]; + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] P_Tensor; + delete [] invP_Tensor; + delete [] Jacobian_i; + delete [] Jacobian_j; + +} + +CNumerics::ResidualType<> CUpwAUSM_Flow::ComputeResidual(const CConfig* config) { + + AD::StartPreacc(); + AD::SetPreaccIn(Normal, nDim); + AD::SetPreaccIn(V_i, nDim+4); + AD::SetPreaccIn(V_j, nDim+4); + + /*--- Face area (norm or the normal vector) ---*/ + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Area += Normal[iDim]*Normal[iDim]; + Area = sqrt(Area); + + /*-- Unit Normal ---*/ + for (iDim = 0; iDim < nDim; iDim++) + UnitNormal[iDim] = Normal[iDim]/Area; + + /*--- Primitive variables at point i ---*/ + sq_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + sq_vel += Velocity_i[iDim]*Velocity_i[iDim]; + } + Pressure_i = V_i[nDim+1]; + Density_i = V_i[nDim+2]; + Enthalpy_i = V_i[nDim+3]; + Energy_i = Enthalpy_i - Pressure_i/Density_i; + SoundSpeed_i = sqrt(fabs(Gamma*Gamma_Minus_One*(Energy_i-0.5*sq_vel))); + + /*--- Primitive variables at point j ---*/ + sq_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_j[iDim] = V_j[iDim+1]; + sq_vel += Velocity_j[iDim]*Velocity_j[iDim]; + } + Pressure_j = V_j[nDim+1]; + Density_j = V_j[nDim+2]; + Enthalpy_j = V_j[nDim+3]; + Energy_j = Enthalpy_j - Pressure_j/Density_j; + SoundSpeed_j = sqrt(fabs(Gamma*Gamma_Minus_One*(Energy_j-0.5*sq_vel))); + + /*--- Projected velocities ---*/ + ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; + } + + mL = ProjVelocity_i/SoundSpeed_i; + mR = ProjVelocity_j/SoundSpeed_j; + + if (fabs(mL) <= 1.0) mLP = 0.25*(mL+1.0)*(mL+1.0); + else mLP = 0.5*(mL+fabs(mL)); + + if (fabs(mR) <= 1.0) mRM = -0.25*(mR-1.0)*(mR-1.0); + else mRM = 0.5*(mR-fabs(mR)); + + mF = mLP + mRM; + + if (fabs(mL) <= 1.0) pLP = 0.25*Pressure_i*(mL+1.0)*(mL+1.0)*(2.0-mL); + else pLP = 0.5*Pressure_i*(mL+fabs(mL))/mL; + + if (fabs(mR) <= 1.0) pRM = 0.25*Pressure_j*(mR-1.0)*(mR-1.0)*(2.0+mR); + else pRM = 0.5*Pressure_j*(mR-fabs(mR))/mR; + + pF = pLP + pRM; + Phi = fabs(mF); + + Flux[0] = 0.5*(mF*((Density_i*SoundSpeed_i)+(Density_j*SoundSpeed_j))-Phi*((Density_j*SoundSpeed_j)-(Density_i*SoundSpeed_i))); + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = 0.5*(mF*((Density_i*SoundSpeed_i*Velocity_i[iDim])+(Density_j*SoundSpeed_j*Velocity_j[iDim])) + -Phi*((Density_j*SoundSpeed_j*Velocity_j[iDim])-(Density_i*SoundSpeed_i*Velocity_i[iDim])))+UnitNormal[iDim]*pF; + Flux[nVar-1] = 0.5*(mF*((Density_i*SoundSpeed_i*Enthalpy_i)+(Density_j*SoundSpeed_j*Enthalpy_j))-Phi*((Density_j*SoundSpeed_j*Enthalpy_j)-(Density_i*SoundSpeed_i*Enthalpy_i))); + + for (iVar = 0; iVar < nVar; iVar++) + Flux[iVar] *= Area; + + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + /*--- Roe's Jacobian for AUSM (this must be fixed) ---*/ + if (implicit) { + + /*--- Mean Roe variables iPoint and jPoint ---*/ + R = sqrt(fabs(Density_j/Density_i)); + RoeDensity = R*Density_i; + sq_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); + sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; + } + RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); + RoeSoundSpeed = sqrt(fabs((Gamma-1)*(RoeEnthalpy-0.5*sq_vel))); + + /*--- Compute P and Lambda (do it with the Normal) ---*/ + GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, P_Tensor); + + ProjVelocity = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; + ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; + } + + /*--- Flow eigenvalues and Entropy correctors ---*/ + for (iDim = 0; iDim < nDim; iDim++) + Lambda[iDim] = ProjVelocity; + Lambda[nVar-2] = ProjVelocity + RoeSoundSpeed; + Lambda[nVar-1] = ProjVelocity - RoeSoundSpeed; + + /*--- Compute inverse P ---*/ + GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); + + /*--- Jacobias of the inviscid flux, scale = 0.5 because val_residual ~ 0.5*(fc_i+fc_j)*Normal ---*/ + GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5, Jacobian_i); + GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5, Jacobian_j); + + /*--- Roe's Flux approximation ---*/ + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Proj_ModJac_Tensor_ij = 0.0; + /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*fabs(Lambda[kVar])*invP_Tensor[kVar][jVar]; + Jacobian_i[iVar][jVar] += 0.5*Proj_ModJac_Tensor_ij*Area; + Jacobian_j[iVar][jVar] -= 0.5*Proj_ModJac_Tensor_ij*Area; + } + } + } + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); +} diff --git a/SU2_CFD/src/numerics/flow/convection/centered.cpp b/SU2_CFD/src/numerics/flow/convection/centered.cpp new file mode 100644 index 000000000000..0c52f2f9ae8a --- /dev/null +++ b/SU2_CFD/src/numerics/flow/convection/centered.cpp @@ -0,0 +1,779 @@ +/*! + * \file centered.cpp + * \brief Implementations of centered schemes. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../../include/numerics/flow/convection/centered.hpp" + +CCentBase_Flow::CCentBase_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + /* 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(); + fix_factor = config->GetCent_Jac_Fix_Factor(); + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + /*--- Allocate required structures ---*/ + Diff_U = new su2double [nVar]; + Diff_Lapl = new su2double [nVar]; + ProjFlux = new su2double [nVar]; + 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]; + } +} + +CCentBase_Flow::~CCentBase_Flow(void) { + delete [] Diff_U; + delete [] Diff_Lapl; + delete [] ProjFlux; + + if (Jacobian_i != nullptr) { + for (iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Jacobian_i; + delete [] Jacobian_j; + } +} + +CNumerics::ResidualType<> CCentBase_Flow::ComputeResidual(const CConfig* config) { + + su2double U_i[5] = {0.0}, U_j[5] = {0.0}; + + bool preacc = SetPreaccInVars(); + + if (preacc) { + AD::SetPreaccIn(Normal, nDim); + AD::SetPreaccIn(V_i, nDim+5); AD::SetPreaccIn(V_j, nDim+5); + AD::SetPreaccIn(Lambda_i); AD::SetPreaccIn(Lambda_j); + if (dynamic_grid) { + AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); + } + } + + /*--- Pressure, density, enthalpy, energy, and velocity at points i and j ---*/ + + Pressure_i = V_i[nDim+1]; Pressure_j = V_j[nDim+1]; + Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; + Enthalpy_i = V_i[nDim+3]; Enthalpy_j = V_j[nDim+3]; + SoundSpeed_i = V_i[nDim+4]; SoundSpeed_j = V_j[nDim+4]; + Energy_i = Enthalpy_i - Pressure_i/Density_i; Energy_j = Enthalpy_j - Pressure_j/Density_j; + + sq_vel_i = 0.0; sq_vel_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Velocity_j[iDim] = V_j[iDim+1]; + sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; + sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; + } + + /*--- Recompute conservative variables ---*/ + + U_i[0] = Density_i; U_j[0] = Density_j; + for (iDim = 0; iDim < nDim; iDim++) { + U_i[iDim+1] = Density_i*Velocity_i[iDim]; U_j[iDim+1] = Density_j*Velocity_j[iDim]; + } + U_i[nDim+1] = Density_i*Energy_i; U_j[nDim+1] = Density_j*Energy_j; + + /*--- Compute mean values of the variables ---*/ + + MeanDensity = 0.5*(Density_i+Density_j); + MeanPressure = 0.5*(Pressure_i+Pressure_j); + MeanEnthalpy = 0.5*(Enthalpy_i+Enthalpy_j); + for (iDim = 0; iDim < nDim; iDim++) + MeanVelocity[iDim] = 0.5*(Velocity_i[iDim]+Velocity_j[iDim]); + MeanEnergy = 0.5*(Energy_i+Energy_j); + + /*--- Residual of the inviscid flux ---*/ + + GetInviscidProjFlux(&MeanDensity, MeanVelocity, &MeanPressure, &MeanEnthalpy, Normal, ProjFlux); + + /*--- Jacobians of the inviscid flux, scale = 0.5 because ProjFlux ~ 0.5*(fc_i+fc_j)*Normal ---*/ + + if (implicit) { + GetInviscidProjJac(MeanVelocity, &MeanEnergy, Normal, 0.5, Jacobian_i); + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + Jacobian_j[iVar][jVar] = Jacobian_i[iVar][jVar]; + } + + /*--- Adjustment due to grid motion ---*/ + + if (dynamic_grid) { + ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + + for (iVar = 0; iVar < nVar; iVar++) { + ProjFlux[iVar] -= ProjGridVel * 0.5*(U_i[iVar] + U_j[iVar]); + if (implicit) { + Jacobian_i[iVar][iVar] -= 0.5*ProjGridVel; + Jacobian_j[iVar][iVar] -= 0.5*ProjGridVel; + } + } + } + + /*--- Compute the local spectral radius and the stretching factor ---*/ + + ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; + Area += Normal[iDim]*Normal[iDim]; + } + Area = sqrt(Area); + + /*--- Adjustment due to mesh motion ---*/ + + if (dynamic_grid) { + ProjVelocity_i -= ProjGridVel; + ProjVelocity_j -= ProjGridVel; + } + + /*--- Dissipation term ---*/ + + Local_Lambda_i = (fabs(ProjVelocity_i)+SoundSpeed_i*Area); + Local_Lambda_j = (fabs(ProjVelocity_j)+SoundSpeed_j*Area); + MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); + + Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); + Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); + StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); + + /*--- Compute differences btw. conservative variables, with a correction for enthalpy ---*/ + + for (iVar = 0; iVar < nVar-1; iVar++) { + Diff_U[iVar] = U_i[iVar]-U_j[iVar]; + } + Diff_U[nVar-1] = Density_i*Enthalpy_i-Density_j*Enthalpy_j; + + DissipationTerm(ProjFlux, Jacobian_i, Jacobian_j); + + if (preacc) { + AD::SetPreaccOut(ProjFlux, nVar); + AD::EndPreacc(); + } + + return ResidualType<>(ProjFlux, Jacobian_i, Jacobian_j); + +} + +void CCentBase_Flow::ScalarDissipationJacobian(su2double **val_Jacobian_i, su2double **val_Jacobian_j) { + + /*--- n-1 diagonal entries ---*/ + + for (iVar = 0; iVar < (nVar-1); iVar++) { + val_Jacobian_i[iVar][iVar] += fix_factor*cte_0; + val_Jacobian_j[iVar][iVar] -= fix_factor*cte_1; + } + + /*--- Last row of Jacobian_i ---*/ + + val_Jacobian_i[nVar-1][0] += fix_factor*cte_0*Gamma_Minus_One*sq_vel_i; + for (iDim = 0; iDim < nDim; iDim++) + val_Jacobian_i[nVar-1][iDim+1] -= fix_factor*cte_0*Gamma_Minus_One*Velocity_i[iDim]; + val_Jacobian_i[nVar-1][nVar-1] += fix_factor*cte_0*Gamma; + + /*--- Last row of Jacobian_j ---*/ + + val_Jacobian_j[nVar-1][0] -= fix_factor*cte_1*Gamma_Minus_One*sq_vel_j; + for (iDim = 0; iDim < nDim; iDim++) + val_Jacobian_j[nVar-1][iDim+1] += fix_factor*cte_1*Gamma_Minus_One*Velocity_j[iDim]; + val_Jacobian_j[nVar-1][nVar-1] -= fix_factor*cte_1*Gamma; + +} + +CCentLax_Flow::CCentLax_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CCentBase_Flow(val_nDim, val_nVar, config) { + + /*--- Artifical dissipation parameters ---*/ + Param_p = 0.3; + Param_Kappa_0 = config->GetKappa_1st_Flow(); + +} + +void CCentLax_Flow::DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) { + + /*--- Compute dissipation coefficient ---*/ + + sc0 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); + Epsilon_0 = Param_Kappa_0*sc0*su2double(nDim)/3.0; + + /*--- Compute viscous part of the residual ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + val_residual[iVar] += Epsilon_0*Diff_U[iVar]*StretchingFactor*MeanLambda; + + /*--- Jacobian computation ---*/ + + if (implicit) { + + cte_0 = Epsilon_0*StretchingFactor*MeanLambda; + cte_1 = cte_0; + + ScalarDissipationJacobian(val_Jacobian_i, val_Jacobian_j); + } +} + +bool CCentLax_Flow::SetPreaccInVars(void) { + AD::StartPreacc(); + return true; +} + +CCentJST_KE_Flow::CCentJST_KE_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CCentBase_Flow(val_nDim, val_nVar, config) { + + /*--- Artifical dissipation parameters ---*/ + Param_p = 0.3; + Param_Kappa_2 = config->GetKappa_2nd_Flow(); + +} + +void CCentJST_KE_Flow::DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) { + + /*--- Compute dissipation coefficient ---*/ + + sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); + Epsilon_2 = Param_Kappa_2*0.5*(Sensor_i+Sensor_j)*sc2; + + /*--- Compute viscous part of the residual ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + val_residual[iVar] += Epsilon_2*(Diff_U[iVar])*StretchingFactor*MeanLambda; + + /*--- Jacobian computation ---*/ + + if (implicit) { + + cte_0 = Epsilon_2*StretchingFactor*MeanLambda; + cte_1 = cte_0; + + ScalarDissipationJacobian(val_Jacobian_i, val_Jacobian_j); + } +} + +bool CCentJST_KE_Flow::SetPreaccInVars(void) { + AD::StartPreacc(); + AD::SetPreaccIn(Sensor_i); AD::SetPreaccIn(Sensor_j); + return true; +} + +CCentJST_Flow::CCentJST_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CCentBase_Flow(val_nDim, val_nVar, config) { + + /*--- Artifical dissipation parameters ---*/ + Param_p = 0.3; + Param_Kappa_2 = config->GetKappa_2nd_Flow(); + Param_Kappa_4 = config->GetKappa_4th_Flow(); + +} + +void CCentJST_Flow::DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) { + + /*--- Compute differences btw. Laplacians ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Diff_Lapl[iVar] = Und_Lapl_i[iVar]-Und_Lapl_j[iVar]; + } + + /*--- Compute dissipation coefficients ---*/ + + sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); + sc4 = sc2*sc2/4.0; + + Epsilon_2 = Param_Kappa_2*0.5*(Sensor_i+Sensor_j)*sc2; + Epsilon_4 = max(0.0, Param_Kappa_4-Epsilon_2)*sc4; + + /*--- Compute viscous part of the residual ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + val_residual[iVar] += (Epsilon_2*Diff_U[iVar] - Epsilon_4*Diff_Lapl[iVar])*StretchingFactor*MeanLambda; + + /*--- Jacobian computation ---*/ + + if (implicit) { + + cte_0 = (Epsilon_2 + Epsilon_4*su2double(Neighbor_i+1))*StretchingFactor*MeanLambda; + cte_1 = (Epsilon_2 + Epsilon_4*su2double(Neighbor_j+1))*StretchingFactor*MeanLambda; + + ScalarDissipationJacobian(val_Jacobian_i, val_Jacobian_j); + } +} + +bool CCentJST_Flow::SetPreaccInVars(void) { + AD::StartPreacc(); + AD::SetPreaccIn(Sensor_i); AD::SetPreaccIn(Und_Lapl_i, nVar); + AD::SetPreaccIn(Sensor_j); AD::SetPreaccIn(Und_Lapl_j, nVar); + return true; +} + +CCentLaxInc_Flow::CCentLaxInc_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + variable_density = (config->GetKind_DensityModel() == VARIABLE); + /* 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(); + energy = config->GetEnergy_Equation(); + + /*--- Artificial dissipation part ---*/ + + Param_p = 0.3; + Param_Kappa_0 = config->GetKappa_1st_Flow(); + + /*--- Allocate some structures ---*/ + + Diff_V = new su2double[nVar]; + Velocity_i = new su2double[nDim]; + Velocity_j = new su2double[nDim]; + MeanVelocity = new su2double[nDim]; + ProjFlux = new su2double[nVar]; + Precon = new su2double*[nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (iVar = 0; iVar < nVar; iVar++) { + Precon[iVar] = new su2double[nVar]; + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } + +} + +CCentLaxInc_Flow::~CCentLaxInc_Flow(void) { + + delete [] Diff_V; + delete [] Velocity_i; + delete [] Velocity_j; + delete [] MeanVelocity; + delete [] ProjFlux; + + for (iVar = 0; iVar < nVar; iVar++) + delete [] Precon[iVar]; + delete [] Precon; + + if (Jacobian_i != nullptr) { + for (iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Jacobian_i; + delete [] Jacobian_j; + } + +} + +CNumerics::ResidualType<> CCentLaxInc_Flow::ComputeResidual(const CConfig* config) { + + su2double U_i[5] = {0.0}, U_j[5] = {0.0}; + su2double ProjGridVel = 0.0, ProjVelocity = 0.0; + + /*--- Primitive variables at point i and j ---*/ + + Pressure_i = V_i[0]; Pressure_j = V_j[0]; + Temperature_i = V_i[nDim+1]; Temperature_j = V_j[nDim+1]; + DensityInc_i = V_i[nDim+2]; DensityInc_j = V_j[nDim+2]; + BetaInc2_i = V_i[nDim+3]; BetaInc2_j = V_j[nDim+3]; + Cp_i = V_i[nDim+7]; Cp_j = V_j[nDim+7]; + Enthalpy_i = Cp_i*Temperature_i; Enthalpy_j = Cp_j*Temperature_j; + + Area = 0.0; + sq_vel_i = 0.0; sq_vel_j = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Velocity_j[iDim] = V_j[iDim+1]; + MeanVelocity[iDim] = 0.5*(Velocity_i[iDim]+Velocity_j[iDim]); + sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; + sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; + ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; + Area += Normal[iDim]*Normal[iDim]; + } + Area = sqrt(Area); + + /*--- Compute mean values of the variables ---*/ + + MeanDensity = 0.5*(DensityInc_i + DensityInc_j); + MeanPressure = 0.5*(Pressure_i + Pressure_j); + MeanBetaInc2 = 0.5*(BetaInc2_i + BetaInc2_j); + MeanEnthalpy = 0.5*(Enthalpy_i + Enthalpy_j); + MeanCp = 0.5*(Cp_i + Cp_j); + MeanTemperature = 0.5*(Temperature_i + Temperature_j); + + /*--- We need the derivative of the equation of state to build the + preconditioning matrix. For now, the only option is the ideal gas + law, but in the future, dRhodT should be in the fluid model. ---*/ + + MeandRhodT = 0.0; + if (variable_density) { + MeandRhodT = -MeanDensity/MeanTemperature; + } + + /*--- Get projected flux tensor ---*/ + + GetInviscidIncProjFlux(&MeanDensity, MeanVelocity, &MeanPressure, &MeanBetaInc2, &MeanEnthalpy, Normal, ProjFlux); + + /*--- Jacobians of the inviscid flux ---*/ + + if (implicit) { + GetInviscidIncProjJac(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Normal, 0.5, Jacobian_i); + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_j[iVar][jVar] = Jacobian_i[iVar][jVar]; + } + } + } + + /*--- Corrections due to grid motion ---*/ + if (dynamic_grid) { + + /*--- Recompute conservative variables ---*/ + + U_i[0] = DensityInc_i; U_j[0] = DensityInc_j; + for (iDim = 0; iDim < nDim; iDim++) { + U_i[iDim+1] = DensityInc_i*Velocity_i[iDim]; U_j[iDim+1] = DensityInc_j*Velocity_j[iDim]; + } + U_i[nDim+1] = DensityInc_i*Enthalpy_i; U_j[nDim+1] = DensityInc_j*Enthalpy_j; + + for (iDim = 0; iDim < nDim; iDim++) + ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + + /*--- Residual contributions ---*/ + for (iVar = 0; iVar < nVar; iVar++) { + ProjFlux[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); + + /*--- Jacobian contributions ---*/ + /*--- Implicit terms ---*/ + if (implicit) { + for (iDim = 0; iDim < nDim; iDim++){ + Jacobian_i[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_i; + Jacobian_j[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_j; + } + Jacobian_i[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_i*Cp_i; + Jacobian_j[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_j*Cp_j; + } + } + } + + /*--- Computes differences btw. conservative variables ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Diff_V[iVar] = V_i[iVar]-V_j[iVar]; + + /*--- Build the preconditioning matrix using mean values ---*/ + + GetPreconditioner(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Precon); + + /*--- Compute the local espectral radius of the preconditioned system + and the stretching factor. ---*/ + + SoundSpeed_i = sqrt(BetaInc2_i*Area*Area); + SoundSpeed_j = sqrt(BetaInc2_j*Area*Area); + + /*--- Projected velocity adjustment due to mesh motion ---*/ + + if (dynamic_grid) { + ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + } + ProjVelocity_i -= ProjGridVel; + ProjVelocity_j -= ProjGridVel; + } + + Local_Lambda_i = fabs(ProjVelocity_i)+SoundSpeed_i; + Local_Lambda_j = fabs(ProjVelocity_j)+SoundSpeed_j; + + MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); + + Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); + Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); + + StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); + + sc0 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); + Epsilon_0 = Param_Kappa_0*sc0*su2double(nDim)/3.0; + + /*--- Compute viscous part of the residual ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + ProjFlux[iVar] += Precon[iVar][jVar]*Epsilon_0*Diff_V[jVar]*StretchingFactor*MeanLambda; + if (implicit) { + Jacobian_i[iVar][jVar] += Precon[iVar][jVar]*Epsilon_0*StretchingFactor*MeanLambda; + Jacobian_j[iVar][jVar] -= Precon[iVar][jVar]*Epsilon_0*StretchingFactor*MeanLambda; + } + } + } + + /*--- Remove energy contributions if we aren't solving the energy equation. ---*/ + + if (!energy) { + ProjFlux[nDim+1] = 0.0; + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) { + Jacobian_i[iVar][nDim+1] = 0.0; + Jacobian_j[iVar][nDim+1] = 0.0; + + Jacobian_i[nDim+1][iVar] = 0.0; + Jacobian_j[nDim+1][iVar] = 0.0; + } + } + } + + return ResidualType<>(ProjFlux, Jacobian_i, Jacobian_j); + +} + + +CCentJSTInc_Flow::CCentJSTInc_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + variable_density = (config->GetKind_DensityModel() == VARIABLE); + energy = config->GetEnergy_Equation(); + /* 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(); + + /*--- Artifical dissipation part ---*/ + + Param_p = 0.3; + Param_Kappa_2 = config->GetKappa_2nd_Flow(); + Param_Kappa_4 = config->GetKappa_4th_Flow(); + + /*--- Allocate some structures ---*/ + + Diff_V = new su2double [nVar]; + Diff_Lapl = new su2double [nVar]; + Velocity_i = new su2double [nDim]; + Velocity_j = new su2double [nDim]; + MeanVelocity = new su2double [nDim]; + ProjFlux = new su2double [nVar]; + Precon = new su2double*[nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (iVar = 0; iVar < nVar; iVar++) { + Precon[iVar] = new su2double[nVar]; + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } + +} + +CCentJSTInc_Flow::~CCentJSTInc_Flow(void) { + + delete [] Diff_V; + delete [] Diff_Lapl; + delete [] Velocity_i; + delete [] Velocity_j; + delete [] MeanVelocity; + delete [] ProjFlux; + + for (iVar = 0; iVar < nVar; iVar++) + delete [] Precon[iVar]; + delete [] Precon; + + if (Jacobian_i != nullptr) { + for (iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Jacobian_i; + delete [] Jacobian_j; + } + +} + +CNumerics::ResidualType<> CCentJSTInc_Flow::ComputeResidual(const CConfig* config) { + + su2double U_i[5] = {0.0}, U_j[5] = {0.0}; + su2double ProjGridVel = 0.0; + + /*--- Primitive variables at point i and j ---*/ + + Pressure_i = V_i[0]; Pressure_j = V_j[0]; + Temperature_i = V_i[nDim+1]; Temperature_j = V_j[nDim+1]; + DensityInc_i = V_i[nDim+2]; DensityInc_j = V_j[nDim+2]; + BetaInc2_i = V_i[nDim+3]; BetaInc2_j = V_j[nDim+3]; + Cp_i = V_i[nDim+7]; Cp_j = V_j[nDim+7]; + Enthalpy_i = Cp_i*Temperature_i; Enthalpy_j = Cp_j*Temperature_j; + + Area = 0.0; + sq_vel_i = 0.0; sq_vel_j = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Velocity_j[iDim] = V_j[iDim+1]; + MeanVelocity[iDim] = 0.5*(Velocity_i[iDim]+Velocity_j[iDim]); + sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; + sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; + ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; + Area += Normal[iDim]*Normal[iDim]; + } + Area = sqrt(Area); + + /*--- Compute mean values of the variables ---*/ + + MeanDensity = 0.5*(DensityInc_i + DensityInc_j); + MeanPressure = 0.5*(Pressure_i + Pressure_j); + MeanBetaInc2 = 0.5*(BetaInc2_i + BetaInc2_j); + MeanEnthalpy = 0.5*(Enthalpy_i + Enthalpy_j); + MeanCp = 0.5*(Cp_i + Cp_j); + MeanTemperature = 0.5*(Temperature_i + Temperature_j); + + /*--- We need the derivative of the equation of state to build the + preconditioning matrix. For now, the only option is the ideal gas + law, but in the future, dRhodT should be in the fluid model. ---*/ + + MeandRhodT = 0.0; + if (variable_density) { + MeandRhodT = -MeanDensity/MeanTemperature; + } + + /*--- Get projected flux tensor ---*/ + + GetInviscidIncProjFlux(&MeanDensity, MeanVelocity, &MeanPressure, &MeanBetaInc2, &MeanEnthalpy, Normal, ProjFlux); + + /*--- Jacobians of the inviscid flux ---*/ + + if (implicit) { + GetInviscidIncProjJac(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Normal, 0.5, Jacobian_i); + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_j[iVar][jVar] = Jacobian_i[iVar][jVar]; + } + } + } + + /*--- Corrections due to grid motion ---*/ + if (dynamic_grid) { + + /*--- Recompute conservative variables ---*/ + + U_i[0] = DensityInc_i; U_j[0] = DensityInc_j; + for (iDim = 0; iDim < nDim; iDim++) { + U_i[iDim+1] = DensityInc_i*Velocity_i[iDim]; U_j[iDim+1] = DensityInc_j*Velocity_j[iDim]; + } + U_i[nDim+1] = DensityInc_i*Enthalpy_i; U_j[nDim+1] = DensityInc_j*Enthalpy_j; + + su2double ProjVelocity = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + + /*--- Residual contributions ---*/ + for (iVar = 0; iVar < nVar; iVar++) { + ProjFlux[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); + + /*--- Jacobian contributions ---*/ + /*--- Implicit terms ---*/ + if (implicit) { + for (iDim = 0; iDim < nDim; iDim++){ + Jacobian_i[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_i; + Jacobian_j[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_j; + } + Jacobian_i[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_i*Cp_i; + Jacobian_j[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_j*Cp_j; + } + } + } + + /*--- Computes differences between Laplacians and conservative variables ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Diff_Lapl[iVar] = Und_Lapl_i[iVar]-Und_Lapl_j[iVar]; + Diff_V[iVar] = V_i[iVar]-V_j[iVar]; + } + + /*--- Build the preconditioning matrix using mean values ---*/ + + GetPreconditioner(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Precon); + + /*--- Compute the local spectral radius of the preconditioned system + and the stretching factor. ---*/ + + /*--- Projected velocity adjustment due to mesh motion ---*/ + + if (dynamic_grid) { + ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + } + ProjVelocity_i -= ProjGridVel; + ProjVelocity_j -= ProjGridVel; + } + + SoundSpeed_i = sqrt(BetaInc2_i*Area*Area); + SoundSpeed_j = sqrt(BetaInc2_j*Area*Area); + + Local_Lambda_i = fabs(ProjVelocity_i)+SoundSpeed_i; + Local_Lambda_j = fabs(ProjVelocity_j)+SoundSpeed_j; + + MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); + + Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); + Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); + + StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); + + sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); + sc4 = sc2*sc2/4.0; + + Epsilon_2 = Param_Kappa_2*0.5*(Sensor_i+Sensor_j)*sc2; + Epsilon_4 = max(0.0, Param_Kappa_4-Epsilon_2)*sc4; + + /*--- Compute viscous part of the residual ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + ProjFlux[iVar] += Precon[iVar][jVar]*(Epsilon_2*Diff_V[jVar] - Epsilon_4*Diff_Lapl[jVar])*StretchingFactor*MeanLambda; + if (implicit) { + Jacobian_i[iVar][jVar] += Precon[iVar][jVar]*(Epsilon_2 + Epsilon_4*su2double(Neighbor_i+1))*StretchingFactor*MeanLambda; + Jacobian_j[iVar][jVar] -= Precon[iVar][jVar]*(Epsilon_2 + Epsilon_4*su2double(Neighbor_j+1))*StretchingFactor*MeanLambda; + } + } + } + + /*--- Remove energy contributions if not solving the energy equation. ---*/ + + if (!energy) { + ProjFlux[nDim+1] = 0.0; + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) { + Jacobian_i[iVar][nDim+1] = 0.0; + Jacobian_j[iVar][nDim+1] = 0.0; + + Jacobian_i[nDim+1][iVar] = 0.0; + Jacobian_j[nDim+1][iVar] = 0.0; + } + } + } + + return ResidualType<>(ProjFlux, Jacobian_i, Jacobian_j); + +} diff --git a/SU2_CFD/src/numerics/flow/convection/cusp.cpp b/SU2_CFD/src/numerics/flow/convection/cusp.cpp new file mode 100644 index 000000000000..b60bb7b83135 --- /dev/null +++ b/SU2_CFD/src/numerics/flow/convection/cusp.cpp @@ -0,0 +1,187 @@ +/*! + * \file cusp.cpp + * \brief Implementation of the CUSP scheme. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../../include/numerics/flow/convection/cusp.hpp" + +CUpwCUSP_Flow::CUpwCUSP_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + if (config->GetDynamic_Grid() && (SU2_MPI::GetRank() == MASTER_NODE)) + cout << "WARNING: Grid velocities are NOT yet considered by the CUSP scheme." << endl; + + /*--- Allocate some structures ---*/ + Flux = new su2double [nVar]; + ProjFlux_i = new su2double [nVar]; + ProjFlux_j = new su2double [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CUpwCUSP_Flow::~CUpwCUSP_Flow(void) { + delete [] Flux; + delete [] ProjFlux_i; + delete [] ProjFlux_j; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Jacobian_i; + delete [] Jacobian_j; +} + +CNumerics::ResidualType<> CUpwCUSP_Flow::ComputeResidual(const CConfig* config) { + + unsigned short iDim, iVar; + su2double Diff_U[5] = {0.0}; + + AD::SetPreaccIn(Normal, nDim); + AD::SetPreaccIn(V_i, nDim+4); + AD::SetPreaccIn(V_j, nDim+4); + + /*--- Pressure, density, enthalpy, energy, and velocity at points i and j ---*/ + + Pressure_i = V_i[nDim+1]; Pressure_j = V_j[nDim+1]; + Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; + Enthalpy_i = V_i[nDim+3]; Enthalpy_j = V_j[nDim+3]; + su2double Energy_i = Enthalpy_i - Pressure_i/Density_i; + su2double Energy_j = Enthalpy_j - Pressure_j/Density_j; + + su2double sq_vel_i = 0.0, sq_vel_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Velocity_j[iDim] = V_j[iDim+1]; + sq_vel_i += Velocity_i[iDim]*Velocity_i[iDim]; + sq_vel_j += Velocity_j[iDim]*Velocity_j[iDim]; + } + + /*-- Face area and unit normal ---*/ + + 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; + + /*--- Computes differences of conservative variables, with a correction for the enthalpy ---*/ + + Diff_U[0] = Density_i - Density_j; + for (iDim = 0; iDim < nDim; iDim++) + Diff_U[iDim+1] = Density_i*Velocity_i[iDim] - Density_j*Velocity_j[iDim]; + Diff_U[nVar-1] = Density_i*Enthalpy_i - Density_j*Enthalpy_j; + + /*--- Get left and right fluxes ---*/ + + GetInviscidProjFlux(&Density_i, Velocity_i, &Pressure_i, &Enthalpy_i, UnitNormal, ProjFlux_i); + GetInviscidProjFlux(&Density_j, Velocity_j, &Pressure_j, &Enthalpy_j, UnitNormal, ProjFlux_j); + + /*--- Compute dissipation parameters based on Roe-averaged values ---*/ + + su2double Beta, Nu_c; + + su2double R = sqrt(Density_j/Density_i), ProjVelocity = 0.0, sq_vel = 0.0; + + for (iDim = 0; iDim < nDim; iDim++) { + su2double MeanVel = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1.0); + ProjVelocity += MeanVel*UnitNormal[iDim]; + sq_vel += MeanVel*MeanVel; + } + su2double MeanEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1.0); + su2double MeanSoundSpeed = sqrt(Gamma_Minus_One*fabs(MeanEnthalpy-0.5*sq_vel)); + + su2double Mach = ProjVelocity / MeanSoundSpeed; + + su2double tmp1 = 0.5*(Gamma+1.0)/Gamma*ProjVelocity; + su2double tmp2 = sqrt(pow(tmp1-ProjVelocity/Gamma, 2.0) + pow(MeanSoundSpeed,2.0)/Gamma); + su2double LamdaNeg = tmp1 - tmp2, LamdaPos = tmp1 + tmp2; + + if (fabs(Mach) >= 1.0) Beta = Mach/fabs(Mach); + else if (Mach >= 0.0) Beta = max(0.0, (ProjVelocity + LamdaNeg)/(ProjVelocity - LamdaNeg)); + else Beta =-max(0.0, (ProjVelocity + LamdaPos)/(ProjVelocity - LamdaPos)); + + if (fabs(Mach) >= 1.0) Nu_c = 0.0; + else { + if (Beta > 0.0) Nu_c =-(1.0+Beta)*LamdaNeg; + else if (Beta < 0.0) Nu_c = (1.0-Beta)*LamdaPos; + /*--- Limit the minimum scalar dissipation ---*/ + else Nu_c = max(fabs(ProjVelocity), config->GetEntropyFix_Coeff()*MeanSoundSpeed); + } + + /*--- Compute the residual ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Flux[iVar] = 0.5*((1.0+Beta)*ProjFlux_i[iVar] + (1.0-Beta)*ProjFlux_j[iVar] + Nu_c*Diff_U[iVar])*Area; + + /*--- Jacobian computation ---*/ + + if (implicit) { + + /*--- Flux average and difference contributions ---*/ + + GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5*(1.0+Beta), Jacobian_i); + GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5*(1.0-Beta), Jacobian_j); + + /*--- Solution difference (scalar dissipation) contribution ---*/ + + su2double cte_0 = 0.5*Nu_c*Area*config->GetCent_Jac_Fix_Factor(); + + /*--- n-1 diagonal entries ---*/ + + for (iVar = 0; iVar < (nVar-1); iVar++) { + Jacobian_i[iVar][iVar] += cte_0; + Jacobian_j[iVar][iVar] -= cte_0; + } + + /*--- Last rows ---*/ + + Jacobian_i[nVar-1][0] += cte_0*Gamma_Minus_One*0.5*sq_vel_i; + for (iDim = 0; iDim < nDim; iDim++) + Jacobian_i[nVar-1][iDim+1] -= cte_0*Gamma_Minus_One*Velocity_i[iDim]; + Jacobian_i[nVar-1][nVar-1] += cte_0*Gamma; + + Jacobian_j[nVar-1][0] -= cte_0*Gamma_Minus_One*0.5*sq_vel_j; + for (iDim = 0; iDim < nDim; iDim++) + Jacobian_j[nVar-1][iDim+1] += cte_0*Gamma_Minus_One*Velocity_j[iDim]; + Jacobian_j[nVar-1][nVar-1] -= cte_0*Gamma; + + } + + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} diff --git a/SU2_CFD/src/numerics/flow/convection/fds.cpp b/SU2_CFD/src/numerics/flow/convection/fds.cpp new file mode 100644 index 000000000000..943e24530a02 --- /dev/null +++ b/SU2_CFD/src/numerics/flow/convection/fds.cpp @@ -0,0 +1,287 @@ +/*! + * \file fds.cpp + * \brief Implementation of Flux-Difference-Splitting schemes. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../../include/numerics/flow/convection/fds.hpp" + +CUpwFDSInc_Flow::CUpwFDSInc_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig *config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + variable_density = (config->GetKind_DensityModel() == VARIABLE); + energy = config->GetEnergy_Equation(); + /* 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(); + + Flux = new su2double[nVar]; + Diff_V = new su2double[nVar]; + Velocity_i = new su2double[nDim]; + Velocity_j = new su2double[nDim]; + MeanVelocity = new su2double[nDim]; + ProjFlux_i = new su2double[nVar]; + ProjFlux_j = new su2double[nVar]; + Lambda = new su2double[nVar]; + Epsilon = new su2double[nVar]; + Precon = new su2double*[nVar]; + invPrecon_A = new su2double*[nVar]; + Jacobian_i = new su2double*[nVar]; + Jacobian_j = new su2double*[nVar]; + for (iVar = 0; iVar < nVar; iVar++) { + Precon[iVar] = new su2double[nVar]; + invPrecon_A[iVar] = new su2double[nVar]; + Jacobian_i[iVar] = new su2double[nVar]; + Jacobian_j[iVar] = new su2double[nVar]; + } + +} + +CUpwFDSInc_Flow::~CUpwFDSInc_Flow(void) { + + delete [] Flux; + delete [] Diff_V; + delete [] Velocity_i; + delete [] Velocity_j; + delete [] MeanVelocity; + delete [] ProjFlux_i; + delete [] ProjFlux_j; + delete [] Lambda; + delete [] Epsilon; + + for (iVar = 0; iVar < nVar; iVar++) { + delete [] Precon[iVar]; + delete [] invPrecon_A[iVar]; + } + delete [] Precon; + delete [] invPrecon_A; + + if (Jacobian_i != nullptr) { + for (iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Jacobian_i; + delete [] Jacobian_j; + } + +} + +CNumerics::ResidualType<> CUpwFDSInc_Flow::ComputeResidual(const CConfig *config) { + + su2double U_i[5] = {0.0,0.0,0.0,0.0,0.0}, U_j[5] = {0.0,0.0,0.0,0.0,0.0}; + su2double ProjGridVel = 0.0; + + AD::StartPreacc(); + AD::SetPreaccIn(V_i, nDim+9); AD::SetPreaccIn(V_j, nDim+9); AD::SetPreaccIn(Normal, nDim); + if (dynamic_grid) { + AD::SetPreaccIn(GridVel_i, nDim); + AD::SetPreaccIn(GridVel_j, nDim); + } + + /*--- Face area (norm or the normal vector) ---*/ + + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Area += Normal[iDim]*Normal[iDim]; + Area = sqrt(Area); + + /*--- Compute and unitary normal vector ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + UnitNormal[iDim] = Normal[iDim]/Area; + if (fabs(UnitNormal[iDim]) < EPS) UnitNormal[iDim] = EPS; + } + + /*--- Set primitive variables at points iPoint and jPoint ---*/ + + Pressure_i = V_i[0]; Pressure_j = V_j[0]; + Temperature_i = V_i[nDim+1]; Temperature_j = V_j[nDim+1]; + DensityInc_i = V_i[nDim+2]; DensityInc_j = V_j[nDim+2]; + BetaInc2_i = V_i[nDim+3]; BetaInc2_j = V_j[nDim+3]; + Cp_i = V_i[nDim+7]; Cp_j = V_j[nDim+7]; + Enthalpy_i = Cp_i*Temperature_i; Enthalpy_j = Cp_j*Temperature_j; + + ProjVelocity = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Velocity_j[iDim] = V_j[iDim+1]; + MeanVelocity[iDim] = 0.5*(Velocity_i[iDim] + Velocity_j[iDim]); + ProjVelocity += MeanVelocity[iDim]*Normal[iDim]; + } + + /*--- Projected velocity adjustment due to mesh motion ---*/ + + if (dynamic_grid) { + ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + } + ProjVelocity -= ProjGridVel; + } + + /*--- Mean variables at points iPoint and jPoint ---*/ + + MeanDensity = 0.5*(DensityInc_i + DensityInc_j); + MeanPressure = 0.5*(Pressure_i + Pressure_j); + MeanBetaInc2 = 0.5*(BetaInc2_i + BetaInc2_j); + MeanEnthalpy = 0.5*(Enthalpy_i + Enthalpy_j); + MeanCp = 0.5*(Cp_i + Cp_j); + MeanTemperature = 0.5*(Temperature_i + Temperature_j); + + /*--- Artificial sound speed based on eigs of preconditioned system ---*/ + + MeanSoundSpeed = sqrt(MeanBetaInc2*Area*Area); + + /*--- We need the derivative of the equation of state to build the + preconditioning matrix. For now, the only option is the ideal gas + law, but in the future, dRhodT should be in the fluid model. ---*/ + + MeandRhodT = 0.0; dRhodT_i = 0.0; dRhodT_j = 0.0; + if (variable_density) { + MeandRhodT = -MeanDensity/MeanTemperature; + dRhodT_i = -DensityInc_i/Temperature_i; + dRhodT_j = -DensityInc_j/Temperature_j; + } + + /*--- Compute ProjFlux_i ---*/ + + GetInviscidIncProjFlux(&DensityInc_i, Velocity_i, &Pressure_i, &BetaInc2_i, &Enthalpy_i, Normal, ProjFlux_i); + + /*--- Compute ProjFlux_j ---*/ + + GetInviscidIncProjFlux(&DensityInc_j, Velocity_j, &Pressure_j, &BetaInc2_j, &Enthalpy_j, Normal, ProjFlux_j); + + /*--- Eigenvalues of the preconditioned system ---*/ + + if (nDim == 2) { + Lambda[0] = ProjVelocity; + Lambda[1] = ProjVelocity; + Lambda[2] = ProjVelocity - MeanSoundSpeed; + Lambda[3] = ProjVelocity + MeanSoundSpeed; + } + if (nDim == 3) { + Lambda[0] = ProjVelocity; + Lambda[1] = ProjVelocity; + Lambda[2] = ProjVelocity; + Lambda[3] = ProjVelocity - MeanSoundSpeed; + Lambda[4] = ProjVelocity + MeanSoundSpeed; + } + + /*--- Absolute value of the eigenvalues ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Lambda[iVar] = fabs(Lambda[iVar]); + + /*--- Build the preconditioning matrix using mean values ---*/ + + GetPreconditioner(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Precon); + + /*--- Build the absolute value of the preconditioned Jacobian, i.e., + |A_precon| = P x |Lambda| x inv(P), where P diagonalizes the matrix + inv(Precon) x dF/dV and Lambda is the diag. matrix of its eigenvalues. ---*/ + + GetPreconditionedProjJac(&MeanDensity, Lambda, &MeanBetaInc2, UnitNormal, invPrecon_A); + + /*--- Difference of primitive variables at iPoint and jPoint ---*/ + + Diff_V[0] = Pressure_j - Pressure_i; + for (iDim = 0; iDim < nDim; iDim++) + Diff_V[iDim+1] = Velocity_j[iDim] - Velocity_i[iDim]; + Diff_V[nDim+1] = Temperature_j - Temperature_i; + + /*--- Build the inviscid Jacobian w.r.t. the primitive variables ---*/ + + if (implicit) { + GetInviscidIncProjJac(&DensityInc_i, Velocity_i, &BetaInc2_i, &Cp_i, &Temperature_i, &dRhodT_i, Normal, 0.5, Jacobian_i); + GetInviscidIncProjJac(&DensityInc_j, Velocity_j, &BetaInc2_j, &Cp_j, &Temperature_j, &dRhodT_j, Normal, 0.5, Jacobian_j); + } + + /*--- Compute dissipation as Precon x |A_precon| x dV. If implicit, + store Precon x |A_precon| from dissipation term. ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] = 0.5*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); + for (jVar = 0; jVar < nVar; jVar++) { + Proj_ModJac_Tensor_ij = 0.0; + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_ij += Precon[iVar][kVar]*invPrecon_A[kVar][jVar]; + Flux[iVar] -= 0.5*Proj_ModJac_Tensor_ij*Diff_V[jVar]; + if (implicit) { + Jacobian_i[iVar][jVar] += 0.5*Proj_ModJac_Tensor_ij; + Jacobian_j[iVar][jVar] -= 0.5*Proj_ModJac_Tensor_ij; + } + } + } + + /*--- Corrections due to grid motion ---*/ + if (dynamic_grid) { + + /*--- Recompute conservative variables ---*/ + + U_i[0] = DensityInc_i; U_j[0] = DensityInc_j; + for (iDim = 0; iDim < nDim; iDim++) { + U_i[iDim+1] = DensityInc_i*Velocity_i[iDim]; U_j[iDim+1] = DensityInc_j*Velocity_j[iDim]; + } + U_i[nDim+1] = DensityInc_i*Enthalpy_i; U_j[nDim+1] = DensityInc_j*Enthalpy_j; + + ProjVelocity = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + + /*--- Residual contributions ---*/ + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); + + /*--- Jacobian contributions ---*/ + /*--- Implicit terms ---*/ + if (implicit) { + for (iDim = 0; iDim < nDim; iDim++){ + Jacobian_i[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_i; + Jacobian_j[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_j; + } + Jacobian_i[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_i*Cp_i; + Jacobian_j[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_j*Cp_j; + } + } + } + + if (!energy) { + Flux[nDim+1] = 0.0; + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) { + Jacobian_i[iVar][nDim+1] = 0.0; + Jacobian_j[iVar][nDim+1] = 0.0; + + Jacobian_i[nDim+1][iVar] = 0.0; + Jacobian_j[nDim+1][iVar] = 0.0; + } + } + } + + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} diff --git a/SU2_CFD/src/numerics/flow/convection/fvs.cpp b/SU2_CFD/src/numerics/flow/convection/fvs.cpp new file mode 100644 index 000000000000..3fcf5c363f2f --- /dev/null +++ b/SU2_CFD/src/numerics/flow/convection/fvs.cpp @@ -0,0 +1,250 @@ +/*! + * \file fvs.cpp + * \brief Implementations of Flux-Vector-Splitting schemes. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../../include/numerics/flow/convection/fvs.hpp" + +CUpwMSW_Flow::CUpwMSW_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : CNumerics(val_nDim, val_nVar, config) { + + if (config->GetDynamic_Grid() && (SU2_MPI::GetRank() == MASTER_NODE)) + cout << "WARNING: Grid velocities are NOT yet considered in the MSW scheme." << endl; + + /*--- Set booleans from CConfig settings ---*/ + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + + /*--- Allocate arrays ---*/ + Diff_U = new su2double [nVar]; + Fc_i = new su2double [nVar]; + Fc_j = new su2double [nVar]; + Lambda_i = new su2double [nVar]; + Lambda_j = new su2double [nVar]; + + u_i = new su2double [nDim]; + u_j = new su2double [nDim]; + ust_i = new su2double [nDim]; + ust_j = new su2double [nDim]; + Vst_i = new su2double [nPrimVar]; + Vst_j = new su2double [nPrimVar]; + Ust_i = new su2double [nVar]; + Ust_j = new su2double [nVar]; + + Velst_i = new su2double [nDim]; + Velst_j = new su2double [nDim]; + + P_Tensor = new su2double* [nVar]; + invP_Tensor= new su2double* [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + P_Tensor[iVar] = new su2double [nVar]; + invP_Tensor[iVar] = new su2double [nVar]; + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } + +} + +CUpwMSW_Flow::~CUpwMSW_Flow(void) { + + delete [] Diff_U; + delete [] Fc_i; + delete [] Fc_j; + delete [] Lambda_i; + delete [] Lambda_j; + + delete [] u_i; + delete [] u_j; + delete [] ust_i; + delete [] ust_j; + delete [] Ust_i; + delete [] Vst_i; + delete [] Ust_j; + delete [] Vst_j; + delete [] Velst_i; + delete [] Velst_j; + + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] P_Tensor[iVar]; + delete [] invP_Tensor[iVar]; + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] P_Tensor; + delete [] invP_Tensor; + delete [] Jacobian_i; + delete [] Jacobian_j; + +} + +CNumerics::ResidualType<> CUpwMSW_Flow::ComputeResidual(const CConfig* config) { + + unsigned short iDim, iVar, jVar, kVar; + su2double P_i, P_j; + su2double ProjVel_i, ProjVel_j, ProjVelst_i, ProjVelst_j; + su2double sqvel_i, sqvel_j; + su2double alpha, w, dp, onemw; + su2double Proj_ModJac_Tensor_i, Proj_ModJac_Tensor_j; + + /*--- Set parameters in the numerical method ---*/ + alpha = 6.0; + + /*--- Calculate supporting geometry parameters ---*/ + + Area = 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; + + /*--- Initialize flux & Jacobian vectors ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Fc_i[iVar] = 0.0; + Fc_j[iVar] = 0.0; + } + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_i[iVar][jVar] = 0.0; + Jacobian_j[iVar][jVar] = 0.0; + } + } + } + + /*--- Load variables from nodes i & j ---*/ + + rhos_i = V_i[0]; + rhos_j = V_j[0]; + for (iDim = 0; iDim < nDim; iDim++) { + u_i[iDim] = V_i[iDim+1]; + u_j[iDim] = V_j[iDim+1]; + } + P_i = V_i[nDim+1]; + P_j = V_j[nDim+1]; + + /*--- Calculate supporting quantities ---*/ + + sqvel_i = 0.0; sqvel_j = 0.0; + ProjVel_i = 0.0; ProjVel_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + sqvel_i += u_i[iDim]*u_i[iDim]; + sqvel_j += u_j[iDim]*u_j[iDim]; + ProjVel_i += u_i[iDim]*UnitNormal[iDim]; + ProjVel_j += u_j[iDim]*UnitNormal[iDim]; + } + + /*--- Calculate the state weighting function ---*/ + + dp = fabs(P_j-P_i) / min(P_j, P_i); + w = 0.5 * (1.0/(pow(alpha*dp,2.0) +1.0)); + onemw = 1.0 - w; + + /*--- Calculate weighted state vector (*) for i & j ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Ust_i[iVar] = onemw*U_i[iVar] + w*U_j[iVar]; + Ust_j[iVar] = onemw*U_j[iVar] + w*U_i[iVar]; + } + for (iVar = 0; iVar < nDim+5; iVar++) { + Vst_i[iVar] = onemw*V_i[iVar] + w*V_j[iVar]; + Vst_j[iVar] = onemw*V_j[iVar] + w*V_i[iVar]; + } + ProjVelst_i = onemw*ProjVel_i + w*ProjVel_j; + ProjVelst_j = onemw*ProjVel_j + w*ProjVel_i; + + for (iDim = 0; iDim < nDim; iDim++) { + Velst_i[iDim] = Vst_i[iDim+1]; + Velst_j[iDim] = Vst_j[iDim+1]; + } + + /*--- Flow eigenvalues at i (Lambda+) ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + Lambda_i[iDim] = 0.5*(ProjVelst_i + fabs(ProjVelst_i)); + } + + Lambda_i[nDim] = 0.5*( ProjVelst_i + Vst_i[nDim+4] + fabs(ProjVelst_i + Vst_i[nDim+4]) ); + Lambda_i[nDim+1] = 0.5*( ProjVelst_i - Vst_i[nDim+4] + fabs(ProjVelst_i - Vst_i[nDim+4]) ); + + /*--- Compute projected P, invP, and Lambda ---*/ + + GetPMatrix(&Vst_i[nDim+2], Velst_i, &Vst_i[nDim+4], UnitNormal, P_Tensor); + GetPMatrix_inv(&Vst_i[nDim+2], Velst_i, &Vst_i[nDim+4], UnitNormal, invP_Tensor); + + /*--- Projected flux (f+) at i ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Proj_ModJac_Tensor_i = 0.0; + + /*--- Compute Proj_ModJac_Tensor = P x Lambda+ x inverse P ---*/ + + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_i += P_Tensor[iVar][kVar]*Lambda_i[kVar]*invP_Tensor[kVar][jVar]; + Fc_i[iVar] += Proj_ModJac_Tensor_i*U_i[jVar]*Area; + if (implicit) + Jacobian_i[iVar][jVar] += Proj_ModJac_Tensor_i*Area; + } + } + + /*--- Flow eigenvalues at j (Lambda-) ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + Lambda_j[iDim] = 0.5*(ProjVelst_j - fabs(ProjVelst_j)); + } + Lambda_j[nDim] = 0.5*( ProjVelst_j + Vst_j[nDim+4] - fabs(ProjVelst_j + Vst_j[nDim+4]) ); + Lambda_j[nDim+1] = 0.5*( ProjVelst_j - Vst_j[nDim+4] - fabs(ProjVelst_j - Vst_j[nDim+4]) ); + + /*--- Compute projected P, invP, and Lambda ---*/ + + GetPMatrix(&Vst_j[nDim+2], Velst_j, &Vst_j[nDim+4], UnitNormal, P_Tensor); + GetPMatrix_inv(&Vst_j[nDim+2], Velst_j, &Vst_j[nDim+4], UnitNormal, invP_Tensor); + + /*--- Projected flux (f-) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Proj_ModJac_Tensor_j = 0.0; + /*--- Compute Proj_ModJac_Tensor = P x Lambda- x inverse P ---*/ + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_j += P_Tensor[iVar][kVar]*Lambda_j[kVar]*invP_Tensor[kVar][jVar]; + Fc_j[iVar] += Proj_ModJac_Tensor_j*U_j[jVar]*Area; + if (implicit) + Jacobian_j[iVar][jVar] += Proj_ModJac_Tensor_j*Area; + } + } + + /*--- Flux splitting, use the i flux as final output. ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + Fc_i[iVar] += Fc_j[iVar]; + } + + return ResidualType<>(Fc_i, Jacobian_i, Jacobian_j); + +} diff --git a/SU2_CFD/src/numerics/flow/convection/hllc.cpp b/SU2_CFD/src/numerics/flow/convection/hllc.cpp new file mode 100644 index 000000000000..c50d8d178ed5 --- /dev/null +++ b/SU2_CFD/src/numerics/flow/convection/hllc.cpp @@ -0,0 +1,1136 @@ +/*! + * \file hllc.cpp + * \brief Implementations of HLLC schemes. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../../include/numerics/flow/convection/hllc.hpp" + +CUpwHLLC_Flow::CUpwHLLC_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + kappa = config->GetRoe_Kappa(); + /* 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(); + + Gamma = config->GetGamma(); + + Gamma_Minus_One = Gamma - 1.0; + + IntermediateState = new su2double [nVar]; + dSm_dU = new su2double [nVar]; + dPI_dU = new su2double [nVar]; + drhoStar_dU = new su2double [nVar]; + dpStar_dU = new su2double [nVar]; + dEStar_dU = new su2double [nVar]; + + Velocity_i = new su2double [nDim]; + Velocity_j = new su2double [nDim]; + RoeVelocity = new su2double [nDim]; + + Flux = new su2double [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CUpwHLLC_Flow::~CUpwHLLC_Flow(void) { + + delete [] IntermediateState; + delete [] dSm_dU; + delete [] dPI_dU; + delete [] drhoStar_dU; + delete [] dpStar_dU; + delete [] dEStar_dU; + + delete [] Velocity_i; + delete [] Velocity_j; + delete [] RoeVelocity; + + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Flux; + delete [] Jacobian_i; + delete [] Jacobian_j; + +} + +CNumerics::ResidualType<> CUpwHLLC_Flow::ComputeResidual(const CConfig* config) { + + /*--- Face area (norm or the normal vector) ---*/ + + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Area += Normal[iDim] * Normal[iDim]; + + Area = sqrt(Area); + + /*-- Unit Normal ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + UnitNormal[iDim] = Normal[iDim] / Area; + + /*-- Fluid velocity at node i,j ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Velocity_j[iDim] = V_j[iDim+1]; + } + + /*--- Primitive variables at point i ---*/ + + Pressure_i = V_i[nDim+1]; + Density_i = V_i[nDim+2]; + Enthalpy_i = V_i[nDim+3]; + + /*--- Primitive variables at point j ---*/ + + Pressure_j = V_j[nDim+1]; + Density_j = V_j[nDim+2]; + Enthalpy_j = V_j[nDim+3]; + + + sq_vel_i = 0.0; + sq_vel_j = 0.0; + + for (iDim = 0; iDim < nDim; iDim++) { + sq_vel_i += Velocity_i[iDim] * Velocity_i[iDim]; + sq_vel_j += Velocity_j[iDim] * Velocity_j[iDim]; + } + + Energy_i = Enthalpy_i - Pressure_i / Density_i; + Energy_j = Enthalpy_j - Pressure_j / Density_j; + + SoundSpeed_i = sqrt( (Enthalpy_i - 0.5 * sq_vel_i) * Gamma_Minus_One ); + SoundSpeed_j = sqrt( (Enthalpy_j - 0.5 * sq_vel_j) * Gamma_Minus_One ); + + /*--- Projected velocities ---*/ + + ProjVelocity_i = 0; + ProjVelocity_j = 0; + + for (iDim = 0; iDim < nDim; iDim++) { + ProjVelocity_i += Velocity_i[iDim] * UnitNormal[iDim]; + ProjVelocity_j += Velocity_j[iDim] * UnitNormal[iDim]; + } + + /*--- Projected Grid Velocity ---*/ + + ProjInterfaceVel = 0; + + if (dynamic_grid) { + + for (iDim = 0; iDim < nDim; iDim++) + ProjInterfaceVel += 0.5 * ( GridVel_i[iDim] + GridVel_j[iDim] )*UnitNormal[iDim]; + + SoundSpeed_i -= ProjInterfaceVel; + SoundSpeed_j += ProjInterfaceVel; + + ProjVelocity_i -= ProjInterfaceVel; + ProjVelocity_j -= ProjInterfaceVel; + } + + /*--- Roe's averaging ---*/ + + Rrho = ( sqrt(Density_i) + sqrt(Density_j) ); + + sq_velRoe = 0.0; + RoeProjVelocity = - ProjInterfaceVel; + + for (iDim = 0; iDim < nDim; iDim++) { + RoeVelocity[iDim] = ( Velocity_i[iDim] * sqrt(Density_i) + Velocity_j[iDim] * sqrt(Density_j) ) / Rrho; + sq_velRoe += RoeVelocity[iDim] * RoeVelocity[iDim]; + RoeProjVelocity += RoeVelocity[iDim] * UnitNormal[iDim]; + } + + /*--- Mean Roe variables iPoint and jPoint ---*/ + + RoeDensity = sqrt( Density_i * Density_j ); + RoeEnthalpy = ( sqrt(Density_j) * Enthalpy_j + sqrt(Density_i) * Enthalpy_i) / Rrho; + + /*--- Roe-averaged speed of sound ---*/ + + //RoeSoundSpeed2 = Gamma_Minus_One * ( RoeEnthalpy - 0.5 * sq_velRoe ); + RoeSoundSpeed = sqrt( Gamma_Minus_One * ( RoeEnthalpy - 0.5 * sq_velRoe ) ) - ProjInterfaceVel; + + + /*--- Speed of sound at L and R ---*/ + + sL = min( RoeProjVelocity - RoeSoundSpeed, ProjVelocity_i - SoundSpeed_i); + sR = max( RoeProjVelocity + RoeSoundSpeed, ProjVelocity_j + SoundSpeed_j); + + /*--- speed of contact surface ---*/ + + RHO = Density_j * (sR - ProjVelocity_j) - Density_i * (sL - ProjVelocity_i); + sM = ( Pressure_i - Pressure_j - Density_i * ProjVelocity_i * ( sL - ProjVelocity_i ) + Density_j * ProjVelocity_j * ( sR - ProjVelocity_j ) ) / RHO; + + /*--- Pressure at right and left (Pressure_j=Pressure_i) side of contact surface ---*/ + + pStar = Density_j * ( ProjVelocity_j - sR ) * ( ProjVelocity_j - sM ) + Pressure_j; + + + if (sM > 0.0) { + + if (sL > 0.0) { + + /*--- Compute Left Flux ---*/ + + Flux[0] = Density_i * ProjVelocity_i; + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = Density_i * Velocity_i[iDim] * ProjVelocity_i + Pressure_i * UnitNormal[iDim]; + Flux[nVar-1] = Enthalpy_i * Density_i * ProjVelocity_i; + + } + else { + + /*--- Compute Flux Left Star from Left Star State ---*/ + + rhoSL = ( sL - ProjVelocity_i ) / ( sL - sM ); + + IntermediateState[0] = rhoSL * Density_i; + for (iDim = 0; iDim < nDim; iDim++) + IntermediateState[iDim+1] = rhoSL * ( Density_i * Velocity_i[iDim] + ( pStar - Pressure_i ) / ( sL - ProjVelocity_i ) * UnitNormal[iDim] ) ; + IntermediateState[nVar-1] = rhoSL * ( Density_i * Energy_i - ( Pressure_i * ProjVelocity_i - pStar * sM) / ( sL - ProjVelocity_i ) ); + + + Flux[0] = sM * IntermediateState[0]; + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = sM * IntermediateState[iDim+1] + pStar * UnitNormal[iDim]; + Flux[nVar-1] = sM * ( IntermediateState[nVar-1] + pStar ) + pStar * ProjInterfaceVel; + } + } + else { + + if (sR < 0.0) { + + /*--- Compute Right Flux ---*/ + + Flux[0] = Density_j * ProjVelocity_j; + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = Density_j * Velocity_j[iDim] * ProjVelocity_j + Pressure_j * UnitNormal[iDim]; + Flux[nVar-1] = Enthalpy_j * Density_j * ProjVelocity_j; + } + else { + + /*--- Compute Flux Right Star from Right Star State ---*/ + + rhoSR = ( sR - ProjVelocity_j ) / ( sR - sM ); + + IntermediateState[0] = rhoSR * Density_j; + for (iDim = 0; iDim < nDim; iDim++) + IntermediateState[iDim+1] = rhoSR * ( Density_j * Velocity_j[iDim] + ( pStar - Pressure_j ) / ( sR - ProjVelocity_j ) * UnitNormal[iDim] ) ; + IntermediateState[nVar-1] = rhoSR * ( Density_j * Energy_j - ( Pressure_j * ProjVelocity_j - pStar * sM ) / ( sR - ProjVelocity_j ) ); + + + Flux[0] = sM * IntermediateState[0]; + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = sM * IntermediateState[iDim+1] + pStar * UnitNormal[iDim]; + Flux[nVar-1] = sM * (IntermediateState[nVar-1] + pStar ) + pStar * ProjInterfaceVel; + } + } + + + for (iVar = 0; iVar < nVar; iVar++) + Flux[iVar] *= Area; + + /*--- Return early if the Jacobians do not need to be computed. ---*/ + + if (implicit) + { + if (sM > 0.0) { + + if (sL > 0.0) { + + /*--- Compute Jacobian based on Left State ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + Jacobian_j[iVar][jVar] = 0; + + GetInviscidProjJac(Velocity_i, &Energy_i, UnitNormal, 1.0, Jacobian_i); + + } + else { + /*--- Compute Jacobian based on Left Star State ---*/ + + EStar = IntermediateState[nVar-1]; + Omega = 1/(sL-sM); + OmegaSM = Omega * sM; + + + /*--------- Left Jacobian ---------*/ + + + /*--- Computing pressure derivatives d/dU_L (PI) ---*/ + + dPI_dU[0] = 0.5 * Gamma_Minus_One * sq_vel_i; + for (iDim = 0; iDim < nDim; iDim++) + dPI_dU[iDim+1] = - Gamma_Minus_One * Velocity_i[iDim]; + dPI_dU[nVar-1] = Gamma_Minus_One; + + + /*--- Computing d/dU_L (Sm) ---*/ + + dSm_dU[0] = ( - ProjVelocity_i * ProjVelocity_i + sM * sL + dPI_dU[0] ) / RHO; + for (iDim = 0; iDim < nDim; iDim++) + dSm_dU[iDim+1] = ( UnitNormal[iDim] * ( 2 * ProjVelocity_i - sL - sM ) + dPI_dU[iDim+1] ) / RHO; + dSm_dU[nVar-1] = dPI_dU[nVar-1] / RHO; + + + /*--- Computing d/dU_L (rhoStar) ---*/ + + drhoStar_dU[0] = Omega * ( sL + IntermediateState[0] * dSm_dU[0] ); + for (iDim = 0; iDim < nDim; iDim++) + drhoStar_dU[iDim+1] = Omega * ( - UnitNormal[iDim] + IntermediateState[0] * dSm_dU[iDim+1] ); + drhoStar_dU[nVar-1] = Omega * IntermediateState[0] * dSm_dU[nVar-1]; + + + /*--- Computing d/dU_L (pStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dpStar_dU[iVar] = Density_i * (sR - ProjVelocity_j) * dSm_dU[iVar]; + + + /*--- Computing d/dU_L (EStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); + + dEStar_dU[0] += Omega * ProjVelocity_i * ( Enthalpy_i - dPI_dU[0] ); + for (iDim = 0; iDim < nDim; iDim++) + dEStar_dU[iDim+1] += Omega * ( - UnitNormal[iDim] * Enthalpy_i - ProjVelocity_i * dPI_dU[iDim+1] ); + dEStar_dU[nVar-1] += Omega * ( sL - ProjVelocity_i - ProjVelocity_i * dPI_dU[nVar-1] ); + + + + /*--- Jacobian First Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[0][iVar] = sM * drhoStar_dU[iVar] + IntermediateState[0] * dSm_dU[iVar]; + + /*--- Jacobian Middle Rows ---*/ + + for (jDim = 0; jDim < nDim; jDim++) { + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[jDim+1][iVar] = ( OmegaSM + 1 ) * ( UnitNormal[jDim] * dpStar_dU[iVar] + IntermediateState[jDim+1] * dSm_dU[iVar] ); + + Jacobian_i[jDim+1][0] += OmegaSM * Velocity_i[jDim] * ProjVelocity_i; + + Jacobian_i[jDim+1][jDim+1] += OmegaSM * (sL - ProjVelocity_i); + + for (iDim = 0; iDim < nDim; iDim++) + Jacobian_i[jDim+1][iDim+1] -= OmegaSM * Velocity_i[jDim] * UnitNormal[iDim]; + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[jDim+1][iVar] -= OmegaSM * dPI_dU[iVar] * UnitNormal[jDim]; + } + + /*--- Jacobian Last Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[nVar-1][iVar] = sM * ( dEStar_dU[iVar] + dpStar_dU[iVar] ) + ( EStar + pStar ) * dSm_dU[iVar]; + + + /*--------- Right Jacobian ---------*/ + + + /*--- Computing d/dU_R (Sm) ---*/ + + dSm_dU[0] = ( ProjVelocity_j * ProjVelocity_j - sM * sR - 0.5 * Gamma_Minus_One * sq_vel_j ) / RHO; + for (iDim = 0; iDim < nDim; iDim++) + dSm_dU[iDim+1] = - ( UnitNormal[iDim] * ( 2 * ProjVelocity_j - sR - sM) - Gamma_Minus_One * Velocity_j[iDim] ) / RHO; + dSm_dU[nVar-1] = - Gamma_Minus_One / RHO; + + + /*--- Computing d/dU_R (pStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dpStar_dU[iVar] = Density_j * (sL - ProjVelocity_i) * dSm_dU[iVar]; + + + /*--- Computing d/dU_R (EStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); + + + + /*--- Jacobian First Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[0][iVar] = IntermediateState[0] * ( OmegaSM + 1 ) * dSm_dU[iVar]; + + /*--- Jacobian Middle Rows ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[iDim+1][iVar] = ( OmegaSM + 1 ) * ( IntermediateState[iDim+1] * dSm_dU[iVar] + UnitNormal[iDim] * dpStar_dU[iVar] ); + } + + /*--- Jacobian Last Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[nVar-1][iVar] = sM * (dEStar_dU[iVar] + dpStar_dU[iVar]) + (EStar + pStar) * dSm_dU[iVar]; + } + } + else { + if (sR < 0.0) { + + /*--- Compute Jacobian based on Right State ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + Jacobian_i[iVar][jVar] = 0; + + GetInviscidProjJac(Velocity_j, &Energy_j, UnitNormal, 1.0, Jacobian_j); + + } + else { + /*--- Compute Jacobian based on Right Star State ---*/ + + EStar = IntermediateState[nVar-1]; + Omega = 1/(sR-sM); + OmegaSM = Omega * sM; + + + /*--------- Left Jacobian ---------*/ + + + /*--- Computing d/dU_L (Sm) ---*/ + + dSm_dU[0] = ( - ProjVelocity_i * ProjVelocity_i + sM * sL + 0.5 * Gamma_Minus_One * sq_vel_i ) / RHO; + for (iDim = 0; iDim < nDim; iDim++) + dSm_dU[iDim+1] = ( UnitNormal[iDim] * ( 2 * ProjVelocity_i - sL - sM ) - Gamma_Minus_One * Velocity_i[iDim] ) / RHO; + dSm_dU[nVar-1] = Gamma_Minus_One / RHO; + + + /*--- Computing d/dU_L (pStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dpStar_dU[iVar] = Density_i * (sR - ProjVelocity_j) * dSm_dU[iVar]; + + + /*--- Computing d/dU_L (EStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); + + + + /*--- Jacobian First Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[0][iVar] = IntermediateState[0] * ( OmegaSM + 1 ) * dSm_dU[iVar]; + + /*--- Jacobian Middle Rows ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[iDim+1][iVar] = (OmegaSM + 1) * ( IntermediateState[iDim+1] * dSm_dU[iVar] + UnitNormal[iDim] * dpStar_dU[iVar] ); + } + + /*--- Jacobian Last Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[nVar-1][iVar] = sM * (dEStar_dU[iVar] + dpStar_dU[iVar]) + (EStar + pStar) * dSm_dU[iVar]; + + + + /*--------- Right Jacobian ---------*/ + + + /*--- Computing pressure derivatives d/dU_R (PI) ---*/ + + dPI_dU[0] = 0.5 * Gamma_Minus_One * sq_vel_j; + for (iDim = 0; iDim < nDim; iDim++) + dPI_dU[iDim+1] = - Gamma_Minus_One * Velocity_j[iDim]; + dPI_dU[nVar-1] = Gamma_Minus_One; + + + + /*--- Computing d/dU_R (Sm) ---*/ + + dSm_dU[0] = - ( - ProjVelocity_j * ProjVelocity_j + sM * sR + dPI_dU[0] ) / RHO; + for (iDim = 0; iDim < nDim; iDim++) + dSm_dU[iDim+1] = - ( UnitNormal[iDim] * ( 2 * ProjVelocity_j - sR - sM) + dPI_dU[iDim+1] ) / RHO; + dSm_dU[nVar-1] = - dPI_dU[nVar-1] / RHO; + + + /*--- Computing d/dU_R (pStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dpStar_dU[iVar] = Density_j * (sL - ProjVelocity_i) * dSm_dU[iVar]; + + + /*--- Computing d/dU_R (rhoStar) ---*/ + + drhoStar_dU[0] = Omega * ( sR + IntermediateState[0] * dSm_dU[0] ); + for (iDim = 0; iDim < nDim; iDim++) + drhoStar_dU[iDim+1] = Omega * ( - UnitNormal[iDim] + IntermediateState[0] * dSm_dU[iDim+1] ); + drhoStar_dU[nVar-1] = Omega * IntermediateState[0] * dSm_dU[nVar-1]; + + + /*--- Computing d/dU_R (EStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); + + dEStar_dU[0] += Omega * ProjVelocity_j * ( Enthalpy_j - dPI_dU[0] ); + for (iDim = 0; iDim < nDim; iDim++) + dEStar_dU[iDim+1] += Omega * ( - UnitNormal[iDim] * Enthalpy_j - ProjVelocity_j * dPI_dU[iDim+1] ); + dEStar_dU[nVar-1] += Omega * ( sR - ProjVelocity_j - ProjVelocity_j * dPI_dU[nVar-1] ); + + + + /*--- Jacobian First Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[0][iVar] = sM * drhoStar_dU[iVar] + IntermediateState[0] * dSm_dU[iVar]; + + /*--- Jacobian Middle Rows ---*/ + + for (jDim = 0; jDim < nDim; jDim++) { + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[jDim+1][iVar] = ( OmegaSM + 1 ) * ( UnitNormal[jDim] * dpStar_dU[iVar] + IntermediateState[jDim+1] * dSm_dU[iVar] ); + + Jacobian_j[jDim+1][0] += OmegaSM * Velocity_j[jDim] * ProjVelocity_j; + + Jacobian_j[jDim+1][jDim+1] += OmegaSM * (sR - ProjVelocity_j); + + for (iDim = 0; iDim < nDim; iDim++) + Jacobian_j[jDim+1][iDim+1] -= OmegaSM * Velocity_j[jDim] * UnitNormal[iDim]; + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[jDim+1][iVar] -= OmegaSM * dPI_dU[iVar] * UnitNormal[jDim]; + } + + /*--- Jacobian Last Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[nVar-1][iVar] = sM * ( dEStar_dU[iVar] + dpStar_dU[iVar] ) + ( EStar + pStar ) * dSm_dU[iVar]; + + } + } + + + /*--- Jacobians of the inviscid flux, scale = k because Flux ~ 0.5*(fc_i+fc_j)*Normal ---*/ + + Area *= kappa; + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_i[iVar][jVar] *= Area; + Jacobian_j[iVar][jVar] *= Area; + } + } + } // end if implicit + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} + +CUpwGeneralHLLC_Flow::CUpwGeneralHLLC_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + kappa = config->GetRoe_Kappa(); + /* 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(); + + Gamma = config->GetGamma(); + + IntermediateState = new su2double [nVar]; + dSm_dU = new su2double [nVar]; + dPI_dU = new su2double [nVar]; + drhoStar_dU = new su2double [nVar]; + dpStar_dU = new su2double [nVar]; + dEStar_dU = new su2double [nVar]; + + Velocity_i = new su2double [nDim]; + Velocity_j = new su2double [nDim]; + RoeVelocity = new su2double [nDim]; + + Flux = new su2double [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CUpwGeneralHLLC_Flow::~CUpwGeneralHLLC_Flow(void) { + + delete [] IntermediateState; + delete [] dSm_dU; + delete [] dPI_dU; + delete [] drhoStar_dU; + delete [] dpStar_dU; + delete [] dEStar_dU; + + delete [] Velocity_i; + delete [] Velocity_j; + delete [] RoeVelocity; + + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Flux; + delete [] Jacobian_i; + delete [] Jacobian_j; + +} + +CNumerics::ResidualType<> CUpwGeneralHLLC_Flow::ComputeResidual(const CConfig* config) { + + /*--- Face area (norm or the normal vector) ---*/ + + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Area += Normal[iDim] * Normal[iDim]; + + Area = sqrt(Area); + + /*-- Unit Normal ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + UnitNormal[iDim] = Normal[iDim] / Area; + + /*-- Fluid velocity at node i,j ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Velocity_j[iDim] = V_j[iDim+1]; + } + + /*--- Primitive variables at point i ---*/ + + Pressure_i = V_i[nDim+1]; + Density_i = V_i[nDim+2]; + Enthalpy_i = V_i[nDim+3]; + + /*--- Primitive variables at point j ---*/ + + Pressure_j = V_j[nDim+1]; + Density_j = V_j[nDim+2]; + Enthalpy_j = V_j[nDim+3]; + + + sq_vel_i = 0.0; + sq_vel_j = 0.0; + + for (iDim = 0; iDim < nDim; iDim++) { + sq_vel_i += Velocity_i[iDim] * Velocity_i[iDim]; + sq_vel_j += Velocity_j[iDim] * Velocity_j[iDim]; + } + + Energy_i = Enthalpy_i - Pressure_i / Density_i; + StaticEnthalpy_i = Enthalpy_i - 0.5 * sq_vel_i; + StaticEnergy_i = Energy_i - 0.5 * sq_vel_i; + + Kappa_i = S_i[1] / Density_i; + Chi_i = S_i[0] - Kappa_i * StaticEnergy_i; + SoundSpeed_i = sqrt(Chi_i + StaticEnthalpy_i * Kappa_i); + + + Energy_j = Enthalpy_j - Pressure_j / Density_j; + StaticEnthalpy_j = Enthalpy_j - 0.5 * sq_vel_j; + StaticEnergy_j = Energy_j - 0.5 * sq_vel_j; + + Kappa_j = S_j[1] / Density_j; + Chi_j = S_j[0] - Kappa_j * StaticEnergy_j; + SoundSpeed_j = sqrt(Chi_j + StaticEnthalpy_j * Kappa_j); + + /*--- Projected velocities ---*/ + + ProjVelocity_i = 0.0; + ProjVelocity_j = 0.0; + + for (iDim = 0; iDim < nDim; iDim++) { + ProjVelocity_i += Velocity_i[iDim] * UnitNormal[iDim]; + ProjVelocity_j += Velocity_j[iDim] * UnitNormal[iDim]; + } + + + /*--- Projected Grid Velocity ---*/ + + ProjInterfaceVel = 0; + + if (dynamic_grid) { + + for (iDim = 0; iDim < nDim; iDim++) + ProjInterfaceVel += 0.5 * ( GridVel_i[iDim] + GridVel_j[iDim] )*UnitNormal[iDim]; + + SoundSpeed_i -= ProjInterfaceVel; + SoundSpeed_j += ProjInterfaceVel; + + ProjVelocity_i -= ProjInterfaceVel; + ProjVelocity_j -= ProjInterfaceVel; + } + + /*--- Roe's averaging ---*/ + + Rrho = ( sqrt(Density_i) + sqrt(Density_j) ); + + sq_velRoe = 0.0; + RoeProjVelocity = - ProjInterfaceVel; + + for (iDim = 0; iDim < nDim; iDim++) { + RoeVelocity[iDim] = ( Velocity_i[iDim] * sqrt(Density_i) + Velocity_j[iDim] * sqrt(Density_j) ) / Rrho; + sq_velRoe += RoeVelocity[iDim] * RoeVelocity[iDim]; + RoeProjVelocity += RoeVelocity[iDim] * UnitNormal[iDim]; + } + + /*--- Mean Roe variables iPoint and jPoint ---*/ + + RoeKappa = 0.5 * ( Kappa_i + Kappa_j ); + RoeChi = 0.5 * ( Chi_i + Chi_j ); + RoeDensity = sqrt( Density_i * Density_j ); + RoeEnthalpy = ( sqrt(Density_j) * Enthalpy_j + sqrt(Density_i) * Enthalpy_i) / Rrho; + + VinokurMontagne(); + + /*--- Roe-averaged speed of sound ---*/ + + //RoeSoundSpeed2 = RoeChi + RoeKappa * ( RoeEnthalpy - 0.5 * sq_velRoe ); + RoeSoundSpeed = sqrt( RoeChi + RoeKappa * ( RoeEnthalpy - 0.5 * sq_velRoe ) ) - ProjInterfaceVel; + + /*--- Speed of sound at L and R ---*/ + + sL = min( RoeProjVelocity - RoeSoundSpeed, ProjVelocity_i - SoundSpeed_i ); + sR = max( RoeProjVelocity + RoeSoundSpeed, ProjVelocity_j + SoundSpeed_j ); + + /*--- speed of contact surface ---*/ + + RHO = Density_j * (sR - ProjVelocity_j) - Density_i * (sL - ProjVelocity_i); + sM = ( Pressure_i - Pressure_j - Density_i * ProjVelocity_i * ( sL - ProjVelocity_i ) + Density_j * ProjVelocity_j * ( sR - ProjVelocity_j ) ) / RHO; + + /*--- Pressure at right and left (Pressure_j=Pressure_i) side of contact surface ---*/ + + pStar = Density_j * ( ProjVelocity_j - sR ) * ( ProjVelocity_j - sM ) + Pressure_j; + + + if (sM > 0.0) { + + if (sL > 0.0) { + + /*--- Compute Left Flux ---*/ + + Flux[0] = Density_i * ProjVelocity_i; + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = Density_i * Velocity_i[iDim] * ProjVelocity_i + Pressure_i * UnitNormal[iDim]; + Flux[nVar-1] = Enthalpy_i * Density_i * ProjVelocity_i; + } + else { + + /*--- Compute Flux Left Star from Left Star State ---*/ + + rhoSL = ( sL - ProjVelocity_i ) / ( sL - sM ); + + IntermediateState[0] = rhoSL * Density_i; + for (iDim = 0; iDim < nDim; iDim++) + IntermediateState[iDim+1] = rhoSL * ( Density_i * Velocity_i[iDim] + ( pStar - Pressure_i ) / ( sL - ProjVelocity_i ) * UnitNormal[iDim] ) ; + IntermediateState[nVar-1] = rhoSL * ( Density_i * Energy_i - ( Pressure_i * ProjVelocity_i - pStar * sM) / ( sL - ProjVelocity_i ) ); + + + Flux[0] = sM * IntermediateState[0]; + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = sM * IntermediateState[iDim+1] + pStar * UnitNormal[iDim]; + Flux[nVar-1] = sM * ( IntermediateState[nVar-1] + pStar ) + pStar * ProjInterfaceVel; + } + } + else { + + if (sR < 0.0) { + + /*--- Compute Right Flux ---*/ + + Flux[0] = Density_j * ProjVelocity_j; + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = Density_j * Velocity_j[iDim] * ProjVelocity_j + Pressure_j * UnitNormal[iDim]; + Flux[nVar-1] = Enthalpy_j * Density_j * ProjVelocity_j; + } + else { + + /*--- Compute Flux Right Star from Right Star State ---*/ + + rhoSR = ( sR - ProjVelocity_j ) / ( sR - sM ); + + IntermediateState[0] = rhoSR * Density_j; + for (iDim = 0; iDim < nDim; iDim++) + IntermediateState[iDim+1] = rhoSR * ( Density_j * Velocity_j[iDim] + ( pStar - Pressure_j ) / ( sR - ProjVelocity_j ) * UnitNormal[iDim] ) ; + IntermediateState[nVar-1] = rhoSR * ( Density_j * Energy_j - ( Pressure_j * ProjVelocity_j - pStar * sM ) / ( sR - ProjVelocity_j ) ); + + + Flux[0] = sM * IntermediateState[0]; + for (iDim = 0; iDim < nDim; iDim++) + Flux[iDim+1] = sM * IntermediateState[iDim+1] + pStar * UnitNormal[iDim]; + Flux[nVar-1] = sM * (IntermediateState[nVar-1] + pStar ) + pStar * ProjInterfaceVel; + } + } + + for (iVar = 0; iVar < nVar; iVar++) + Flux[iVar] *= Area; + + /*--- Return early if the Jacobians do not need to be computed. ---*/ + + if (implicit) + { + if (sM > 0.0) { + + if (sL > 0.0) { + + /*--- Compute Jacobian based on Left State ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + Jacobian_j[iVar][jVar] = 0; + + + GetInviscidProjJac(Velocity_i, &Enthalpy_i, &Chi_i, &Kappa_i, UnitNormal, 1.0, Jacobian_i); + + } + else { + /*--- Compute Jacobian based on Left Star State ---*/ + + EStar = IntermediateState[nVar-1]; + Omega = 1/(sL-sM); + OmegaSM = Omega * sM; + + + /*--------- Left Jacobian ---------*/ + + + /*--- Computing pressure derivatives d/dU_L (PI) ---*/ + + dPI_dU[0] = Chi_i - 0.5 * Kappa_i * sq_vel_i; + for (iDim = 0; iDim < nDim; iDim++) + dPI_dU[iDim+1] = - Kappa_i * Velocity_i[iDim]; + dPI_dU[nVar-1] = Kappa_i; + + + /*--- Computing d/dU_L (Sm) ---*/ + + dSm_dU[0] = ( - ProjVelocity_i * ProjVelocity_i + sM * sL + dPI_dU[0] ) / RHO; + for (iDim = 0; iDim < nDim; iDim++) + dSm_dU[iDim+1] = ( UnitNormal[iDim] * ( 2 * ProjVelocity_i - sL - sM ) + dPI_dU[iDim+1] ) / RHO; + dSm_dU[nVar-1] = dPI_dU[nVar-1] / RHO; + + + /*--- Computing d/dU_L (rhoStar) ---*/ + + drhoStar_dU[0] = Omega * ( sL + IntermediateState[0] * dSm_dU[0] ); + for (iDim = 0; iDim < nDim; iDim++) + drhoStar_dU[iDim+1] = Omega * ( - UnitNormal[iDim] + IntermediateState[0] * dSm_dU[iDim+1] ); + drhoStar_dU[nVar-1] = Omega * IntermediateState[0] * dSm_dU[nVar-1]; + + + /*--- Computing d/dU_L (pStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dpStar_dU[iVar] = Density_i * (sR - ProjVelocity_j) * dSm_dU[iVar]; + + + /*--- Computing d/dU_L (EStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); + + dEStar_dU[0] += Omega * ProjVelocity_i * ( Enthalpy_i - dPI_dU[0] ); + for (iDim = 0; iDim < nDim; iDim++) + dEStar_dU[iDim+1] += Omega * ( - UnitNormal[iDim] * Enthalpy_i - ProjVelocity_i * dPI_dU[iDim+1] ); + dEStar_dU[nVar-1] += Omega * ( sL - ProjVelocity_i - ProjVelocity_i * dPI_dU[nVar-1] ); + + + + /*--- Jacobian First Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[0][iVar] = sM * drhoStar_dU[iVar] + IntermediateState[0] * dSm_dU[iVar]; + + /*--- Jacobian Middle Rows ---*/ + + for (jDim = 0; jDim < nDim; jDim++) { + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[jDim+1][iVar] = ( OmegaSM + 1 ) * ( UnitNormal[jDim] * dpStar_dU[iVar] + IntermediateState[jDim+1] * dSm_dU[iVar] ); + + Jacobian_i[jDim+1][0] += OmegaSM * Velocity_i[jDim] * ProjVelocity_i; + + Jacobian_i[jDim+1][jDim+1] += OmegaSM * (sL - ProjVelocity_i); + + for (iDim = 0; iDim < nDim; iDim++) + Jacobian_i[jDim+1][iDim+1] -= OmegaSM * Velocity_i[jDim] * UnitNormal[iDim]; + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[jDim+1][iVar] -= OmegaSM * dPI_dU[iVar] * UnitNormal[jDim]; + } + + /*--- Jacobian Last Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[nVar-1][iVar] = sM * ( dEStar_dU[iVar] + dpStar_dU[iVar] ) + ( EStar + pStar ) * dSm_dU[iVar]; + + + /*--------- Right Jacobian ---------*/ + + + /*--- Computing pressure derivatives d/dU_R (PI) ---*/ + + dPI_dU[0] = Chi_j - 0.5 * Kappa_j * sq_vel_j; + for (iDim = 0; iDim < nDim; iDim++) + dPI_dU[iDim+1] = - Kappa_j * Velocity_j[iDim]; + dPI_dU[nVar-1] = Kappa_j; + + + /*--- Computing d/dU_R (Sm) ---*/ + + dSm_dU[0] = ( ProjVelocity_j * ProjVelocity_j - sM * sR - dPI_dU[0] ) / RHO; + for (iDim = 0; iDim < nDim; iDim++) + dSm_dU[iDim+1] = - ( UnitNormal[iDim] * ( 2 * ProjVelocity_j - sR - sM) + dPI_dU[iDim+1] ) / RHO; + dSm_dU[nVar-1] = - dPI_dU[nVar-1] / RHO; + + + /*--- Computing d/dU_R (pStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dpStar_dU[iVar] = Density_j * (sL - ProjVelocity_i) * dSm_dU[iVar]; + + + /*--- Computing d/dU_R (EStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); + + + + /*--- Jacobian First Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[0][iVar] = IntermediateState[0] * ( OmegaSM + 1 ) * dSm_dU[iVar]; + + /*--- Jacobian Middle Rows ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[iDim+1][iVar] = ( OmegaSM + 1 ) * ( IntermediateState[iDim+1] * dSm_dU[iVar] + UnitNormal[iDim] * dpStar_dU[iVar] ); + } + + /*--- Jacobian Last Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[nVar-1][iVar] = sM * (dEStar_dU[iVar] + dpStar_dU[iVar]) + (EStar + pStar) * dSm_dU[iVar]; + } + } + else { + if (sR < 0.0) { + + /*--- Compute Jacobian based on Right State ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + Jacobian_i[iVar][jVar] = 0; + + GetInviscidProjJac(Velocity_j, &Enthalpy_j, &Chi_j, &Kappa_j, UnitNormal, 1.0, Jacobian_j); + + } + else { + /*--- Compute Jacobian based on Right Star State ---*/ + + EStar = IntermediateState[nVar-1]; + Omega = 1/(sR-sM); + OmegaSM = Omega * sM; + + + /*--------- Left Jacobian ---------*/ + + + /*--- Computing pressure derivatives d/dU_L (PI) ---*/ + + dPI_dU[0] = Chi_i - 0.5 * Kappa_i * sq_vel_i; + for (iDim = 0; iDim < nDim; iDim++) + dPI_dU[iDim+1] = - Kappa_i * Velocity_i[iDim]; + dPI_dU[nVar-1] = Kappa_i; + + + /*--- Computing d/dU_L (Sm) ---*/ + + dSm_dU[0] = ( - ProjVelocity_i * ProjVelocity_i + sM * sL + dPI_dU[0] ) / RHO; + for (iDim = 0; iDim < nDim; iDim++) + dSm_dU[iDim+1] = ( UnitNormal[iDim] * ( 2 * ProjVelocity_i - sL - sM ) + dPI_dU[iDim+1] ) / RHO; + dSm_dU[nVar-1] = dPI_dU[nVar-1] / RHO; + + + /*--- Computing d/dU_L (pStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dpStar_dU[iVar] = Density_i * (sR - ProjVelocity_j) * dSm_dU[iVar]; + + + /*--- Computing d/dU_L (EStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); + + + + /*--- Jacobian First Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[0][iVar] = IntermediateState[0] * ( OmegaSM + 1 ) * dSm_dU[iVar]; + + /*--- Jacobian Middle Rows ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[iDim+1][iVar] = (OmegaSM + 1) * ( IntermediateState[iDim+1] * dSm_dU[iVar] + UnitNormal[iDim] * dpStar_dU[iVar] ); + } + + /*--- Jacobian Last Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_i[nVar-1][iVar] = sM * (dEStar_dU[iVar] + dpStar_dU[iVar]) + (EStar + pStar) * dSm_dU[iVar]; + + + + /*--------- Right Jacobian ---------*/ + + + /*--- Computing pressure derivatives d/dU_R (PI) ---*/ + + dPI_dU[0] = Chi_j - 0.5 * Kappa_j * sq_vel_j; + for (iDim = 0; iDim < nDim; iDim++) + dPI_dU[iDim+1] = - Kappa_j * Velocity_j[iDim]; + dPI_dU[nVar-1] = Kappa_j; + + + /*--- Computing d/dU_R (Sm) ---*/ + + dSm_dU[0] = - ( - ProjVelocity_j * ProjVelocity_j + sM * sR + dPI_dU[0] ) / RHO; + for (iDim = 0; iDim < nDim; iDim++) + dSm_dU[iDim+1] = - ( UnitNormal[iDim] * ( 2 * ProjVelocity_j - sR - sM) + dPI_dU[iDim+1] ) / RHO; + dSm_dU[nVar-1] = - dPI_dU[nVar-1] / RHO; + + + /*--- Computing d/dU_R (pStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dpStar_dU[iVar] = Density_j * (sL - ProjVelocity_i) * dSm_dU[iVar]; + + + /*--- Computing d/dU_R (rhoStar) ---*/ + + drhoStar_dU[0] = Omega * ( sR + IntermediateState[0] * dSm_dU[0] ); + for (iDim = 0; iDim < nDim; iDim++) + drhoStar_dU[iDim+1] = Omega * ( - UnitNormal[iDim] + IntermediateState[0] * dSm_dU[iDim+1] ); + drhoStar_dU[nVar-1] = Omega * IntermediateState[0] * dSm_dU[nVar-1]; + + + /*--- Computing d/dU_R (EStar) ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); + + dEStar_dU[0] += Omega * ProjVelocity_j * ( Enthalpy_j - dPI_dU[0] ); + for (iDim = 0; iDim < nDim; iDim++) + dEStar_dU[iDim+1] += Omega * ( - UnitNormal[iDim] * Enthalpy_j - ProjVelocity_j * dPI_dU[iDim+1] ); + dEStar_dU[nVar-1] += Omega * ( sR - ProjVelocity_j - ProjVelocity_j * dPI_dU[nVar-1] ); + + + + /*--- Jacobian First Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[0][iVar] = sM * drhoStar_dU[iVar] + IntermediateState[0] * dSm_dU[iVar]; + + /*--- Jacobian Middle Rows ---*/ + + for (jDim = 0; jDim < nDim; jDim++) { + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[jDim+1][iVar] = ( OmegaSM + 1 ) * ( UnitNormal[jDim] * dpStar_dU[iVar] + IntermediateState[jDim+1] * dSm_dU[iVar] ); + + Jacobian_j[jDim+1][0] += OmegaSM * Velocity_j[jDim] * ProjVelocity_j; + + Jacobian_j[jDim+1][jDim+1] += OmegaSM * (sR - ProjVelocity_j); + + for (iDim = 0; iDim < nDim; iDim++) + Jacobian_j[jDim+1][iDim+1] -= OmegaSM * Velocity_j[jDim] * UnitNormal[iDim]; + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[jDim+1][iVar] -= OmegaSM * dPI_dU[iVar] * UnitNormal[jDim]; + } + + /*--- Jacobian Last Row ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Jacobian_j[nVar-1][iVar] = sM * ( dEStar_dU[iVar] + dpStar_dU[iVar] ) + ( EStar + pStar ) * dSm_dU[iVar]; + } + } + + + /*--- Jacobians of the inviscid flux, scale = kappa because Flux ~ 0.5*(fc_i+fc_j)*Normal ---*/ + + Area *= kappa; + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_i[iVar][jVar] *= Area; + Jacobian_j[iVar][jVar] *= Area; + } + } + } // end if implicit + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} + +void CUpwGeneralHLLC_Flow::VinokurMontagne() { + + su2double delta_rhoStaticEnergy, delta_rho, delta_p, err_P, s, D; + + delta_rho = Density_j - Density_i; + delta_p = Pressure_j - Pressure_i; + + RoeKappaStaticEnthalpy = 0.5 * ( StaticEnthalpy_i * Kappa_i + StaticEnthalpy_j * Kappa_j ); + + s = RoeChi + RoeKappaStaticEnthalpy; + + D = s*s * delta_rho * delta_rho + delta_p * delta_p; + + delta_rhoStaticEnergy = Density_j * StaticEnergy_j - Density_i * StaticEnergy_i; + + err_P = delta_p - RoeChi * delta_rho - RoeKappa * delta_rhoStaticEnergy; + + if (abs((D - delta_p*err_P)/Density_i) > 1e-3 && abs(delta_rho/Density_i) > 1e-3 && s/Density_i > 1e-3) { + + RoeKappa = ( D * RoeKappa ) / ( D - delta_p * err_P ); + RoeChi = ( D * RoeChi+ s*s * delta_rho * err_P ) / ( D - delta_p * err_P ); + + } +} diff --git a/SU2_CFD/src/numerics/flow/convection/roe.cpp b/SU2_CFD/src/numerics/flow/convection/roe.cpp new file mode 100644 index 000000000000..850adc958ffc --- /dev/null +++ b/SU2_CFD/src/numerics/flow/convection/roe.cpp @@ -0,0 +1,1023 @@ +/*! + * \file roe.cpp + * \brief Implementations of Roe-type schemes. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../../include/numerics/flow/convection/roe.hpp" + +CUpwRoeBase_Flow::CUpwRoeBase_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config, + bool val_low_dissipation) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + /* 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(); + kappa = config->GetRoe_Kappa(); // 1 is unstable + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + roe_low_dissipation = val_low_dissipation; + + Flux = new su2double [nVar]; + Diff_U = new su2double [nVar]; + ProjFlux_i = new su2double [nVar]; + ProjFlux_j = new su2double [nVar]; + Conservatives_i = new su2double [nVar]; + Conservatives_j = new su2double [nVar]; + Lambda = new su2double [nVar]; + P_Tensor = new su2double* [nVar]; + invP_Tensor = new su2double* [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + P_Tensor[iVar] = new su2double [nVar]; + invP_Tensor[iVar] = new su2double [nVar]; + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CUpwRoeBase_Flow::~CUpwRoeBase_Flow(void) { + + delete [] Flux; + delete [] Diff_U; + delete [] ProjFlux_i; + delete [] ProjFlux_j; + delete [] Conservatives_i; + delete [] Conservatives_j; + delete [] Lambda; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] P_Tensor[iVar]; + delete [] invP_Tensor[iVar]; + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] P_Tensor; + delete [] invP_Tensor; + delete [] Jacobian_i; + delete [] Jacobian_j; + +} + +void CUpwRoeBase_Flow::FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, const CConfig* config) { +/*--- + CUpwRoeBase_Flow::ComputeResidual initializes the residual (flux) and its Jacobians with the standard Roe averaging + fc_{1/2} = kappa*(fc_i+fc_j)*Normal. It then calls this method, which derived classes specialize, to account for + the dissipation part. +---*/ +} + +CNumerics::ResidualType<> CUpwRoeBase_Flow::ComputeResidual(const CConfig* config) { + + unsigned short iVar, jVar, iDim; + su2double ProjGridVel = 0.0, Energy_i, Energy_j; + + AD::StartPreacc(); + AD::SetPreaccIn(V_i, nDim+4); AD::SetPreaccIn(V_j, nDim+4); AD::SetPreaccIn(Normal, nDim); + if (dynamic_grid) { + AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); + } + if (roe_low_dissipation){ + AD::SetPreaccIn(Sensor_i); AD::SetPreaccIn(Sensor_j); + AD::SetPreaccIn(Dissipation_i); AD::SetPreaccIn(Dissipation_j); + } + + /*--- Face area (norm or the normal vector) and unit normal ---*/ + + 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; + + /*--- Primitive variables at point i ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + Velocity_i[iDim] = V_i[iDim+1]; + Pressure_i = V_i[nDim+1]; + Density_i = V_i[nDim+2]; + Enthalpy_i = V_i[nDim+3]; + Energy_i = Enthalpy_i - Pressure_i/Density_i; + + /*--- Primitive variables at point j ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + Velocity_j[iDim] = V_j[iDim+1]; + Pressure_j = V_j[nDim+1]; + Density_j = V_j[nDim+2]; + Enthalpy_j = V_j[nDim+3]; + Energy_j = Enthalpy_j - Pressure_j/Density_j; + + /*--- Compute variables that are common to the derived schemes ---*/ + + /*--- Roe-averaged variables at interface between i & j ---*/ + + su2double R = sqrt(fabs(Density_j/Density_i)); + RoeDensity = R*Density_i; + su2double sq_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); + sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; + } + RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); + RoeSoundSpeed2 = (Gamma-1)*(RoeEnthalpy-0.5*sq_vel); + + /*--- Negative RoeSoundSpeed^2, the jump variables is too large, clear fluxes and exit. ---*/ + + if (RoeSoundSpeed2 <= 0.0) { + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] = 0.0; + if (implicit){ + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_i[iVar][jVar] = 0.0; + Jacobian_j[iVar][jVar] = 0.0; + } + } + } + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + } + + RoeSoundSpeed = sqrt(RoeSoundSpeed2); + + /*--- P tensor ---*/ + + GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, P_Tensor); + + /*--- Projected velocity adjusted for mesh motion ---*/ + + ProjVelocity = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; + + if (dynamic_grid) { + for (iDim = 0; iDim < nDim; iDim++) + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*UnitNormal[iDim]; + ProjVelocity -= ProjGridVel; + } + + /*--- Flow eigenvalues ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + Lambda[iDim] = ProjVelocity; + + Lambda[nVar-2] = ProjVelocity + RoeSoundSpeed; + Lambda[nVar-1] = ProjVelocity - RoeSoundSpeed; + + /*--- Apply Mavriplis' entropy correction to eigenvalues ---*/ + + su2double MaxLambda = fabs(ProjVelocity) + RoeSoundSpeed; + + for (iVar = 0; iVar < nVar; iVar++) + Lambda[iVar] = max(fabs(Lambda[iVar]), config->GetEntropyFix_Coeff()*MaxLambda); + + /*--- Reconstruct conservative variables ---*/ + + Conservatives_i[0] = Density_i; + Conservatives_j[0] = Density_j; + + for (iDim = 0; iDim < nDim; iDim++) { + Conservatives_i[iDim+1] = Density_i*Velocity_i[iDim]; + Conservatives_j[iDim+1] = Density_j*Velocity_j[iDim]; + } + Conservatives_i[nDim+1] = Density_i*Energy_i; + Conservatives_j[nDim+1] = Density_j*Energy_j; + + /*--- Compute left and right fluxes ---*/ + + GetInviscidProjFlux(&Density_i, Velocity_i, &Pressure_i, &Enthalpy_i, Normal, ProjFlux_i); + GetInviscidProjFlux(&Density_j, Velocity_j, &Pressure_j, &Enthalpy_j, Normal, ProjFlux_j); + + /*--- Initialize residual (flux) and Jacobians ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + Flux[iVar] = kappa*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); + + if (implicit) { + GetInviscidProjJac(Velocity_i, &Energy_i, Normal, kappa, Jacobian_i); + GetInviscidProjJac(Velocity_j, &Energy_j, Normal, kappa, Jacobian_j); + } + + /*--- Finalize in children class ---*/ + + FinalizeResidual(Flux, Jacobian_i, Jacobian_j, config); + + /*--- Correct for grid motion ---*/ + + if (dynamic_grid) { + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] -= ProjGridVel*Area * 0.5*(Conservatives_i[iVar]+Conservatives_j[iVar]); + + if (implicit) { + Jacobian_i[iVar][iVar] -= 0.5*ProjGridVel*Area; + Jacobian_j[iVar][iVar] -= 0.5*ProjGridVel*Area; + } + } + } + + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} + +CUpwRoe_Flow::CUpwRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config, + bool val_low_dissipation) : CUpwRoeBase_Flow(val_nDim, val_nVar, config, val_low_dissipation) {} + +void CUpwRoe_Flow::FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, const CConfig* config) { + + unsigned short iVar, jVar, kVar; + + /*--- Compute inverse P tensor ---*/ + GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); + + /*--- Diference between conservative variables at jPoint and iPoint ---*/ + for (iVar = 0; iVar < nVar; iVar++) + Diff_U[iVar] = Conservatives_j[iVar]-Conservatives_i[iVar]; + + /*--- Low dissipation formulation ---*/ + if (roe_low_dissipation) + Dissipation_ij = GetRoe_Dissipation(Dissipation_i, Dissipation_j, Sensor_i, Sensor_j, config); + else + Dissipation_ij = 1.0; + + /*--- Standard Roe "dissipation" ---*/ + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ + su2double Proj_ModJac_Tensor_ij = 0.0; + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; + + /*--- Update residual and Jacobians ---*/ + val_residual[iVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Diff_U[jVar]*Area*Dissipation_ij; + + if(implicit){ + val_Jacobian_i[iVar][jVar] += (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; + val_Jacobian_j[iVar][jVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; + } + } + } + +} + +CUpwL2Roe_Flow::CUpwL2Roe_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CUpwRoeBase_Flow(val_nDim, val_nVar, config, false) {} + +void CUpwL2Roe_Flow::FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, const CConfig* config) { + + /*--- L2Roe: a low dissipation version of Roe's approximate Riemann solver for low Mach numbers. IJNMF 2015 ---*/ + + unsigned short iVar, jVar, kVar, iDim; + + /*--- Clamped Mach number ---*/ + + su2double M_i = 0.0, M_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + M_i += Velocity_i[iDim]*Velocity_i[iDim]; + M_j += Velocity_j[iDim]*Velocity_j[iDim]; + } + M_i = sqrt(M_i / fabs(Pressure_i*Gamma/Density_i)); + M_j = sqrt(M_j / fabs(Pressure_j*Gamma/Density_j)); + + su2double zeta = max(0.05,min(max(M_i,M_j),1.0)); + + /*--- Compute wave amplitudes (characteristics) ---*/ + + su2double proj_delta_vel = 0.0, delta_vel[3]; + for (iDim = 0; iDim < nDim; iDim++) { + delta_vel[iDim] = Velocity_j[iDim] - Velocity_i[iDim]; + proj_delta_vel += delta_vel[iDim]*UnitNormal[iDim]; + } + proj_delta_vel *= zeta; + su2double delta_p = Pressure_j - Pressure_i; + su2double delta_rho = Density_j - Density_i; + + su2double delta_wave[5] = {0.0, 0.0, 0.0, 0.0, 0.0}; + if (nDim == 2) { + delta_wave[0] = delta_rho - delta_p/RoeSoundSpeed2; + delta_wave[1] = (UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1])*zeta; + delta_wave[2] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + delta_wave[3] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + } else { + delta_wave[0] = delta_rho - delta_p/RoeSoundSpeed2; + delta_wave[1] = (UnitNormal[0]*delta_vel[2]-UnitNormal[2]*delta_vel[0])*zeta; + delta_wave[2] = (UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1])*zeta; + delta_wave[3] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + delta_wave[4] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + } + + /*--- Update residual ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + for (kVar = 0; kVar < nVar; kVar++) + val_residual[iVar] -= (1.0-kappa)*Lambda[kVar]*delta_wave[kVar]*P_Tensor[iVar][kVar]*Area; + + if (!implicit) return; + + /*--- If implicit use the Jacobians of the standard Roe scheme as an approximation ---*/ + + GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ + su2double Proj_ModJac_Tensor_ij = 0.0; + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; + + val_Jacobian_i[iVar][jVar] += (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; + val_Jacobian_j[iVar][jVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; + } + } + +} + +CUpwLMRoe_Flow::CUpwLMRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CUpwRoeBase_Flow(val_nDim, val_nVar, config, false) {} + +void CUpwLMRoe_Flow::FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, const CConfig* config) { + + /*--- Rieper, A low-Mach number fix for Roe's approximate Riemman Solver, JCP 2011 ---*/ + + unsigned short iVar, jVar, kVar, iDim; + + /*--- Clamped Mach number ---*/ + + su2double M_i = 0.0, M_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + M_i += Velocity_i[iDim]*Velocity_i[iDim]; + M_j += Velocity_j[iDim]*Velocity_j[iDim]; + } + M_i = sqrt(M_i / fabs(Pressure_i*Gamma/Density_i)); + M_j = sqrt(M_j / fabs(Pressure_j*Gamma/Density_j)); + + su2double zeta = max(0.05,min(max(M_i,M_j),1.0)); + + /*--- Compute wave amplitudes (characteristics) ---*/ + + su2double proj_delta_vel = 0.0, delta_vel[3]; + for (iDim = 0; iDim < nDim; iDim++) { + delta_vel[iDim] = Velocity_j[iDim] - Velocity_i[iDim]; + proj_delta_vel += delta_vel[iDim]*UnitNormal[iDim]; + } + proj_delta_vel *= zeta; + su2double delta_p = Pressure_j - Pressure_i; + su2double delta_rho = Density_j - Density_i; + + su2double delta_wave[5] = {0.0, 0.0, 0.0, 0.0, 0.0}; + if (nDim == 2) { + delta_wave[0] = delta_rho - delta_p/RoeSoundSpeed2; + delta_wave[1] = (UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]); + delta_wave[2] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + delta_wave[3] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + } else { + delta_wave[0] = delta_rho - delta_p/RoeSoundSpeed2; + delta_wave[1] = (UnitNormal[0]*delta_vel[2]-UnitNormal[2]*delta_vel[0]); + delta_wave[2] = (UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]); + delta_wave[3] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + delta_wave[4] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + } + + /*--- Update residual ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + for (kVar = 0; kVar < nVar; kVar++) + val_residual[iVar] -= (1.0-kappa)*Lambda[kVar]*delta_wave[kVar]*P_Tensor[iVar][kVar]*Area; + + if (!implicit) return; + + /*--- If implicit use the Jacobians of the standard Roe scheme as an approximation ---*/ + + GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); + + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ + su2double Proj_ModJac_Tensor_ij = 0.0; + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; + + val_Jacobian_i[iVar][jVar] += (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; + val_Jacobian_j[iVar][jVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; + } + } + +} + +CUpwTurkel_Flow::CUpwTurkel_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + /* 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(); + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + Beta_min = config->GetminTurkelBeta(); + Beta_max = config->GetmaxTurkelBeta(); + + Flux = new su2double [nVar]; + Diff_U = new su2double [nVar]; + Velocity_i = new su2double [nDim]; + Velocity_j = new su2double [nDim]; + RoeVelocity = new su2double [nDim]; + ProjFlux_i = new su2double [nVar]; + ProjFlux_j = new su2double [nVar]; + Lambda = new su2double [nVar]; + Epsilon = new su2double [nVar]; + absPeJac = new su2double* [nVar]; + invRinvPe = new su2double* [nVar]; + R_Tensor = new su2double* [nVar]; + Matrix = new su2double* [nVar]; + Art_Visc = new su2double* [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (iVar = 0; iVar < nVar; iVar++) { + absPeJac[iVar] = new su2double [nVar]; + invRinvPe[iVar] = new su2double [nVar]; + Matrix[iVar] = new su2double [nVar]; + Art_Visc[iVar] = new su2double [nVar]; + R_Tensor[iVar] = new su2double [nVar]; + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CUpwTurkel_Flow::~CUpwTurkel_Flow(void) { + + delete [] Flux; + delete [] Diff_U; + delete [] Velocity_i; + delete [] Velocity_j; + delete [] RoeVelocity; + delete [] ProjFlux_i; + delete [] ProjFlux_j; + delete [] Lambda; + delete [] Epsilon; + for (iVar = 0; iVar < nVar; iVar++) { + delete [] absPeJac[iVar]; + delete [] invRinvPe[iVar]; + delete [] Matrix[iVar]; + delete [] Art_Visc[iVar]; + delete [] R_Tensor[iVar]; + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Matrix; + delete [] Art_Visc; + delete [] absPeJac; + delete [] invRinvPe; + delete [] R_Tensor; + delete [] Jacobian_i; + delete [] Jacobian_j; + +} + +CNumerics::ResidualType<> CUpwTurkel_Flow::ComputeResidual(const CConfig* config) { + + su2double U_i[5] = {0.0}, U_j[5] = {0.0}; + + /*--- Face area (norm or the normal vector) ---*/ + + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Area += Normal[iDim]*Normal[iDim]; + Area = sqrt(Area); + + /*-- Unit Normal ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + UnitNormal[iDim] = Normal[iDim]/Area; + + /*--- Primitive variables at point i ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + Velocity_i[iDim] = V_i[iDim+1]; + Pressure_i = V_i[nDim+1]; + Density_i = V_i[nDim+2]; + Enthalpy_i = V_i[nDim+3]; + Energy_i = Enthalpy_i - Pressure_i/Density_i; + SoundSpeed_i = sqrt(fabs(Pressure_i*Gamma/Density_i)); + + /*--- Primitive variables at point j ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + Velocity_j[iDim] = V_j[iDim+1]; + Pressure_j = V_j[nDim+1]; + Density_j = V_j[nDim+2]; + Enthalpy_j = V_j[nDim+3]; + Energy_j = Enthalpy_j - Pressure_j/Density_j; + SoundSpeed_j = sqrt(fabs(Pressure_j*Gamma/Density_j)); + + /*--- Recompute conservative variables ---*/ + + U_i[0] = Density_i; U_j[0] = Density_j; + for (iDim = 0; iDim < nDim; iDim++) { + U_i[iDim+1] = Density_i*Velocity_i[iDim]; U_j[iDim+1] = Density_j*Velocity_j[iDim]; + } + U_i[nDim+1] = Density_i*Energy_i; U_j[nDim+1] = Density_j*Energy_j; + + /*--- Roe-averaged variables at interface between i & j ---*/ + + R = sqrt(fabs(Density_j/Density_i)); + RoeDensity = R*Density_i; + sq_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); + sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; + } + RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); + RoeSoundSpeed = sqrt(fabs((Gamma-1)*(RoeEnthalpy-0.5*sq_vel))); + RoePressure = RoeDensity/Gamma*RoeSoundSpeed*RoeSoundSpeed; + + /*--- Compute ProjFlux_i ---*/ + GetInviscidProjFlux(&Density_i, Velocity_i, &Pressure_i, &Enthalpy_i, Normal, ProjFlux_i); + + /*--- Compute ProjFlux_j ---*/ + GetInviscidProjFlux(&Density_j, Velocity_j, &Pressure_j, &Enthalpy_j, Normal, ProjFlux_j); + + ProjVelocity = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; + ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; + } + + /*--- Projected velocity adjustment due to mesh motion ---*/ + if (dynamic_grid) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*UnitNormal[iDim]; + } + ProjVelocity -= ProjGridVel; + ProjVelocity_i -= ProjGridVel; + ProjVelocity_j -= ProjGridVel; + } + + /*--- First few flow eigenvalues of A.Normal with the normal---*/ + for (iDim = 0; iDim < nDim; iDim++) + Lambda[iDim] = ProjVelocity; + + local_Mach = sqrt(sq_vel)/RoeSoundSpeed; + Beta = max(Beta_min, min(local_Mach, Beta_max)); + Beta2 = Beta*Beta; + + one_m_Betasqr = 1.0 - Beta2; // 1-Beta*Beta + one_p_Betasqr = 1.0 + Beta2; // 1+Beta*Beta + sqr_one_m_Betasqr_Lam1 = pow((one_m_Betasqr*Lambda[0]),2); // [(1-Beta^2)*Lambda[0]]^2 + sqr_two_Beta_c_Area = pow(2.0*Beta*RoeSoundSpeed*Area,2); // [2*Beta*c*Area]^2 + + /*--- The rest of the flow eigenvalues of preconditioned matrix---*/ + Lambda[nVar-2] = 0.5 * ( one_p_Betasqr*Lambda[0] + sqrt( sqr_one_m_Betasqr_Lam1 + sqr_two_Beta_c_Area)); + Lambda[nVar-1] = 0.5 * ( one_p_Betasqr*Lambda[0] - sqrt( sqr_one_m_Betasqr_Lam1 + sqr_two_Beta_c_Area)); + + s_hat = 1.0/Area * (Lambda[nVar-1] - Lambda[0]*Beta2); + r_hat = 1.0/Area * (Lambda[nVar-2] - Lambda[0]*Beta2); + t_hat = 0.5/Area * (Lambda[nVar-1] - Lambda[nVar-2]); + rhoB2a2 = RoeDensity*Beta2*RoeSoundSpeed*RoeSoundSpeed; + + /*--- Diference variables iPoint and jPoint and absolute value of the eigen values---*/ + for (iVar = 0; iVar < nVar; iVar++) { + Diff_U[iVar] = U_j[iVar]-U_i[iVar]; + Lambda[iVar] = fabs(Lambda[iVar]); + } + + /*--- Compute the absolute Preconditioned Jacobian in entropic Variables (do it with the Unitary Normal) ---*/ + GetPrecondJacobian(Beta2, r_hat, s_hat, t_hat, rhoB2a2, Lambda, UnitNormal, absPeJac); + + /*--- Compute the matrix from entropic variables to conserved variables ---*/ + GetinvRinvPe(Beta2, RoeEnthalpy, RoeSoundSpeed, RoeDensity, RoeVelocity, invRinvPe); + + /*--- Compute the matrix from entropic variables to conserved variables ---*/ + GetRMatrix(RoePressure, RoeSoundSpeed, RoeDensity, RoeVelocity, R_Tensor); + + if (implicit) { + /*--- Jacobians of the inviscid flux, scaled by + 0.5 because Flux ~ 0.5*(fc_i+fc_j)*Normal ---*/ + GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5, Jacobian_i); + GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5, Jacobian_j); + } + + for (iVar = 0; iVar < nVar; iVar ++) { + for (jVar = 0; jVar < nVar; jVar ++) { + Matrix[iVar][jVar] = 0.0; + for (kVar = 0; kVar < nVar; kVar++) + Matrix[iVar][jVar] += absPeJac[iVar][kVar]*R_Tensor[kVar][jVar]; + } + } + + for (iVar = 0; iVar < nVar; iVar ++) { + for (jVar = 0; jVar < nVar; jVar ++) { + Art_Visc[iVar][jVar] = 0.0; + for (kVar = 0; kVar < nVar; kVar++) + Art_Visc[iVar][jVar] += invRinvPe[iVar][kVar]*Matrix[kVar][jVar]; + } + } + + /*--- Roe's Flux approximation ---*/ + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] = 0.5*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); + for (jVar = 0; jVar < nVar; jVar++) { + Flux[iVar] -= 0.5*Art_Visc[iVar][jVar]*Diff_U[jVar]; + if (implicit) { + Jacobian_i[iVar][jVar] += 0.5*Art_Visc[iVar][jVar]; + Jacobian_j[iVar][jVar] -= 0.5*Art_Visc[iVar][jVar]; + } + } + } + + /*--- Contributions due to mesh motion---*/ + if (dynamic_grid) { + ProjVelocity = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*UnitNormal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); + /*--- Implicit terms ---*/ + if (implicit) { + Jacobian_i[iVar][iVar] -= 0.5*ProjVelocity; + Jacobian_j[iVar][iVar] -= 0.5*ProjVelocity; + } + } + } + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} + +CUpwGeneralRoe_Flow::CUpwGeneralRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + /* 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(); + kappa = config->GetRoe_Kappa(); // 1 is unstable + + + Flux = new su2double [nVar]; + Diff_U = new su2double [nVar]; + Velocity_i = new su2double [nDim]; + Velocity_j = new su2double [nDim]; + RoeVelocity = new su2double [nDim]; + delta_vel = new su2double [nDim]; + delta_wave = new su2double [nVar]; + ProjFlux_i = new su2double [nVar]; + ProjFlux_j = new su2double [nVar]; + Lambda = new su2double [nVar]; + Epsilon = new su2double [nVar]; + P_Tensor = new su2double* [nVar]; + invP_Tensor = new su2double* [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (iVar = 0; iVar < nVar; iVar++) { + P_Tensor[iVar] = new su2double [nVar]; + invP_Tensor[iVar] = new su2double [nVar]; + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CUpwGeneralRoe_Flow::~CUpwGeneralRoe_Flow(void) { + + delete [] Flux; + delete [] Diff_U; + delete [] Velocity_i; + delete [] Velocity_j; + delete [] RoeVelocity; + delete [] delta_vel; + delete [] delta_wave; + delete [] ProjFlux_i; + delete [] ProjFlux_j; + delete [] Lambda; + delete [] Epsilon; + for (iVar = 0; iVar < nVar; iVar++) { + delete [] P_Tensor[iVar]; + delete [] invP_Tensor[iVar]; + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] P_Tensor; + delete [] invP_Tensor; + delete [] Jacobian_i; + delete [] Jacobian_j; + +} + +CNumerics::ResidualType<> CUpwGeneralRoe_Flow::ComputeResidual(const CConfig* config) { + + AD::StartPreacc(); + AD::SetPreaccIn(V_i, nDim+4); AD::SetPreaccIn(V_j, nDim+4); AD::SetPreaccIn(Normal, nDim); + AD::SetPreaccIn(S_i, 2); AD::SetPreaccIn(S_j, 2); + if (dynamic_grid) { + AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); + } + su2double U_i[5] = {0.0,0.0,0.0,0.0,0.0}, U_j[5] = {0.0,0.0,0.0,0.0,0.0}; + + /*--- Face area (norm or the normal vector) ---*/ + + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Area += Normal[iDim]*Normal[iDim]; + Area = sqrt(Area); + + /*-- Unit Normal ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + UnitNormal[iDim] = Normal[iDim]/Area; + + /*--- Primitive variables at point i ---*/ + + Velocity2_i = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Velocity2_i += Velocity_i[iDim]*Velocity_i[iDim]; + } + + Pressure_i = V_i[nDim+1]; + Density_i = V_i[nDim+2]; + Enthalpy_i = V_i[nDim+3]; + Energy_i = Enthalpy_i - Pressure_i/Density_i; + StaticEnthalpy_i = Enthalpy_i - 0.5*Velocity2_i; + StaticEnergy_i = StaticEnthalpy_i - Pressure_i/Density_i; + + Kappa_i = S_i[1]/Density_i; + Chi_i = S_i[0] - Kappa_i*StaticEnergy_i; + SoundSpeed_i = sqrt(Chi_i + StaticEnthalpy_i*Kappa_i); + + /*--- Primitive variables at point j ---*/ + + Velocity2_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_j[iDim] = V_j[iDim+1]; + Velocity2_j += Velocity_j[iDim]*Velocity_j[iDim]; + } + + Pressure_j = V_j[nDim+1]; + Density_j = V_j[nDim+2]; + Enthalpy_j = V_j[nDim+3]; + Energy_j = Enthalpy_j - Pressure_j/Density_j; + + StaticEnthalpy_j = Enthalpy_j - 0.5*Velocity2_j; + StaticEnergy_j = StaticEnthalpy_j - Pressure_j/Density_j; + + Kappa_j = S_j[1]/Density_j; + Chi_j = S_j[0] - Kappa_j*StaticEnergy_j; + SoundSpeed_j = sqrt(Chi_j + StaticEnthalpy_j*Kappa_j); + + /*--- Recompute conservative variables ---*/ + + U_i[0] = Density_i; U_j[0] = Density_j; + for (iDim = 0; iDim < nDim; iDim++) { + U_i[iDim+1] = Density_i*Velocity_i[iDim]; U_j[iDim+1] = Density_j*Velocity_j[iDim]; + } + U_i[nDim+1] = Density_i*Energy_i; U_j[nDim+1] = Density_j*Energy_j; + + /*--- Roe-averaged variables at interface between i & j ---*/ + + ComputeRoeAverage(); + + if (RoeSoundSpeed2 <= 0.0) { + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] = 0.0; + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_i[iVar][iVar] = 0.0; + Jacobian_j[iVar][iVar] = 0.0; + } + } + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + } + + RoeSoundSpeed = sqrt(RoeSoundSpeed2); + + /*--- Compute ProjFlux_i ---*/ + GetInviscidProjFlux(&Density_i, Velocity_i, &Pressure_i, &Enthalpy_i, Normal, ProjFlux_i); + + /*--- Compute ProjFlux_j ---*/ + GetInviscidProjFlux(&Density_j, Velocity_j, &Pressure_j, &Enthalpy_j, Normal, ProjFlux_j); + + /*--- Compute P and Lambda (do it with the Normal) ---*/ + + GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, &RoeEnthalpy, &RoeChi, &RoeKappa, UnitNormal, P_Tensor); + + ProjVelocity = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; + ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; + ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; + } + + /*--- Projected velocity adjustment due to mesh motion ---*/ + if (dynamic_grid) { + su2double ProjGridVel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*UnitNormal[iDim]; + } + ProjVelocity -= ProjGridVel; + ProjVelocity_i -= ProjGridVel; + ProjVelocity_j -= ProjGridVel; + } + + /*--- Flow eigenvalues and entropy correctors ---*/ + for (iDim = 0; iDim < nDim; iDim++) + Lambda[iDim] = ProjVelocity; + + Lambda[nVar-2] = ProjVelocity + RoeSoundSpeed; + Lambda[nVar-1] = ProjVelocity - RoeSoundSpeed; + + /*--- Compute absolute value with Mavriplis' entropy correction ---*/ + + MaxLambda = fabs(ProjVelocity) + RoeSoundSpeed; + Delta = config->GetEntropyFix_Coeff(); + + for (iVar = 0; iVar < nVar; iVar++) { + Lambda[iVar] = max(fabs(Lambda[iVar]), Delta*MaxLambda); + } + +// /*--- Harten and Hyman (1983) entropy correction ---*/ +// for (iDim = 0; iDim < nDim; iDim++) +// Epsilon[iDim] = 4.0*max(0.0, max(Lambda[iDim]-ProjVelocity_i, ProjVelocity_j-Lambda[iDim])); +// +// Epsilon[nVar-2] = 4.0*max(0.0, max(Lambda[nVar-2]-(ProjVelocity_i+SoundSpeed_i),(ProjVelocity_j+SoundSpeed_j)-Lambda[nVar-2])); +// Epsilon[nVar-1] = 4.0*max(0.0, max(Lambda[nVar-1]-(ProjVelocity_i-SoundSpeed_i),(ProjVelocity_j-SoundSpeed_j)-Lambda[nVar-1])); +// +// for (iVar = 0; iVar < nVar; iVar++) +// if ( fabs(Lambda[iVar]) < Epsilon[iVar] ) +// Lambda[iVar] = (Lambda[iVar]*Lambda[iVar] + Epsilon[iVar]*Epsilon[iVar])/(2.0*Epsilon[iVar]); +// else +// Lambda[iVar] = fabs(Lambda[iVar]); + +// for (iVar = 0; iVar < nVar; iVar++) +// Lambda[iVar] = fabs(Lambda[iVar]); + + if (!implicit) { + + /*--- Compute wave amplitudes (characteristics) ---*/ + proj_delta_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + delta_vel[iDim] = Velocity_j[iDim] - Velocity_i[iDim]; + proj_delta_vel += delta_vel[iDim]*Normal[iDim]; + } + delta_p = Pressure_j - Pressure_i; + delta_rho = Density_j - Density_i; + proj_delta_vel = proj_delta_vel/Area; + + if (nDim == 2) { + delta_wave[0] = delta_rho - delta_p/(RoeSoundSpeed*RoeSoundSpeed); + delta_wave[1] = UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]; + delta_wave[2] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + delta_wave[3] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + } else { + delta_wave[0] = delta_rho - delta_p/(RoeSoundSpeed*RoeSoundSpeed); + delta_wave[1] = UnitNormal[0]*delta_vel[2]-UnitNormal[2]*delta_vel[0]; + delta_wave[2] = UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]; + delta_wave[3] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + delta_wave[4] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); + } + + /*--- Roe's Flux approximation ---*/ + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] = 0.5*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); + for (jVar = 0; jVar < nVar; jVar++) + Flux[iVar] -= 0.5*Lambda[jVar]*delta_wave[jVar]*P_Tensor[iVar][jVar]*Area; + } + + /*--- Flux contribution due to grid motion ---*/ + if (dynamic_grid) { + ProjVelocity = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); + } + } + } + else { + + /*--- Compute inverse P ---*/ + + GetPMatrix_inv(invP_Tensor, &RoeDensity, RoeVelocity, &RoeSoundSpeed, &RoeChi , &RoeKappa, UnitNormal); + + /*--- Jacobians of the inviscid flux, scaled by + kappa because val_resconv ~ kappa*(fc_i+fc_j)*Normal ---*/ + + GetInviscidProjJac(Velocity_i, &Enthalpy_i, &Chi_i, &Kappa_i, Normal, kappa, Jacobian_i); + + GetInviscidProjJac(Velocity_j, &Enthalpy_j, &Chi_j, &Kappa_j, Normal, kappa, Jacobian_j); + + + /*--- Diference variables iPoint and jPoint ---*/ + for (iVar = 0; iVar < nVar; iVar++) + Diff_U[iVar] = U_j[iVar]-U_i[iVar]; + + /*--- Roe's Flux approximation ---*/ + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] = kappa*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); + for (jVar = 0; jVar < nVar; jVar++) { + Proj_ModJac_Tensor_ij = 0.0; + + /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ + + for (kVar = 0; kVar < nVar; kVar++) + Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; + + Flux[iVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Diff_U[jVar]*Area; + Jacobian_i[iVar][jVar] += (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; + Jacobian_j[iVar][jVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; + } + } + + /*--- Jacobian contributions due to grid motion ---*/ + if (dynamic_grid) { + ProjVelocity = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) { + Flux[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); + /*--- Implicit terms ---*/ + Jacobian_i[iVar][iVar] -= 0.5*ProjVelocity; + Jacobian_j[iVar][iVar] -= 0.5*ProjVelocity; + } + } + + } + + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} + +void CUpwGeneralRoe_Flow::ComputeRoeAverage() { + + //su2double delta_rhoStaticEnergy, err_P, s, D; + // su2double tol = 10-6; + + R = sqrt(fabs(Density_j/Density_i)); + RoeDensity = R*Density_i; + sq_vel = 0; for (iDim = 0; iDim < nDim; iDim++) { + RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); + sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; + } + + RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); + delta_rho = Density_j - Density_i; + delta_p = Pressure_j - Pressure_i; + RoeKappa = 0.5*(Kappa_i + Kappa_j); + RoeKappa = (Kappa_i + Kappa_j + 4*RoeKappa)/6; + RoeChi = 0.5*(Chi_i + Chi_j); + RoeChi = (Chi_i + Chi_j + 4*RoeChi)/6; + +// RoeKappaStaticEnthalpy = 0.5*(StaticEnthalpy_i*Kappa_i + StaticEnthalpy_j*Kappa_j); +// RoeKappaStaticEnthalpy = (StaticEnthalpy_i*Kappa_i + StaticEnthalpy_j*Kappa_j + 4*RoeKappaStaticEnthalpy)/6; +// s = RoeChi + RoeKappaStaticEnthalpy; +// D = s*s*delta_rho*delta_rho + delta_p*delta_p; +// delta_rhoStaticEnergy = Density_j*StaticEnergy_j - Density_i*StaticEnergy_i; +// err_P = delta_p - RoeChi*delta_rho - RoeKappa*delta_rhoStaticEnergy; +// +// +// if (abs((D - delta_p*err_P)/Density_i)>1e-3 && abs(delta_rho/Density_i)>1e-3 && s/Density_i > 1e-3) { +// +// RoeKappa = (D*RoeKappa)/(D - delta_p*err_P); +// RoeChi = (D*RoeChi+ s*s*delta_rho*err_P)/(D - delta_p*err_P); +// +// } + + RoeSoundSpeed2 = RoeChi + RoeKappa*(RoeEnthalpy-0.5*sq_vel); + +} diff --git a/SU2_CFD/src/numerics/flow/flow_diffusion.cpp b/SU2_CFD/src/numerics/flow/flow_diffusion.cpp new file mode 100644 index 000000000000..2587155c0ab4 --- /dev/null +++ b/SU2_CFD/src/numerics/flow/flow_diffusion.cpp @@ -0,0 +1,1181 @@ +/*! + * \file flow_diffusion.cpp + * \brief Implementation of numerics classes for discretization + * of viscous fluxes in fluid flow problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/numerics/flow/flow_diffusion.hpp" + +CAvgGrad_Base::CAvgGrad_Base(unsigned short val_nDim, + unsigned short val_nVar, + unsigned short val_nPrimVar, + bool val_correct_grad, + const CConfig* config) + : CNumerics(val_nDim, val_nVar, config), + nPrimVar(val_nPrimVar), + correct_gradient(val_correct_grad) { + + unsigned short iVar, iDim; + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + + TauWall_i = 0; TauWall_j = 0; + + Mean_PrimVar = new su2double [nPrimVar]; + + Mean_GradPrimVar = new su2double* [nPrimVar]; + for (iVar = 0; iVar < nPrimVar; iVar++) + Mean_GradPrimVar[iVar] = new su2double [nDim]; + + Proj_Mean_GradPrimVar_Edge = new su2double[val_nPrimVar]; + + tau_jacobian_i = new su2double* [nDim]; + for (iDim = 0; iDim < nDim; iDim++) { + tau_jacobian_i[iDim] = new su2double [nVar]; + } + + heat_flux_jac_i = new su2double[nVar]; + + 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]; + } + +} + +CAvgGrad_Base::~CAvgGrad_Base() { + + delete [] Mean_PrimVar; + + if (Mean_GradPrimVar != nullptr) { + for (unsigned short iVar = 0; iVar < nPrimVar; iVar++) + delete [] Mean_GradPrimVar[iVar]; + delete [] Mean_GradPrimVar; + } + + delete [] Proj_Mean_GradPrimVar_Edge; + + if (tau_jacobian_i != nullptr) { + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + delete [] tau_jacobian_i[iDim]; + } + delete [] tau_jacobian_i; + } + + delete [] heat_flux_jac_i; + + if (Jacobian_i != nullptr) { + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Jacobian_i; + delete [] Jacobian_j; + } + +} + +void CAvgGrad_Base::CorrectGradient(su2double** GradPrimVar, + const su2double* val_PrimVar_i, + const su2double* val_PrimVar_j, + const su2double* val_edge_vector, + const su2double val_dist_ij_2, + const unsigned short val_nPrimVar) { + for (unsigned short iVar = 0; iVar < val_nPrimVar; iVar++) { + Proj_Mean_GradPrimVar_Edge[iVar] = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + Proj_Mean_GradPrimVar_Edge[iVar] += GradPrimVar[iVar][iDim]*val_edge_vector[iDim]; + } + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + GradPrimVar[iVar][iDim] -= (Proj_Mean_GradPrimVar_Edge[iVar] - + (val_PrimVar_j[iVar]-val_PrimVar_i[iVar]))*val_edge_vector[iDim] / val_dist_ij_2; + } + } +} + +void CAvgGrad_Base::SetStressTensor(const su2double *val_primvar, + const su2double* const *val_gradprimvar, + const su2double val_turb_ke, + const su2double val_laminar_viscosity, + const su2double val_eddy_viscosity) { + + unsigned short iDim, jDim; + const su2double Density = val_primvar[nDim+2]; + const su2double total_viscosity = val_laminar_viscosity + val_eddy_viscosity; + + su2double div_vel = 0.0; + for (iDim = 0 ; iDim < nDim; iDim++) + div_vel += val_gradprimvar[iDim+1][iDim]; + + /* --- If UQ methodology is used, calculate tau using the perturbed reynolds stress tensor --- */ + + if (using_uq){ + for (iDim = 0 ; iDim < nDim; iDim++) + for (jDim = 0 ; jDim < nDim; jDim++) + tau[iDim][jDim] = val_laminar_viscosity*( val_gradprimvar[jDim+1][iDim] + val_gradprimvar[iDim+1][jDim] ) + - TWO3*val_laminar_viscosity*div_vel*delta[iDim][jDim] - Density * MeanPerturbedRSM[iDim][jDim]; + + } else { + + for (iDim = 0 ; iDim < nDim; iDim++) + for (jDim = 0 ; jDim < nDim; jDim++) + tau[iDim][jDim] = total_viscosity*( val_gradprimvar[jDim+1][iDim] + val_gradprimvar[iDim+1][jDim] ) + - TWO3*total_viscosity*div_vel*delta[iDim][jDim]; + } +} + +void CAvgGrad_Base::AddQCR(const su2double* const *val_gradprimvar) { + + su2double den_aux, c_cr1= 0.3, O_ik, O_jk; + unsigned short iDim, jDim, kDim; + + /*--- Denominator Antisymmetric normalized rotation tensor ---*/ + + den_aux = 0.0; + for (iDim = 0 ; iDim < nDim; iDim++) + for (jDim = 0 ; jDim < nDim; jDim++) + den_aux += val_gradprimvar[iDim+1][jDim] * val_gradprimvar[iDim+1][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 = (val_gradprimvar[iDim+1][kDim] - val_gradprimvar[kDim+1][iDim])/ den_aux; + O_jk = (val_gradprimvar[jDim+1][kDim] - val_gradprimvar[kDim+1][jDim])/ den_aux; + tau[iDim][jDim] -= c_cr1 * ((O_ik * tau[jDim][kDim]) + (O_jk * tau[iDim][kDim])); + } + } + } +} + +void CAvgGrad_Base::AddTauWall(const su2double *val_normal, + const su2double val_tau_wall) { + + unsigned short iDim, jDim; + su2double TauNormal, TauElem[3], TauTangent[3], WallShearStress, Area, UnitNormal[3]; + + Area = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Area += val_normal[iDim]*val_normal[iDim]; + Area = sqrt(Area); + + for (iDim = 0; iDim < nDim; iDim++) + UnitNormal[iDim] = val_normal[iDim]/Area; + + /*--- First, compute wall shear stress as the magnitude of the wall-tangential + component of the shear stress tensor---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + TauElem[iDim] = 0.0; + for (jDim = 0; jDim < nDim; jDim++) + TauElem[iDim] += tau[iDim][jDim]*UnitNormal[jDim]; + } + + TauNormal = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + TauNormal += TauElem[iDim] * UnitNormal[iDim]; + + for (iDim = 0; iDim < nDim; iDim++) + TauTangent[iDim] = TauElem[iDim] - TauNormal * UnitNormal[iDim]; + + WallShearStress = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + WallShearStress += TauTangent[iDim]*TauTangent[iDim]; + WallShearStress = sqrt(WallShearStress); + + /*--- Scale the stress tensor by the ratio of the wall shear stress + to the computed representation of the shear stress ---*/ + + for (iDim = 0 ; iDim < nDim; iDim++) + for (jDim = 0 ; jDim < nDim; jDim++) + tau[iDim][jDim] = tau[iDim][jDim]*(val_tau_wall/WallShearStress); +} + +void CAvgGrad_Base::GetMeanRateOfStrainMatrix(su2double **S_ij) const +{ + /* --- Calculate the rate of strain tensor, using mean velocity gradients --- */ + + if (nDim == 3){ + S_ij[0][0] = Mean_GradPrimVar[1][0]; + S_ij[1][1] = Mean_GradPrimVar[2][1]; + S_ij[2][2] = Mean_GradPrimVar[3][2]; + S_ij[0][1] = 0.5 * (Mean_GradPrimVar[1][1] + Mean_GradPrimVar[2][0]); + S_ij[0][2] = 0.5 * (Mean_GradPrimVar[1][2] + Mean_GradPrimVar[3][0]); + S_ij[1][2] = 0.5 * (Mean_GradPrimVar[2][2] + Mean_GradPrimVar[3][1]); + S_ij[1][0] = S_ij[0][1]; + S_ij[2][1] = S_ij[1][2]; + S_ij[2][0] = S_ij[0][2]; + } + else { + S_ij[0][0] = Mean_GradPrimVar[1][0]; + S_ij[1][1] = Mean_GradPrimVar[2][1]; + S_ij[2][2] = 0.0; + S_ij[0][1] = 0.5 * (Mean_GradPrimVar[1][1] + Mean_GradPrimVar[2][0]); + S_ij[0][2] = 0.0; + S_ij[1][2] = 0.0; + S_ij[1][0] = S_ij[0][1]; + S_ij[2][1] = S_ij[1][2]; + S_ij[2][0] = S_ij[0][2]; + + } +} + +void CAvgGrad_Base::SetReynoldsStressMatrix(su2double turb_ke){ + + unsigned short iDim, jDim; + su2double **S_ij = new su2double* [3]; + su2double muT = Mean_Eddy_Viscosity; + su2double divVel = 0; + su2double density; + su2double TWO3 = 2.0/3.0; + density = Mean_PrimVar[nDim+2]; + + for (iDim = 0; iDim < 3; iDim++){ + S_ij[iDim] = new su2double [3]; + } + + GetMeanRateOfStrainMatrix(S_ij); + + /* --- Using rate of strain matrix, calculate Reynolds stress tensor --- */ + + for (iDim = 0; iDim < 3; iDim++){ + divVel += S_ij[iDim][iDim]; + } + + for (iDim = 0; iDim < 3; iDim++){ + for (jDim = 0; jDim < 3; jDim++){ + MeanReynoldsStress[iDim][jDim] = TWO3 * turb_ke * delta3[iDim][jDim] + - muT / density * (2 * S_ij[iDim][jDim] - TWO3 * divVel * delta3[iDim][jDim]); + } + } + + for (iDim = 0; iDim < 3; iDim++) + delete [] S_ij[iDim]; + delete [] S_ij; +} + +void CAvgGrad_Base::SetPerturbedRSM(su2double turb_ke, const CConfig* config){ + + unsigned short iDim,jDim; + + /* --- Calculate anisotropic part of Reynolds Stress tensor --- */ + + for (iDim = 0; iDim< 3; iDim++){ + for (jDim = 0; jDim < 3; jDim++){ + A_ij[iDim][jDim] = .5 * MeanReynoldsStress[iDim][jDim] / turb_ke - delta3[iDim][jDim] / 3.0; + Eig_Vec[iDim][jDim] = A_ij[iDim][jDim]; + } + } + + /* --- Get ordered eigenvectors and eigenvalues of A_ij --- */ + + EigenDecomposition(A_ij, Eig_Vec, Eig_Val, 3); + + /* compute convex combination coefficients */ + su2double c1c = Eig_Val[2] - Eig_Val[1]; + su2double c2c = 2.0 * (Eig_Val[1] - Eig_Val[0]); + su2double c3c = 3.0 * Eig_Val[0] + 1.0; + + /* define barycentric traingle corner points */ + Corners[0][0] = 1.0; + Corners[0][1] = 0.0; + Corners[1][0] = 0.0; + Corners[1][1] = 0.0; + Corners[2][0] = 0.5; + Corners[2][1] = 0.866025; + + /* define barycentric coordinates */ + Barycentric_Coord[0] = Corners[0][0] * c1c + Corners[1][0] * c2c + Corners[2][0] * c3c; + Barycentric_Coord[1] = Corners[0][1] * c1c + Corners[1][1] * c2c + Corners[2][1] * c3c; + + if (Eig_Val_Comp == 1) { + /* 1C turbulence */ + New_Coord[0] = Corners[0][0]; + New_Coord[1] = Corners[0][1]; + } + else if (Eig_Val_Comp== 2) { + /* 2C turbulence */ + New_Coord[0] = Corners[1][0]; + New_Coord[1] = Corners[1][1]; + } + else if (Eig_Val_Comp == 3) { + /* 3C turbulence */ + New_Coord[0] = Corners[2][0]; + New_Coord[1] = Corners[2][1]; + } + else { + /* 2C turbulence */ + New_Coord[0] = Corners[1][0]; + New_Coord[1] = Corners[1][1]; + } + + /* calculate perturbed barycentric coordinates */ + Barycentric_Coord[0] = Barycentric_Coord[0] + (uq_delta_b) * (New_Coord[0] - Barycentric_Coord[0]); + Barycentric_Coord[1] = Barycentric_Coord[1] + (uq_delta_b) * (New_Coord[1] - Barycentric_Coord[1]); + + /* rebuild c1c,c2c,c3c based on perturbed barycentric coordinates */ + c3c = Barycentric_Coord[1] / Corners[2][1]; + c1c = Barycentric_Coord[0] - Corners[2][0] * c3c; + c2c = 1 - c1c - c3c; + + /* build new anisotropy eigenvalues */ + Eig_Val[0] = (c3c - 1) / 3.0; + Eig_Val[1] = 0.5 *c2c + Eig_Val[0]; + Eig_Val[2] = c1c + Eig_Val[1]; + + /* permute eigenvectors if required */ + if (uq_permute) { + for (iDim=0; iDim<3; iDim++) { + for (jDim=0; jDim<3; jDim++) { + New_Eig_Vec[iDim][jDim] = Eig_Vec[2-iDim][jDim]; + } + } + } + + else { + for (iDim=0; iDim<3; iDim++) { + for (jDim=0; jDim<3; jDim++) { + New_Eig_Vec[iDim][jDim] = Eig_Vec[iDim][jDim]; + } + } + } + + EigenRecomposition(newA_ij, New_Eig_Vec, Eig_Val, 3); + + /* compute perturbed Reynolds stress matrix; use under-relaxation factor (uq_urlx)*/ + for (iDim = 0; iDim< 3; iDim++){ + for (jDim = 0; jDim < 3; jDim++){ + MeanPerturbedRSM[iDim][jDim] = 2.0 * turb_ke * (newA_ij[iDim][jDim] + 1.0/3.0 * delta3[iDim][jDim]); + MeanPerturbedRSM[iDim][jDim] = MeanReynoldsStress[iDim][jDim] + + uq_urlx*(MeanPerturbedRSM[iDim][jDim] - MeanReynoldsStress[iDim][jDim]); + } + } + +} + + +void CAvgGrad_Base::SetTauJacobian(const su2double *val_Mean_PrimVar, + const su2double val_laminar_viscosity, + const su2double val_eddy_viscosity, + const su2double val_dist_ij, + const su2double *val_normal) { + + /*--- QCR and wall functions are **not** accounted for here ---*/ + + const su2double Density = val_Mean_PrimVar[nDim+2]; + const su2double total_viscosity = val_laminar_viscosity + val_eddy_viscosity; + const su2double xi = total_viscosity/(Density*val_dist_ij); + + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + for (unsigned short jDim = 0; jDim < nDim; jDim++) { + // Jacobian w.r.t. momentum + tau_jacobian_i[iDim][jDim+1] = -xi*(delta[iDim][jDim] + val_normal[iDim]*val_normal[jDim]/3.0); + } + // Jacobian w.r.t. density + tau_jacobian_i[iDim][0] = 0; + for (unsigned short jDim = 0; jDim < nDim; jDim++) { + tau_jacobian_i[iDim][0] -= tau_jacobian_i[iDim][jDim+1]*val_Mean_PrimVar[jDim+1]; + } + // Jacobian w.r.t. energy + tau_jacobian_i[iDim][nDim+1] = 0; + } +} + +void CAvgGrad_Base::SetIncTauJacobian(const su2double val_laminar_viscosity, + const su2double val_eddy_viscosity, + const su2double val_dist_ij, + const su2double *val_normal) { + + const su2double total_viscosity = val_laminar_viscosity + val_eddy_viscosity; + const su2double xi = total_viscosity/val_dist_ij; + + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + tau_jacobian_i[iDim][0] = 0; + for (unsigned short jDim = 0; jDim < nDim; jDim++) { + tau_jacobian_i[iDim][jDim+1] = -xi*(delta[iDim][jDim] + val_normal[iDim]*val_normal[jDim]/3.0); + } + tau_jacobian_i[iDim][nDim+1] = 0; + } +} + +void CAvgGrad_Base::GetViscousProjFlux(const su2double *val_primvar, + const su2double *val_normal) { + + /*--- Primitive variables -> [Temp vel_x vel_y vel_z Pressure] ---*/ + + if (nDim == 2) { + Flux_Tensor[0][0] = 0.0; + Flux_Tensor[1][0] = tau[0][0]; + Flux_Tensor[2][0] = tau[0][1]; + Flux_Tensor[3][0] = tau[0][0]*val_primvar[1] + tau[0][1]*val_primvar[2]+ + heat_flux_vector[0]; + Flux_Tensor[0][1] = 0.0; + Flux_Tensor[1][1] = tau[1][0]; + Flux_Tensor[2][1] = tau[1][1]; + Flux_Tensor[3][1] = tau[1][0]*val_primvar[1] + tau[1][1]*val_primvar[2]+ + heat_flux_vector[1]; + } else { + Flux_Tensor[0][0] = 0.0; + Flux_Tensor[1][0] = tau[0][0]; + Flux_Tensor[2][0] = tau[0][1]; + Flux_Tensor[3][0] = tau[0][2]; + Flux_Tensor[4][0] = tau[0][0]*val_primvar[1] + tau[0][1]*val_primvar[2] + tau[0][2]*val_primvar[3] + + heat_flux_vector[0]; + Flux_Tensor[0][1] = 0.0; + Flux_Tensor[1][1] = tau[1][0]; + Flux_Tensor[2][1] = tau[1][1]; + Flux_Tensor[3][1] = tau[1][2]; + Flux_Tensor[4][1] = tau[1][0]*val_primvar[1] + tau[1][1]*val_primvar[2] + tau[1][2]*val_primvar[3] + + heat_flux_vector[1]; + Flux_Tensor[0][2] = 0.0; + Flux_Tensor[1][2] = tau[2][0]; + Flux_Tensor[2][2] = tau[2][1]; + Flux_Tensor[3][2] = tau[2][2]; + Flux_Tensor[4][2] = tau[2][0]*val_primvar[1] + tau[2][1]*val_primvar[2] + tau[2][2]*val_primvar[3] + + heat_flux_vector[2]; + } + + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + Proj_Flux_Tensor[iVar] = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Proj_Flux_Tensor[iVar] += Flux_Tensor[iVar][iDim] * val_normal[iDim]; + } + +} + +void CAvgGrad_Base::GetViscousProjJacs(const su2double *val_Mean_PrimVar, + const su2double val_dS, + const su2double *val_Proj_Visc_Flux, + su2double **val_Proj_Jac_Tensor_i, + su2double **val_Proj_Jac_Tensor_j) { + + const su2double Density = val_Mean_PrimVar[nDim+2]; + const su2double factor = 0.5/Density; + + if (nDim == 2) { + + val_Proj_Jac_Tensor_i[0][0] = 0.0; + val_Proj_Jac_Tensor_i[0][1] = 0.0; + val_Proj_Jac_Tensor_i[0][2] = 0.0; + val_Proj_Jac_Tensor_i[0][3] = 0.0; + val_Proj_Jac_Tensor_i[1][0] = val_dS*tau_jacobian_i[0][0]; + val_Proj_Jac_Tensor_i[1][1] = val_dS*tau_jacobian_i[0][1]; + val_Proj_Jac_Tensor_i[1][2] = val_dS*tau_jacobian_i[0][2]; + val_Proj_Jac_Tensor_i[1][3] = val_dS*tau_jacobian_i[0][3]; + val_Proj_Jac_Tensor_i[2][0] = val_dS*tau_jacobian_i[1][0]; + val_Proj_Jac_Tensor_i[2][1] = val_dS*tau_jacobian_i[1][1]; + val_Proj_Jac_Tensor_i[2][2] = val_dS*tau_jacobian_i[1][2]; + val_Proj_Jac_Tensor_i[2][3] = val_dS*tau_jacobian_i[1][3]; + const su2double contraction = tau_jacobian_i[0][0]*val_Mean_PrimVar[1] + + tau_jacobian_i[1][0]*val_Mean_PrimVar[2]; + val_Proj_Jac_Tensor_i[3][0] = val_dS*(contraction - heat_flux_jac_i[0]); + val_Proj_Jac_Tensor_i[3][1] = -val_dS*(tau_jacobian_i[0][0] + heat_flux_jac_i[1]); + val_Proj_Jac_Tensor_i[3][2] = -val_dS*(tau_jacobian_i[1][0] + heat_flux_jac_i[2]); + val_Proj_Jac_Tensor_i[3][3] = -val_dS*heat_flux_jac_i[3]; + + for (unsigned short iVar = 0; iVar < nVar; iVar++) + for (unsigned short jVar = 0; jVar < nVar; jVar++) + val_Proj_Jac_Tensor_j[iVar][jVar] = -val_Proj_Jac_Tensor_i[iVar][jVar]; + + const su2double proj_viscousflux_vel= val_Proj_Visc_Flux[1]*val_Mean_PrimVar[1] + + val_Proj_Visc_Flux[2]*val_Mean_PrimVar[2]; + val_Proj_Jac_Tensor_i[3][0] -= factor*proj_viscousflux_vel; + val_Proj_Jac_Tensor_j[3][0] -= factor*proj_viscousflux_vel; + val_Proj_Jac_Tensor_i[3][1] += factor*val_Proj_Visc_Flux[1]; + val_Proj_Jac_Tensor_j[3][1] += factor*val_Proj_Visc_Flux[1]; + val_Proj_Jac_Tensor_i[3][2] += factor*val_Proj_Visc_Flux[2]; + val_Proj_Jac_Tensor_j[3][2] += factor*val_Proj_Visc_Flux[2]; + + + } else { + + val_Proj_Jac_Tensor_i[0][0] = 0.0; + val_Proj_Jac_Tensor_i[0][1] = 0.0; + val_Proj_Jac_Tensor_i[0][2] = 0.0; + val_Proj_Jac_Tensor_i[0][3] = 0.0; + val_Proj_Jac_Tensor_i[0][4] = 0.0; + val_Proj_Jac_Tensor_i[1][0] = val_dS*tau_jacobian_i[0][0]; + val_Proj_Jac_Tensor_i[1][1] = val_dS*tau_jacobian_i[0][1]; + val_Proj_Jac_Tensor_i[1][2] = val_dS*tau_jacobian_i[0][2]; + val_Proj_Jac_Tensor_i[1][3] = val_dS*tau_jacobian_i[0][3]; + val_Proj_Jac_Tensor_i[1][4] = val_dS*tau_jacobian_i[0][4]; + val_Proj_Jac_Tensor_i[2][0] = val_dS*tau_jacobian_i[1][0]; + val_Proj_Jac_Tensor_i[2][1] = val_dS*tau_jacobian_i[1][1]; + val_Proj_Jac_Tensor_i[2][2] = val_dS*tau_jacobian_i[1][2]; + val_Proj_Jac_Tensor_i[2][3] = val_dS*tau_jacobian_i[1][3]; + val_Proj_Jac_Tensor_i[2][4] = val_dS*tau_jacobian_i[1][4]; + val_Proj_Jac_Tensor_i[3][0] = val_dS*tau_jacobian_i[2][0]; + val_Proj_Jac_Tensor_i[3][1] = val_dS*tau_jacobian_i[2][1]; + val_Proj_Jac_Tensor_i[3][2] = val_dS*tau_jacobian_i[2][2]; + val_Proj_Jac_Tensor_i[3][3] = val_dS*tau_jacobian_i[2][3]; + val_Proj_Jac_Tensor_i[3][4] = val_dS*tau_jacobian_i[2][4]; + const su2double contraction = tau_jacobian_i[0][0]*val_Mean_PrimVar[1] + + tau_jacobian_i[1][0]*val_Mean_PrimVar[2] + + tau_jacobian_i[2][0]*val_Mean_PrimVar[3]; + val_Proj_Jac_Tensor_i[4][0] = val_dS*(contraction - heat_flux_jac_i[0]); + val_Proj_Jac_Tensor_i[4][1] = -val_dS*(tau_jacobian_i[0][0] + heat_flux_jac_i[1]); + val_Proj_Jac_Tensor_i[4][2] = -val_dS*(tau_jacobian_i[1][0] + heat_flux_jac_i[2]); + val_Proj_Jac_Tensor_i[4][3] = -val_dS*(tau_jacobian_i[2][0] + heat_flux_jac_i[3]); + val_Proj_Jac_Tensor_i[4][4] = -val_dS*heat_flux_jac_i[4]; + + for (unsigned short iVar = 0; iVar < nVar; iVar++) + for (unsigned short jVar = 0; jVar < nVar; jVar++) + val_Proj_Jac_Tensor_j[iVar][jVar] = -val_Proj_Jac_Tensor_i[iVar][jVar]; + + const su2double proj_viscousflux_vel= val_Proj_Visc_Flux[1]*val_Mean_PrimVar[1] + + val_Proj_Visc_Flux[2]*val_Mean_PrimVar[2] + + val_Proj_Visc_Flux[3]*val_Mean_PrimVar[3]; + val_Proj_Jac_Tensor_i[4][0] -= factor*proj_viscousflux_vel; + val_Proj_Jac_Tensor_j[4][0] -= factor*proj_viscousflux_vel; + val_Proj_Jac_Tensor_i[4][1] += factor*val_Proj_Visc_Flux[1]; + val_Proj_Jac_Tensor_j[4][1] += factor*val_Proj_Visc_Flux[1]; + val_Proj_Jac_Tensor_i[4][2] += factor*val_Proj_Visc_Flux[2]; + val_Proj_Jac_Tensor_j[4][2] += factor*val_Proj_Visc_Flux[2]; + val_Proj_Jac_Tensor_i[4][3] += factor*val_Proj_Visc_Flux[3]; + val_Proj_Jac_Tensor_j[4][3] += factor*val_Proj_Visc_Flux[3]; + + } + +} + +CAvgGrad_Flow::CAvgGrad_Flow(unsigned short val_nDim, + unsigned short val_nVar, + bool val_correct_grad, + const CConfig* config) + : CAvgGrad_Base(val_nDim, val_nVar, val_nDim+3, val_correct_grad, config) { } + +CNumerics::ResidualType<> CAvgGrad_Flow::ComputeResidual(const CConfig* config) { + + AD::StartPreacc(); + AD::SetPreaccIn(V_i, nDim+9); AD::SetPreaccIn(V_j, nDim+9); + AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); + AD::SetPreaccIn(PrimVar_Grad_i, nDim+1, nDim); + AD::SetPreaccIn(PrimVar_Grad_j, nDim+1, nDim); + AD::SetPreaccIn(turb_ke_i); AD::SetPreaccIn(turb_ke_j); + AD::SetPreaccIn(Normal, nDim); + + unsigned short iVar, jVar, iDim; + + /*--- Normalized normal vector ---*/ + + 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; + + PrimVar_i = V_i; + PrimVar_j = V_j; + + for (iVar = 0; iVar < nPrimVar; iVar++) { + Mean_PrimVar[iVar] = 0.5*(PrimVar_i[iVar]+PrimVar_j[iVar]); + } + + + /*--- Compute vector going from iPoint to jPoint ---*/ + + dist_ij_2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; + dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; + } + + /*--- Laminar and Eddy viscosity ---*/ + + Laminar_Viscosity_i = V_i[nDim+5]; Laminar_Viscosity_j = V_j[nDim+5]; + Eddy_Viscosity_i = V_i[nDim+6]; Eddy_Viscosity_j = V_j[nDim+6]; + + /*--- Mean Viscosities and turbulent kinetic energy---*/ + + Mean_Laminar_Viscosity = 0.5*(Laminar_Viscosity_i + Laminar_Viscosity_j); + Mean_Eddy_Viscosity = 0.5*(Eddy_Viscosity_i + Eddy_Viscosity_j); + Mean_turb_ke = 0.5*(turb_ke_i + turb_ke_j); + + /*--- Mean gradient approximation ---*/ + + for (iVar = 0; iVar < nDim+1; iVar++) { + for (iDim = 0; iDim < nDim; iDim++) { + Mean_GradPrimVar[iVar][iDim] = 0.5*(PrimVar_Grad_i[iVar][iDim] + PrimVar_Grad_j[iVar][iDim]); + } + } + + /*--- Projection of the mean gradient in the direction of the edge ---*/ + + if (correct_gradient && dist_ij_2 != 0.0) { + CorrectGradient(Mean_GradPrimVar, PrimVar_i, PrimVar_j, Edge_Vector, + dist_ij_2, nDim+1); + } + + /*--- Wall shear stress values (wall functions) ---*/ + + if (TauWall_i > 0.0 && TauWall_j > 0.0) Mean_TauWall = 0.5*(TauWall_i + TauWall_j); + else if (TauWall_i > 0.0) Mean_TauWall = TauWall_i; + else if (TauWall_j > 0.0) Mean_TauWall = TauWall_j; + else Mean_TauWall = -1.0; + + /* --- If using UQ methodology, set Reynolds Stress tensor and perform perturbation--- */ + + if (using_uq){ + SetReynoldsStressMatrix(Mean_turb_ke); + SetPerturbedRSM(Mean_turb_ke, config); + } + + /*--- Get projected flux tensor (viscous residual) ---*/ + + SetStressTensor(Mean_PrimVar, Mean_GradPrimVar, Mean_turb_ke, + Mean_Laminar_Viscosity, Mean_Eddy_Viscosity); + if (config->GetQCR()) AddQCR(Mean_GradPrimVar); + if (Mean_TauWall > 0) AddTauWall(Normal, Mean_TauWall); + + SetHeatFluxVector(Mean_GradPrimVar, Mean_Laminar_Viscosity, + Mean_Eddy_Viscosity); + + GetViscousProjFlux(Mean_PrimVar, Normal); + + /*--- Compute the implicit part ---*/ + + if (implicit) { + + if (dist_ij_2 == 0.0) { + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_i[iVar][jVar] = 0.0; + Jacobian_j[iVar][jVar] = 0.0; + } + } + } else { + const su2double dist_ij = sqrt(dist_ij_2); + SetTauJacobian(Mean_PrimVar, Mean_Laminar_Viscosity, Mean_Eddy_Viscosity, dist_ij, UnitNormal); + + SetHeatFluxJacobian(Mean_PrimVar, Mean_Laminar_Viscosity, + Mean_Eddy_Viscosity, dist_ij, UnitNormal); + + GetViscousProjJacs(Mean_PrimVar, Area, Proj_Flux_Tensor, Jacobian_i, Jacobian_j); + } + + } + + AD::SetPreaccOut(Proj_Flux_Tensor, nVar); + AD::EndPreacc(); + + return ResidualType<>(Proj_Flux_Tensor, Jacobian_i, Jacobian_j); + +} + +void CAvgGrad_Flow::SetHeatFluxVector(const su2double* const *val_gradprimvar, + const su2double val_laminar_viscosity, + const su2double val_eddy_viscosity) { + + const su2double Cp = (Gamma / Gamma_Minus_One) * Gas_Constant; + const su2double heat_flux_factor = Cp * (val_laminar_viscosity/Prandtl_Lam + val_eddy_viscosity/Prandtl_Turb); + + /*--- Gradient of primitive variables -> [Temp vel_x vel_y vel_z Pressure] ---*/ + + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + heat_flux_vector[iDim] = heat_flux_factor*val_gradprimvar[0][iDim]; + } +} + +void CAvgGrad_Flow::SetHeatFluxJacobian(const su2double *val_Mean_PrimVar, + const su2double val_laminar_viscosity, + const su2double val_eddy_viscosity, + const su2double val_dist_ij, + const su2double *val_normal) { + su2double sqvel = 0.0; + + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + sqvel += val_Mean_PrimVar[iDim+1]*val_Mean_PrimVar[iDim+1]; + } + + const su2double Density = val_Mean_PrimVar[nDim+2]; + const su2double Pressure = val_Mean_PrimVar[nDim+1]; + const su2double phi = Gamma_Minus_One/Density; + + /*--- R times partial derivatives of temp. ---*/ + + const su2double R_dTdu0 = -Pressure/(Density*Density) + 0.5*sqvel*phi; + const su2double R_dTdu1 = -phi*val_Mean_PrimVar[1]; + const su2double R_dTdu2 = -phi*val_Mean_PrimVar[2]; + + const su2double heat_flux_factor = val_laminar_viscosity/Prandtl_Lam + val_eddy_viscosity/Prandtl_Turb; + const su2double cpoR = Gamma/Gamma_Minus_One; // cp over R + const su2double conductivity_over_Rd = cpoR*heat_flux_factor/val_dist_ij; + + heat_flux_jac_i[0] = conductivity_over_Rd * R_dTdu0; + heat_flux_jac_i[1] = conductivity_over_Rd * R_dTdu1; + heat_flux_jac_i[2] = conductivity_over_Rd * R_dTdu2; + + if (nDim == 2) { + + const su2double R_dTdu3 = phi; + heat_flux_jac_i[3] = conductivity_over_Rd * R_dTdu3; + + } else { + + const su2double R_dTdu3 = -phi*val_Mean_PrimVar[3]; + const su2double R_dTdu4 = phi; + heat_flux_jac_i[3] = conductivity_over_Rd * R_dTdu3; + heat_flux_jac_i[4] = conductivity_over_Rd * R_dTdu4; + + } +} + +CAvgGradInc_Flow::CAvgGradInc_Flow(unsigned short val_nDim, + unsigned short val_nVar, + bool val_correct_grad, const CConfig* config) + : CAvgGrad_Base(val_nDim, val_nVar, val_nDim+3, val_correct_grad, config) { + + energy = config->GetEnergy_Equation(); + +} + +CNumerics::ResidualType<> CAvgGradInc_Flow::ComputeResidual(const CConfig* config) { + + AD::StartPreacc(); + AD::SetPreaccIn(V_i, nDim+9); AD::SetPreaccIn(V_j, nDim+9); + AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); + AD::SetPreaccIn(PrimVar_Grad_i, nVar, nDim); + AD::SetPreaccIn(PrimVar_Grad_j, nVar, nDim); + AD::SetPreaccIn(turb_ke_i); AD::SetPreaccIn(turb_ke_j); + AD::SetPreaccIn(Normal, nDim); + + unsigned short iVar, jVar, iDim; + + /*--- Normalized normal vector ---*/ + + 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; + + PrimVar_i = V_i; + PrimVar_j = V_j; + + for (iVar = 0; iVar < nPrimVar; iVar++) { + Mean_PrimVar[iVar] = 0.5*(PrimVar_i[iVar]+PrimVar_j[iVar]); + } + + /*--- Compute vector going from iPoint to jPoint ---*/ + + dist_ij_2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; + dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; + } + + /*--- Density and transport properties ---*/ + + Laminar_Viscosity_i = V_i[nDim+4]; Laminar_Viscosity_j = V_j[nDim+4]; + Eddy_Viscosity_i = V_i[nDim+5]; Eddy_Viscosity_j = V_j[nDim+5]; + Thermal_Conductivity_i = V_i[nDim+6]; Thermal_Conductivity_j = V_j[nDim+6]; + + /*--- Mean transport properties ---*/ + + Mean_Laminar_Viscosity = 0.5*(Laminar_Viscosity_i + Laminar_Viscosity_j); + Mean_Eddy_Viscosity = 0.5*(Eddy_Viscosity_i + Eddy_Viscosity_j); + Mean_turb_ke = 0.5*(turb_ke_i + turb_ke_j); + Mean_Thermal_Conductivity = 0.5*(Thermal_Conductivity_i + Thermal_Conductivity_j); + + /*--- Mean gradient approximation ---*/ + + for (iVar = 0; iVar < nVar; iVar++) + for (iDim = 0; iDim < nDim; iDim++) + Mean_GradPrimVar[iVar][iDim] = 0.5*(PrimVar_Grad_i[iVar][iDim] + PrimVar_Grad_j[iVar][iDim]); + + /*--- Projection of the mean gradient in the direction of the edge ---*/ + + if (correct_gradient && dist_ij_2 != 0.0) { + CorrectGradient(Mean_GradPrimVar, PrimVar_i, PrimVar_j, Edge_Vector, + dist_ij_2, nVar); + } + + /*--- Get projected flux tensor (viscous residual) ---*/ + SetStressTensor(Mean_PrimVar, Mean_GradPrimVar, Mean_turb_ke, Mean_Laminar_Viscosity, Mean_Eddy_Viscosity); + + GetViscousIncProjFlux(Mean_GradPrimVar, Normal, Mean_Thermal_Conductivity); + + /*--- Implicit part ---*/ + + if (implicit) { + + if (dist_ij_2 == 0.0) { + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_i[iVar][jVar] = 0.0; + Jacobian_j[iVar][jVar] = 0.0; + } + } + } else { + + const su2double dist_ij = sqrt(dist_ij_2); + SetIncTauJacobian(Mean_Laminar_Viscosity, Mean_Eddy_Viscosity, dist_ij, UnitNormal); + + GetViscousIncProjJacs(Area, Jacobian_i, Jacobian_j); + + /*--- Include the temperature equation Jacobian. ---*/ + su2double proj_vector_ij = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + proj_vector_ij += (Coord_j[iDim]-Coord_i[iDim])*Normal[iDim]; + } + proj_vector_ij = proj_vector_ij/dist_ij_2; + Jacobian_i[nDim+1][nDim+1] = -Mean_Thermal_Conductivity*proj_vector_ij; + Jacobian_j[nDim+1][nDim+1] = Mean_Thermal_Conductivity*proj_vector_ij; + } + + } + + if (!energy) { + Proj_Flux_Tensor[nDim+1] = 0.0; + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) { + Jacobian_i[iVar][nDim+1] = 0.0; + Jacobian_j[iVar][nDim+1] = 0.0; + + Jacobian_i[nDim+1][iVar] = 0.0; + Jacobian_j[nDim+1][iVar] = 0.0; + } + } + } + + AD::SetPreaccOut(Proj_Flux_Tensor, nVar); + AD::EndPreacc(); + + return ResidualType<>(Proj_Flux_Tensor, Jacobian_i, Jacobian_j); + +} + +void CAvgGradInc_Flow::GetViscousIncProjFlux(const su2double* const *val_gradprimvar, + const su2double *val_normal, + su2double val_thermal_conductivity) { + + /*--- Gradient of primitive variables -> [Pressure vel_x vel_y vel_z Temperature] ---*/ + + if (nDim == 2) { + Flux_Tensor[0][0] = 0.0; + Flux_Tensor[1][0] = tau[0][0]; + Flux_Tensor[2][0] = tau[0][1]; + Flux_Tensor[3][0] = val_thermal_conductivity*val_gradprimvar[nDim+1][0]; + + Flux_Tensor[0][1] = 0.0; + Flux_Tensor[1][1] = tau[1][0]; + Flux_Tensor[2][1] = tau[1][1]; + Flux_Tensor[3][1] = val_thermal_conductivity*val_gradprimvar[nDim+1][1]; + + } else { + + Flux_Tensor[0][0] = 0.0; + Flux_Tensor[1][0] = tau[0][0]; + Flux_Tensor[2][0] = tau[0][1]; + Flux_Tensor[3][0] = tau[0][2]; + Flux_Tensor[4][0] = val_thermal_conductivity*val_gradprimvar[nDim+1][0]; + + Flux_Tensor[0][1] = 0.0; + Flux_Tensor[1][1] = tau[1][0]; + Flux_Tensor[2][1] = tau[1][1]; + Flux_Tensor[3][1] = tau[1][2]; + Flux_Tensor[4][1] = val_thermal_conductivity*val_gradprimvar[nDim+1][1]; + + Flux_Tensor[0][2] = 0.0; + Flux_Tensor[1][2] = tau[2][0]; + Flux_Tensor[2][2] = tau[2][1]; + Flux_Tensor[3][2] = tau[2][2]; + Flux_Tensor[4][2] = val_thermal_conductivity*val_gradprimvar[nDim+1][2]; + + } + + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + Proj_Flux_Tensor[iVar] = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Proj_Flux_Tensor[iVar] += Flux_Tensor[iVar][iDim] * val_normal[iDim]; + } + +} + +void CAvgGradInc_Flow::GetViscousIncProjJacs(su2double val_dS, + su2double **val_Proj_Jac_Tensor_i, + su2double **val_Proj_Jac_Tensor_j) { + if (nDim == 2) { + + val_Proj_Jac_Tensor_i[0][0] = 0.0; + val_Proj_Jac_Tensor_i[0][1] = 0.0; + val_Proj_Jac_Tensor_i[0][2] = 0.0; + val_Proj_Jac_Tensor_i[0][3] = 0.0; + + val_Proj_Jac_Tensor_i[1][0] = val_dS*tau_jacobian_i[0][0]; + val_Proj_Jac_Tensor_i[1][1] = val_dS*tau_jacobian_i[0][1]; + val_Proj_Jac_Tensor_i[1][2] = val_dS*tau_jacobian_i[0][2]; + val_Proj_Jac_Tensor_i[1][3] = val_dS*tau_jacobian_i[0][3]; + + val_Proj_Jac_Tensor_i[2][0] = val_dS*tau_jacobian_i[1][0]; + val_Proj_Jac_Tensor_i[2][1] = val_dS*tau_jacobian_i[1][1]; + val_Proj_Jac_Tensor_i[2][2] = val_dS*tau_jacobian_i[1][2]; + val_Proj_Jac_Tensor_i[2][3] = val_dS*tau_jacobian_i[1][3]; + + val_Proj_Jac_Tensor_i[3][0] = 0.0; + val_Proj_Jac_Tensor_i[3][1] = 0.0; + val_Proj_Jac_Tensor_i[3][2] = 0.0; + val_Proj_Jac_Tensor_i[3][3] = 0.0; + + } else { + + val_Proj_Jac_Tensor_i[0][0] = 0.0; + val_Proj_Jac_Tensor_i[0][1] = 0.0; + val_Proj_Jac_Tensor_i[0][2] = 0.0; + val_Proj_Jac_Tensor_i[0][3] = 0.0; + val_Proj_Jac_Tensor_i[0][4] = 0.0; + + val_Proj_Jac_Tensor_i[1][0] = val_dS*tau_jacobian_i[0][0]; + val_Proj_Jac_Tensor_i[1][1] = val_dS*tau_jacobian_i[0][1]; + val_Proj_Jac_Tensor_i[1][2] = val_dS*tau_jacobian_i[0][2]; + val_Proj_Jac_Tensor_i[1][3] = val_dS*tau_jacobian_i[0][3]; + val_Proj_Jac_Tensor_i[1][4] = val_dS*tau_jacobian_i[0][4]; + + val_Proj_Jac_Tensor_i[2][0] = val_dS*tau_jacobian_i[1][0]; + val_Proj_Jac_Tensor_i[2][1] = val_dS*tau_jacobian_i[1][1]; + val_Proj_Jac_Tensor_i[2][2] = val_dS*tau_jacobian_i[1][2]; + val_Proj_Jac_Tensor_i[2][3] = val_dS*tau_jacobian_i[1][3]; + val_Proj_Jac_Tensor_i[2][4] = val_dS*tau_jacobian_i[1][4]; + + val_Proj_Jac_Tensor_i[3][0] = val_dS*tau_jacobian_i[2][0]; + val_Proj_Jac_Tensor_i[3][1] = val_dS*tau_jacobian_i[2][1]; + val_Proj_Jac_Tensor_i[3][2] = val_dS*tau_jacobian_i[2][2]; + val_Proj_Jac_Tensor_i[3][3] = val_dS*tau_jacobian_i[2][3]; + val_Proj_Jac_Tensor_i[3][4] = val_dS*tau_jacobian_i[2][4]; + + val_Proj_Jac_Tensor_i[4][0] = 0.0; + val_Proj_Jac_Tensor_i[4][1] = 0.0; + val_Proj_Jac_Tensor_i[4][2] = 0.0; + val_Proj_Jac_Tensor_i[4][3] = 0.0; + val_Proj_Jac_Tensor_i[4][4] = 0.0; + + } + + for (unsigned short iVar = 0; iVar < nVar; iVar++) + for (unsigned short jVar = 0; jVar < nVar; jVar++) + val_Proj_Jac_Tensor_j[iVar][jVar] = -val_Proj_Jac_Tensor_i[iVar][jVar]; + +} + +CGeneralAvgGrad_Flow::CGeneralAvgGrad_Flow(unsigned short val_nDim, + unsigned short val_nVar, + bool val_correct_grad, + const CConfig* config) + : CAvgGrad_Base(val_nDim, val_nVar, val_nDim+4, val_correct_grad, config) { } + +void CGeneralAvgGrad_Flow::SetHeatFluxVector(const su2double* const *val_gradprimvar, + const su2double val_laminar_viscosity, + const su2double val_eddy_viscosity, + const su2double val_thermal_conductivity, + const su2double val_heat_capacity_cp) { + + const su2double heat_flux_factor = val_thermal_conductivity + val_heat_capacity_cp*val_eddy_viscosity/Prandtl_Turb; + + /*--- Gradient of primitive variables -> [Temp vel_x vel_y vel_z Pressure] ---*/ + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + heat_flux_vector[iDim] = heat_flux_factor*val_gradprimvar[0][iDim]; + } +} + +void CGeneralAvgGrad_Flow::SetHeatFluxJacobian(const su2double *val_Mean_PrimVar, + const su2double *val_Mean_SecVar, + const su2double val_eddy_viscosity, + const su2double val_thermal_conductivity, + const su2double val_heat_capacity_cp, + const su2double val_dist_ij) { + /* Viscous flux Jacobians for arbitrary equations of state */ + + //order of val_mean_primitives: T, vx, vy, vz, P, rho, ht + //order of secondary:dTdrho_e, dTde_rho + + su2double sqvel = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + sqvel += val_Mean_PrimVar[iDim+1]*val_Mean_PrimVar[iDim+1]; + } + + su2double rho = val_Mean_PrimVar[nDim+2]; + su2double P= val_Mean_PrimVar[nDim+1]; + su2double h= val_Mean_PrimVar[nDim+3]; + su2double dTdrho_e= val_Mean_SecVar[0]; + su2double dTde_rho= val_Mean_SecVar[1]; + + su2double dTdu0= dTdrho_e + dTde_rho*(-(h-P/rho) + sqvel)*(1/rho); + su2double dTdu1= dTde_rho*(-val_Mean_PrimVar[1])*(1/rho); + su2double dTdu2= dTde_rho*(-val_Mean_PrimVar[2])*(1/rho); + + su2double total_conductivity = val_thermal_conductivity + val_heat_capacity_cp*val_eddy_viscosity/Prandtl_Turb; + su2double factor2 = total_conductivity/val_dist_ij; + + heat_flux_jac_i[0] = factor2*dTdu0; + heat_flux_jac_i[1] = factor2*dTdu1; + heat_flux_jac_i[2] = factor2*dTdu2; + + if (nDim == 2) { + + su2double dTdu3= dTde_rho*(1/rho); + heat_flux_jac_i[3] = factor2*dTdu3; + + } else { + + su2double dTdu3= dTde_rho*(-val_Mean_PrimVar[3])*(1/rho); + su2double dTdu4= dTde_rho*(1/rho); + heat_flux_jac_i[3] = factor2*dTdu3; + heat_flux_jac_i[4] = factor2*dTdu4; + + } + +} + +CNumerics::ResidualType<> CGeneralAvgGrad_Flow::ComputeResidual(const CConfig* config) { + + AD::StartPreacc(); + AD::SetPreaccIn(V_i, nDim+9); AD::SetPreaccIn(V_j, nDim+9); + AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); + AD::SetPreaccIn(S_i, 4); AD::SetPreaccIn(S_j, 4); + AD::SetPreaccIn(PrimVar_Grad_i, nDim+1, nDim); + AD::SetPreaccIn(PrimVar_Grad_j, nDim+1, nDim); + AD::SetPreaccIn(turb_ke_i); AD::SetPreaccIn(turb_ke_j); + AD::SetPreaccIn(Normal, nDim); + + unsigned short iVar, jVar, iDim; + + /*--- Normalized normal vector ---*/ + + 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; + + /*--- Mean primitive variables ---*/ + + PrimVar_i = V_i; + PrimVar_j = V_j; + + for (iVar = 0; iVar < nPrimVar; iVar++) { + Mean_PrimVar[iVar] = 0.5*(PrimVar_i[iVar]+PrimVar_j[iVar]); + } + + /*--- Compute vector going from iPoint to jPoint ---*/ + + dist_ij_2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; + dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; + } + + /*--- Laminar and Eddy viscosity ---*/ + + Laminar_Viscosity_i = V_i[nDim+5]; Laminar_Viscosity_j = V_j[nDim+5]; + Eddy_Viscosity_i = V_i[nDim+6]; Eddy_Viscosity_j = V_j[nDim+6]; + Thermal_Conductivity_i = V_i[nDim+7]; Thermal_Conductivity_j = V_j[nDim+7]; + Cp_i = V_i[nDim+8]; Cp_j = V_j[nDim+8]; + + /*--- Mean secondary variables ---*/ + + for (iVar = 0; iVar < 2; iVar++) { + Mean_SecVar[iVar] = 0.5*(S_i[iVar+2]+S_j[iVar+2]); + } + + /*--- Mean Viscosities and turbulent kinetic energy---*/ + + Mean_Laminar_Viscosity = 0.5*(Laminar_Viscosity_i + Laminar_Viscosity_j); + Mean_Eddy_Viscosity = 0.5*(Eddy_Viscosity_i + Eddy_Viscosity_j); + Mean_turb_ke = 0.5*(turb_ke_i + turb_ke_j); + Mean_Thermal_Conductivity = 0.5*(Thermal_Conductivity_i + Thermal_Conductivity_j); + Mean_Cp = 0.5*(Cp_i + Cp_j); + + /*--- Mean gradient approximation ---*/ + + for (iVar = 0; iVar < nDim+1; iVar++) { + for (iDim = 0; iDim < nDim; iDim++) { + Mean_GradPrimVar[iVar][iDim] = 0.5*(PrimVar_Grad_i[iVar][iDim] + PrimVar_Grad_j[iVar][iDim]); + } + } + + /*--- Projection of the mean gradient in the direction of the edge ---*/ + + if (correct_gradient && dist_ij_2 != 0.0) { + CorrectGradient(Mean_GradPrimVar, PrimVar_i, PrimVar_j, Edge_Vector, + dist_ij_2, nDim+1); + } + + /* --- If using UQ methodology, set Reynolds Stress tensor and perform perturbation--- */ + + if (using_uq){ + SetReynoldsStressMatrix(Mean_turb_ke); + SetPerturbedRSM(Mean_turb_ke, config); + } + + /*--- Get projected flux tensor (viscous residual) ---*/ + + SetStressTensor(Mean_PrimVar, Mean_GradPrimVar, Mean_turb_ke, + Mean_Laminar_Viscosity, Mean_Eddy_Viscosity); + + SetHeatFluxVector(Mean_GradPrimVar, Mean_Laminar_Viscosity, + Mean_Eddy_Viscosity, Mean_Thermal_Conductivity, Mean_Cp); + + GetViscousProjFlux(Mean_PrimVar, Normal); + + /*--- Compute the implicit part ---*/ + + if (implicit) { + + if (dist_ij_2 == 0.0) { + for (iVar = 0; iVar < nVar; iVar++) { + for (jVar = 0; jVar < nVar; jVar++) { + Jacobian_i[iVar][jVar] = 0.0; + Jacobian_j[iVar][jVar] = 0.0; + } + } + } else { + const su2double dist_ij = sqrt(dist_ij_2); + + SetTauJacobian(Mean_PrimVar, Mean_Laminar_Viscosity, Mean_Eddy_Viscosity, dist_ij, UnitNormal); + + SetHeatFluxJacobian(Mean_PrimVar, Mean_SecVar, Mean_Eddy_Viscosity, + Mean_Thermal_Conductivity, Mean_Cp, dist_ij); + + GetViscousProjJacs(Mean_PrimVar, Area, Proj_Flux_Tensor, Jacobian_i, Jacobian_j); + } + + } + + AD::SetPreaccOut(Proj_Flux_Tensor, nVar); + AD::EndPreacc(); + + return ResidualType<>(Proj_Flux_Tensor, Jacobian_i, Jacobian_j); + +} diff --git a/SU2_CFD/src/numerics/flow/flow_sources.cpp b/SU2_CFD/src/numerics/flow/flow_sources.cpp new file mode 100644 index 000000000000..1744b9852efa --- /dev/null +++ b/SU2_CFD/src/numerics/flow/flow_sources.cpp @@ -0,0 +1,564 @@ +/*! + * \file flow_sources.cpp + * \brief Implementation of numerics classes for integration + * of source terms in fluid flow problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/numerics/flow/flow_sources.hpp" + +CSourceBase_Flow::CSourceBase_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CNumerics(val_nDim, val_nVar, config) { + residual = new su2double [nVar](); + jacobian = new su2double* [nVar]; + for(unsigned short iVar = 0; iVar < nVar; ++iVar) + jacobian[iVar] = new su2double [nVar](); +} + +CSourceBase_Flow::~CSourceBase_Flow() { + delete [] residual; + if(jacobian) { + for(unsigned short iVar = 0; iVar < nVar; ++iVar) + delete [] jacobian[iVar]; + delete [] jacobian; + } +} + +CSourceAxisymmetric_Flow::CSourceAxisymmetric_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CSourceBase_Flow(val_nDim, val_nVar, config) { + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + +} + +CNumerics::ResidualType<> CSourceAxisymmetric_Flow::ComputeResidual(const CConfig* config) { + + su2double yinv, Pressure_i, Enthalpy_i, Velocity_i, sq_vel; + unsigned short iDim, iVar, jVar; + + bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + + if (Coord_i[1] > EPS) { + + yinv = 1.0/Coord_i[1]; + + sq_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i = U_i[iDim+1] / U_i[0]; + sq_vel += Velocity_i *Velocity_i; + } + + Pressure_i = (Gamma-1.0)*U_i[0]*(U_i[nDim+1]/U_i[0]-0.5*sq_vel); + Enthalpy_i = (U_i[nDim+1] + Pressure_i) / U_i[0]; + + residual[0] = yinv*Volume*U_i[2]; + residual[1] = yinv*Volume*U_i[1]*U_i[2]/U_i[0]; + residual[2] = yinv*Volume*(U_i[2]*U_i[2]/U_i[0]); + residual[3] = yinv*Volume*Enthalpy_i*U_i[2]; + + if (implicit) { + jacobian[0][0] = 0.0; + jacobian[0][1] = 0.0; + jacobian[0][2] = 1.0; + jacobian[0][3] = 0.0; + + jacobian[1][0] = -U_i[1]*U_i[2]/(U_i[0]*U_i[0]); + jacobian[1][1] = U_i[2]/U_i[0]; + jacobian[1][2] = U_i[1]/U_i[0]; + jacobian[1][3] = 0.0; + + jacobian[2][0] = -U_i[2]*U_i[2]/(U_i[0]*U_i[0]); + jacobian[2][1] = 0.0; + jacobian[2][2] = 2*U_i[2]/U_i[0]; + jacobian[2][3] = 0.0; + + jacobian[3][0] = -Gamma*U_i[2]*U_i[3]/(U_i[0]*U_i[0]) + (Gamma-1)*U_i[2]*(U_i[1]*U_i[1]+U_i[2]*U_i[2])/(U_i[0]*U_i[0]*U_i[0]); + jacobian[3][1] = -(Gamma-1)*U_i[2]*U_i[1]/(U_i[0]*U_i[0]); + jacobian[3][2] = Gamma*U_i[3]/U_i[0] - 1/2*(Gamma-1)*( (U_i[1]*U_i[1]+U_i[2]*U_i[2])/(U_i[0]*U_i[0]) + 2*U_i[2]*U_i[2]/(U_i[0]*U_i[0]) ); + jacobian[3][3] = Gamma*U_i[2]/U_i[0]; + + for (iVar=0; iVar < nVar; iVar++) + for (jVar=0; jVar < nVar; jVar++) + jacobian[iVar][jVar] *= yinv*Volume; + + } + + } + + else { + + for (iVar=0; iVar < nVar; iVar++) + residual[iVar] = 0.0; + + if (implicit) { + for (iVar=0; iVar < nVar; iVar++) { + for (jVar=0; jVar < nVar; jVar++) + jacobian[iVar][jVar] = 0.0; + } + } + + } + + return ResidualType<>(residual, jacobian, nullptr); +} + +CSourceIncAxisymmetric_Flow::CSourceIncAxisymmetric_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CSourceBase_Flow(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + energy = config->GetEnergy_Equation(); + viscous = config->GetViscous(); + +} + +CNumerics::ResidualType<> CSourceIncAxisymmetric_Flow::ComputeResidual(const CConfig* config) { + + su2double yinv, Velocity_i[3]; + unsigned short iDim, jDim, iVar, jVar; + + if (Coord_i[1] > EPS) { + + yinv = 1.0/Coord_i[1]; + + /*--- Set primitive variables at points iPoint. ---*/ + + Pressure_i = V_i[0]; + Temp_i = V_i[nDim+1]; + DensityInc_i = V_i[nDim+2]; + BetaInc2_i = V_i[nDim+3]; + Cp_i = V_i[nDim+7]; + Enthalpy_i = Cp_i*Temp_i; + + for (iDim = 0; iDim < nDim; iDim++) + Velocity_i[iDim] = V_i[iDim+1]; + + /*--- Inviscid component of the source term. ---*/ + + residual[0] = yinv*Volume*DensityInc_i*Velocity_i[1]; + residual[1] = yinv*Volume*DensityInc_i*Velocity_i[0]*Velocity_i[1]; + residual[2] = yinv*Volume*DensityInc_i*Velocity_i[1]*Velocity_i[1]; + residual[3] = yinv*Volume*DensityInc_i*Enthalpy_i*Velocity_i[1]; + + if (implicit) { + + jacobian[0][0] = 0.0; + jacobian[0][1] = 0.0; + jacobian[0][2] = 1.0; + jacobian[0][3] = 0.0; + + jacobian[1][0] = 0.0; + jacobian[1][1] = Velocity_i[1]; + jacobian[1][2] = Velocity_i[0]; + jacobian[1][3] = 0.0; + + jacobian[2][0] = 0.0; + jacobian[2][1] = 0.0; + jacobian[2][2] = 2.0*Velocity_i[1]; + jacobian[2][3] = 0.0; + + jacobian[3][0] = 0.0; + jacobian[3][1] = 0.0; + jacobian[3][2] = Enthalpy_i; + jacobian[3][3] = Cp_i*Velocity_i[1]; + + for (iVar=0; iVar < nVar; iVar++) + for (jVar=0; jVar < nVar; jVar++) + jacobian[iVar][jVar] *= yinv*Volume*DensityInc_i; + + } + + /*--- Add the viscous terms if necessary. ---*/ + + if (viscous) { + + Laminar_Viscosity_i = V_i[nDim+4]; + Eddy_Viscosity_i = V_i[nDim+5]; + Thermal_Conductivity_i = V_i[nDim+6]; + + su2double total_viscosity, div_vel; + + total_viscosity = (Laminar_Viscosity_i + Eddy_Viscosity_i); + + /*--- The full stress tensor is needed for variable density ---*/ + + div_vel = 0.0; + for (iDim = 0 ; iDim < nDim; iDim++) + div_vel += PrimVar_Grad_i[iDim+1][iDim]; + + for (iDim = 0 ; iDim < nDim; iDim++) + for (jDim = 0 ; jDim < nDim; jDim++) + tau[iDim][jDim] = (total_viscosity*(PrimVar_Grad_i[jDim+1][iDim] + + PrimVar_Grad_i[iDim+1][jDim] ) + -TWO3*total_viscosity*div_vel*delta[iDim][jDim]); + + /*--- Viscous terms. ---*/ + + residual[0] -= 0.0; + residual[1] -= Volume*(yinv*tau[0][1] - TWO3*AuxVar_Grad_i[0]); + residual[2] -= Volume*(yinv*2.0*total_viscosity*PrimVar_Grad_i[2][1] - + yinv*yinv*2.0*total_viscosity*Velocity_i[1] - + TWO3*AuxVar_Grad_i[1]); + residual[3] -= Volume*yinv*Thermal_Conductivity_i*PrimVar_Grad_i[nDim+1][1]; + + } + + } else { + + for (iVar=0; iVar < nVar; iVar++) + residual[iVar] = 0.0; + + if (implicit) { + for (iVar=0; iVar < nVar; iVar++) { + for (jVar=0; jVar < nVar; jVar++) + jacobian[iVar][jVar] = 0.0; + } + } + + } + + if (!energy) { + residual[nDim+1] = 0.0; + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) { + jacobian[iVar][nDim+1] = 0.0; + jacobian[nDim+1][iVar] = 0.0; + } + } + } + + return ResidualType<>(residual, jacobian, nullptr); +} + +CSourceBodyForce::CSourceBodyForce(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CSourceBase_Flow(val_nDim, val_nVar, config) { + + /*--- Store the pointer to the constant body force vector. ---*/ + + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Body_Force_Vector[iDim] = config->GetBody_Force_Vector()[iDim]; + +} + +CNumerics::ResidualType<> CSourceBodyForce::ComputeResidual(const CConfig* config) { + + unsigned short iDim; + su2double Force_Ref = config->GetForce_Ref(); + + /*--- Zero the continuity contribution ---*/ + + residual[0] = 0.0; + + /*--- Momentum contribution ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + residual[iDim+1] = -Volume * U_i[0] * Body_Force_Vector[iDim] / Force_Ref; + + /*--- Energy contribution ---*/ + + residual[nDim+1] = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + residual[nDim+1] += -Volume * U_i[iDim+1] * Body_Force_Vector[iDim] / Force_Ref; + + return ResidualType<>(residual, jacobian, nullptr); +} + +CSourceIncBodyForce::CSourceIncBodyForce(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CSourceBase_Flow(val_nDim, val_nVar, config) { + + /*--- Store the pointer to the constant body force vector. ---*/ + + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Body_Force_Vector[iDim] = config->GetBody_Force_Vector()[iDim]; + +} + +CNumerics::ResidualType<> CSourceIncBodyForce::ComputeResidual(const CConfig* config) { + + unsigned short iDim; + su2double DensityInc_0 = 0.0; + su2double Force_Ref = config->GetForce_Ref(); + bool variable_density = (config->GetKind_DensityModel() == VARIABLE); + + /*--- Check for variable density. If we have a variable density + problem, we should subtract out the hydrostatic pressure component. ---*/ + + if (variable_density) DensityInc_0 = config->GetDensity_FreeStreamND(); + + /*--- Zero the continuity contribution ---*/ + + residual[0] = 0.0; + + /*--- Momentum contribution. Note that this form assumes we have + subtracted the operating density * gravity, i.e., removed the + hydrostatic pressure component (important for pressure BCs). ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + residual[iDim+1] = -Volume * (DensityInc_i - DensityInc_0) * Body_Force_Vector[iDim] / Force_Ref; + + /*--- Zero the temperature contribution ---*/ + + residual[nDim+1] = 0.0; + + return ResidualType<>(residual, jacobian, nullptr); +} + +CSourceBoussinesq::CSourceBoussinesq(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CSourceBase_Flow(val_nDim, val_nVar, config) { + + /*--- Store the pointer to the constant body force vector. ---*/ + + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Gravity_Vector[iDim] = 0.0; + + /*--- Gravity is downward in y-dir for 2D and downward z-dir for 3D. ---*/ + + Gravity_Vector[nDim-1] = -STANDARD_GRAVITY; + +} + +CNumerics::ResidualType<> CSourceBoussinesq::ComputeResidual(const CConfig* config) { + + unsigned short iDim; + su2double Force_Ref = config->GetForce_Ref(); + su2double T0 = config->GetTemperature_FreeStreamND(); + su2double Beta = config->GetThermal_Expansion_CoeffND(); + + /*--- Zero the continuity contribution ---*/ + + residual[0] = 0.0; + + /*--- Momentum contribution. Note that this form assumes we have + subtracted the operating density * gravity, i.e., removed the + hydrostatic pressure component (important for pressure BCs). ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + residual[iDim+1] = Volume * DensityInc_i * ( Beta * (U_i[nDim+1] - T0)) * Gravity_Vector[iDim] / Force_Ref; + + /*--- Zero the energy contribution ---*/ + + residual[nDim+1] = 0.0; + + return ResidualType<>(residual, jacobian, nullptr); +} + +CSourceGravity::CSourceGravity(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CSourceBase_Flow(val_nDim, val_nVar, config) { } + +CNumerics::ResidualType<> CSourceGravity::ComputeResidual(const CConfig* config) { + + unsigned short iVar; + + for (iVar = 0; iVar < nVar; iVar++) + residual[iVar] = 0.0; + + /*--- Evaluate the source term ---*/ + residual[nDim] = Volume * U_i[0] * STANDARD_GRAVITY; + + return ResidualType<>(residual, jacobian, nullptr); +} + +CSourceRotatingFrame_Flow::CSourceRotatingFrame_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CSourceBase_Flow(val_nDim, val_nVar, config) { + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + +} + +CNumerics::ResidualType<> CSourceRotatingFrame_Flow::ComputeResidual(const CConfig* config) { + + unsigned short iDim, iVar, jVar; + su2double Omega[MAXNDIM] = {0}, Momentum[MAXNDIM] = {0}; + + bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + + /*--- Retrieve the angular velocity vector from config. ---*/ + + for (iDim = 0; iDim < 3; iDim++){ + Omega[iDim] = config->GetRotation_Rate(iDim)/config->GetOmega_Ref(); + } + + /*--- Get the momentum vector at the current node. ---*/ + + for (iDim = 0; iDim < nDim; iDim++) + Momentum[iDim] = U_i[iDim+1]; + + /*--- Calculate rotating frame source term as ( Omega X Rho-U ) ---*/ + + if (nDim == 2) { + residual[0] = 0.0; + residual[1] = (Omega[1]*Momentum[2] - Omega[2]*Momentum[1])*Volume; + residual[2] = (Omega[2]*Momentum[0] - Omega[0]*Momentum[2])*Volume; + residual[3] = 0.0; + } else { + residual[0] = 0.0; + residual[1] = (Omega[1]*Momentum[2] - Omega[2]*Momentum[1])*Volume; + residual[2] = (Omega[2]*Momentum[0] - Omega[0]*Momentum[2])*Volume; + residual[3] = (Omega[0]*Momentum[1] - Omega[1]*Momentum[0])*Volume; + residual[4] = 0.0; + } + + /*--- Calculate the source term Jacobian ---*/ + + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + jacobian[iVar][jVar] = 0.0; + if (nDim == 2) { + jacobian[1][2] = -Omega[2]*Volume; + jacobian[2][1] = Omega[2]*Volume; + } else { + jacobian[1][2] = -Omega[2]*Volume; + jacobian[1][3] = Omega[1]*Volume; + jacobian[2][1] = Omega[2]*Volume; + jacobian[2][3] = -Omega[0]*Volume; + jacobian[3][1] = -Omega[1]*Volume; + jacobian[3][2] = Omega[0]*Volume; + } + } + + return ResidualType<>(residual, jacobian, nullptr); +} + +CSourceIncRotatingFrame_Flow::CSourceIncRotatingFrame_Flow(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CSourceBase_Flow(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + + Gamma = config->GetGamma(); + Gamma_Minus_One = Gamma - 1.0; + + /*--- Retrieve the angular velocity vector from config. ---*/ + for (unsigned short iDim = 0; iDim < 3; iDim++) + Omega[iDim] = config->GetRotation_Rate(iDim)/config->GetOmega_Ref(); + +} + +CNumerics::ResidualType<> CSourceIncRotatingFrame_Flow::ComputeResidual(const CConfig* config) { + + unsigned short iDim, iVar, jVar; + su2double Momentum[MAXNDIM] = {0}, + Velocity_i[MAXNDIM] = {0}; + + /*--- Primitive variables plus momentum at the node (point i) ---*/ + + DensityInc_i = V_i[nDim+2]; + + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Momentum[iDim] = DensityInc_i*Velocity_i[iDim]; + } + + /*--- Calculate rotating frame source term residual as ( Omega X Rho-U ) ---*/ + + if (nDim == 2) { + residual[0] = 0.0; + residual[1] = (Omega[1]*Momentum[2] - Omega[2]*Momentum[1])*Volume; + residual[2] = (Omega[2]*Momentum[0] - Omega[0]*Momentum[2])*Volume; + residual[3] = 0.0; + } else { + residual[0] = 0.0; + residual[1] = (Omega[1]*Momentum[2] - Omega[2]*Momentum[1])*Volume; + residual[2] = (Omega[2]*Momentum[0] - Omega[0]*Momentum[2])*Volume; + residual[3] = (Omega[0]*Momentum[1] - Omega[1]*Momentum[0])*Volume; + residual[4] = 0.0; + } + + /*--- Calculate the source term Jacobian ---*/ + + if (implicit) { + for (iVar = 0; iVar < nVar; iVar++) + for (jVar = 0; jVar < nVar; jVar++) + jacobian[iVar][jVar] = 0.0; + if (nDim == 2) { + jacobian[1][2] = -DensityInc_i*Omega[2]*Volume; + jacobian[2][1] = DensityInc_i*Omega[2]*Volume; + } else { + jacobian[1][2] = -DensityInc_i*Omega[2]*Volume; + jacobian[1][3] = DensityInc_i*Omega[1]*Volume; + jacobian[2][1] = DensityInc_i*Omega[2]*Volume; + jacobian[2][3] = -DensityInc_i*Omega[0]*Volume; + jacobian[3][1] = -DensityInc_i*Omega[1]*Volume; + jacobian[3][2] = DensityInc_i*Omega[0]*Volume; + } + } + + return ResidualType<>(residual, jacobian, nullptr); +} + +CSourceWindGust::CSourceWindGust(unsigned short val_nDim, unsigned short val_nVar, const CConfig* config) : + CSourceBase_Flow(val_nDim, val_nVar, config) { } + +CNumerics::ResidualType<> CSourceWindGust::ComputeResidual(const CConfig* config) { + + su2double u_gust, v_gust, du_gust_dx, du_gust_dy, du_gust_dt, dv_gust_dx, dv_gust_dy, dv_gust_dt; + su2double smx, smy, se, rho, u, v, p; + unsigned short GustDir = config->GetGust_Dir(); //Gust direction + + u_gust = WindGust_i[0]; + v_gust = WindGust_i[1]; + + if (GustDir == X_DIR) { + du_gust_dx = WindGustDer_i[0]; + du_gust_dy = WindGustDer_i[1]; + du_gust_dt = WindGustDer_i[2]; + dv_gust_dx = 0.0; + dv_gust_dy = 0.0; + dv_gust_dt = 0.0; + } else { + du_gust_dx = 0.0; + du_gust_dy = 0.0; + du_gust_dt = 0.0; + dv_gust_dx = WindGustDer_i[0]; + dv_gust_dy = WindGustDer_i[1]; + dv_gust_dt = WindGustDer_i[2]; + + } + + /*--- Primitive variables at point i ---*/ + u = V_i[1]; + v = V_i[2]; + p = V_i[nDim+1]; + rho = V_i[nDim+2]; + + /*--- Source terms ---*/ + smx = rho*(du_gust_dt + (u+u_gust)*du_gust_dx + (v+v_gust)*du_gust_dy); + smy = rho*(dv_gust_dt + (u+u_gust)*dv_gust_dx + (v+v_gust)*dv_gust_dy); + se = u*smx + v*smy + p*(du_gust_dx + dv_gust_dy); + + if (nDim == 2) { + residual[0] = 0.0; + residual[1] = smx*Volume; + residual[2] = smy*Volume; + residual[3] = se*Volume; + } else { + SU2_MPI::Error("You should only be in the gust source term in two dimensions", CURRENT_FUNCTION); + } + + /*--- For now the source term Jacobian is just set to zero ---*/ + //bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + + return ResidualType<>(residual, jacobian, nullptr); +} diff --git a/SU2_CFD/src/numerics_direct_heat.cpp b/SU2_CFD/src/numerics/heat.cpp similarity index 88% rename from SU2_CFD/src/numerics_direct_heat.cpp rename to SU2_CFD/src/numerics/heat.cpp index 7f5e7596e299..acfbd2cfe38f 100644 --- a/SU2_CFD/src/numerics_direct_heat.cpp +++ b/SU2_CFD/src/numerics/heat.cpp @@ -1,12 +1,12 @@ /*! - * \file numerics_direct_heat.cpp - * \brief This file contains all the convective term discretization. + * \file heat.cpp + * \brief Implementation of numerics classes for heat transfer. * \author F. Palacios, T. Economon * \version 7.0.1 "Blackbird" * * 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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -25,65 +25,12 @@ * License along with SU2. If not, see . */ +#include "../../include/numerics/heat.hpp" -#include "../include/numerics_structure.hpp" -#include +CCentSca_Heat::CCentSca_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : + CNumerics(val_nDim, val_nVar, config) { -CUpwSca_Heat::CUpwSca_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); - /* 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(); - - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - - Laminar_Viscosity_i = config->GetViscosity_FreeStreamND(); - Laminar_Viscosity_j = config->GetViscosity_FreeStreamND(); -} - -CUpwSca_Heat::~CUpwSca_Heat(void) { - - delete [] Velocity_i; - delete [] Velocity_j; - -} - -void CUpwSca_Heat::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - q_ij = 0.0; - - AD::StartPreacc(); - AD::SetPreaccIn(V_i, nDim+1); AD::SetPreaccIn(V_j, nDim+1); - AD::SetPreaccIn(Temp_i); AD::SetPreaccIn(Temp_j); - AD::SetPreaccIn(Normal, nDim); - if (dynamic_grid) { - AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); - } - - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity_j[iDim] = V_j[iDim+1]; - q_ij += 0.5*(Velocity_i[iDim]+Velocity_j[iDim])*Normal[iDim]; - } - - a0 = 0.5*(q_ij+fabs(q_ij)); - a1 = 0.5*(q_ij-fabs(q_ij)); - val_residual[0] = a0*Temp_i+a1*Temp_j; - - if (implicit) { - val_Jacobian_i[0][0] = a0; - val_Jacobian_j[0][0] = a1; - } - - AD::SetPreaccOut(val_residual[0]); - AD::EndPreacc(); - -} - -CCentSca_Heat::CCentSca_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); + implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); /* 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(); @@ -103,7 +50,8 @@ CCentSca_Heat::~CCentSca_Heat(void) { } -void CCentSca_Heat::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { +void CCentSca_Heat::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, CConfig *config) { AD::StartPreacc(); AD::SetPreaccIn(V_i, nDim+3); AD::SetPreaccIn(V_j, nDim+3); @@ -167,9 +115,64 @@ void CCentSca_Heat::ComputeResidual(su2double *val_residual, su2double **val_Jac } -CAvgGrad_Heat::CAvgGrad_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { +CUpwSca_Heat::CUpwSca_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : + CNumerics(val_nDim, val_nVar, config) { - implicit = (config->GetKind_TimeIntScheme_Heat() == EULER_IMPLICIT); + implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); + /* 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(); + + Velocity_i = new su2double [nDim]; + Velocity_j = new su2double [nDim]; + + Laminar_Viscosity_i = config->GetViscosity_FreeStreamND(); + Laminar_Viscosity_j = config->GetViscosity_FreeStreamND(); +} + +CUpwSca_Heat::~CUpwSca_Heat(void) { + + delete [] Velocity_i; + delete [] Velocity_j; + +} + +void CUpwSca_Heat::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, CConfig *config) { + + q_ij = 0.0; + + AD::StartPreacc(); + AD::SetPreaccIn(V_i, nDim+1); AD::SetPreaccIn(V_j, nDim+1); + AD::SetPreaccIn(Temp_i); AD::SetPreaccIn(Temp_j); + AD::SetPreaccIn(Normal, nDim); + if (dynamic_grid) { + AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); + } + + for (iDim = 0; iDim < nDim; iDim++) { + Velocity_i[iDim] = V_i[iDim+1]; + Velocity_j[iDim] = V_j[iDim+1]; + q_ij += 0.5*(Velocity_i[iDim]+Velocity_j[iDim])*Normal[iDim]; + } + + a0 = 0.5*(q_ij+fabs(q_ij)); + a1 = 0.5*(q_ij-fabs(q_ij)); + val_residual[0] = a0*Temp_i+a1*Temp_j; + + if (implicit) { + val_Jacobian_i[0][0] = a0; + val_Jacobian_j[0][0] = a1; + } + + AD::SetPreaccOut(val_residual[0]); + AD::EndPreacc(); + +} + +CAvgGrad_Heat::CAvgGrad_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : + CNumerics(val_nDim, val_nVar, config) { + + implicit = (config->GetKind_TimeIntScheme_Heat() == EULER_IMPLICIT); Edge_Vector = new su2double [nDim]; Proj_Mean_GradHeatVar_Normal = new su2double [nVar]; @@ -191,7 +194,8 @@ CAvgGrad_Heat::~CAvgGrad_Heat(void) { } -void CAvgGrad_Heat::ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config) { +void CAvgGrad_Heat::ComputeResidual(su2double *val_residual, su2double **Jacobian_i, + su2double **Jacobian_j, CConfig *config) { AD::StartPreacc(); AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); @@ -237,11 +241,10 @@ void CAvgGrad_Heat::ComputeResidual(su2double *val_residual, su2double **Jacobia } +CAvgGradCorrected_Heat::CAvgGradCorrected_Heat(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : + CNumerics(val_nDim, val_nVar, config) { -CAvgGradCorrected_Heat::CAvgGradCorrected_Heat(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Heat() == EULER_IMPLICIT); + implicit = (config->GetKind_TimeIntScheme_Heat() == EULER_IMPLICIT); Edge_Vector = new su2double [nDim]; Proj_Mean_GradHeatVar_Edge = new su2double [nVar]; @@ -265,7 +268,8 @@ CAvgGradCorrected_Heat::~CAvgGradCorrected_Heat(void) { } -void CAvgGradCorrected_Heat::ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config) { +void CAvgGradCorrected_Heat::ComputeResidual(su2double *val_residual, su2double **Jacobian_i, + su2double **Jacobian_j, CConfig *config) { AD::StartPreacc(); AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); diff --git a/SU2_CFD/src/numerics/template.cpp b/SU2_CFD/src/numerics/template.cpp new file mode 100644 index 000000000000..f21b2162206b --- /dev/null +++ b/SU2_CFD/src/numerics/template.cpp @@ -0,0 +1,70 @@ +/*! + * \file template.cpp + * \brief Empty implementation of numerics templates, see .hpp file. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../include/numerics/template.hpp" + +CConvective_Template::CConvective_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : + CNumerics(val_nDim, val_nVar, config) { + +} + +CConvective_Template::~CConvective_Template(void) { + +} + +void CConvective_Template::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, CConfig *config) { + +} + +CViscous_Template::CViscous_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : + CNumerics(val_nDim, val_nVar, config) { + +} + +CViscous_Template::~CViscous_Template(void) { + +} + +void CViscous_Template::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, CConfig *config) { + +} + + +CSource_Template::CSource_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : + CNumerics(val_nDim, val_nVar, config) { + +} + +CSource_Template::~CSource_Template(void) { + +} + +void CSource_Template::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) { + +} diff --git a/SU2_CFD/src/numerics_direct_transition.cpp b/SU2_CFD/src/numerics/transition.cpp similarity index 97% rename from SU2_CFD/src/numerics_direct_transition.cpp rename to SU2_CFD/src/numerics/transition.cpp index 6a55fe1f248a..efbb12ab7053 100644 --- a/SU2_CFD/src/numerics_direct_transition.cpp +++ b/SU2_CFD/src/numerics/transition.cpp @@ -1,12 +1,12 @@ /*! - * \file numerics_direct_transition.cpp - * \brief This file contains all the convective term discretization. - * \author A. Aranake + * \file transition.cpp + * \brief Implementation of numerics classes for transition problems. + * \author F. Palacios, T. Economon * \version 7.0.1 "Blackbird" * * 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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -25,21 +25,19 @@ * License along with SU2. If not, see . */ - -#include "../include/numerics_structure.hpp" -#include +#include "../../include/numerics/transition.hpp" CUpwLin_TransLM::CUpwLin_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - + implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - + Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; - + Velocity_i = new su2double [nDim]; Velocity_j = new su2double [nDim]; - + } CUpwLin_TransLM::~CUpwLin_TransLM(void) { @@ -48,18 +46,18 @@ CUpwLin_TransLM::~CUpwLin_TransLM(void) { } void CUpwLin_TransLM::ComputeResidual (su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - + + Density_i = U_i[0]; Density_j = U_j[0]; - + q_ij = 0; for (iDim = 0; iDim < nDim; iDim++) { Velocity_i[iDim] = U_i[iDim+1]/Density_i; Velocity_j[iDim] = U_j[iDim+1]/Density_j; q_ij += 0.5*(Velocity_i[iDim]+Velocity_j[iDim])*Normal[iDim]; } - + a0 = 0.5*(q_ij+fabs(q_ij)); a1 = 0.5*(q_ij-fabs(q_ij)); val_residual[0] = a0*TransVar_i[0]+a1*TransVar_j[0]; @@ -67,8 +65,8 @@ void CUpwLin_TransLM::ComputeResidual (su2double *val_residual, su2double **val_ // cout << "Velicity x: " << Velocity_i[0] << ", " << Velocity_j[0] << endl; // cout << "Velicity y: " << Velocity_i[1] << ", " << Velocity_j[1] << endl; // cout << "val_resid: " << val_residual[0] << ", " << val_residual[1] << endl; - - + + if (implicit) { val_Jacobian_i[0][0] = a0; val_Jacobian_i[1][1] = a0; @@ -77,12 +75,12 @@ void CUpwLin_TransLM::ComputeResidual (su2double *val_residual, su2double **val_ CUpwSca_TransLM::CUpwSca_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - + implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); - + Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; - + Velocity_i = new su2double [nDim]; Velocity_j = new su2double [nDim]; } @@ -93,43 +91,43 @@ CUpwSca_TransLM::~CUpwSca_TransLM(void) { } void CUpwSca_TransLM::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - + q_ij = 0; for (iDim = 0; iDim < nDim; iDim++) { q_ij += 0.5*(U_i[iDim]+U_j[iDim])*Normal[iDim]; } - + a0 = 0.5*(q_ij+fabs(q_ij)); a1 = 0.5*(q_ij-fabs(q_ij)); val_residual[0] = a0*TransVar_i[0]+a1*TransVar_j[0]; val_residual[1] = a0*TransVar_i[1]+a1*TransVar_j[1]; - + if (implicit) { val_Jacobian_i[0][0] = a0; val_Jacobian_j[0][0] = a1; val_Jacobian_i[1][1] = a0; val_Jacobian_j[1][1] = a1; - + /*--- Zero out off-diagonal terms just in case ---*/ val_Jacobian_i[0][1] = 0; val_Jacobian_j[0][1] = 0; val_Jacobian_i[1][0] = 0; val_Jacobian_j[1][0] = 0; } - + } CAvgGrad_TransLM::CAvgGrad_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { unsigned short iVar; - + implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; - + sigma = 2./3.; - + Edge_Vector = new su2double [nDim]; Proj_Mean_GradTransVar_Kappa = new su2double [nVar]; Proj_Mean_GradTransVar_Edge = new su2double [nVar]; @@ -139,9 +137,9 @@ CAvgGrad_TransLM::CAvgGrad_TransLM(unsigned short val_nDim, unsigned short val_n } CAvgGrad_TransLM::~CAvgGrad_TransLM(void) { - + unsigned short iVar; - + delete [] Edge_Vector; delete [] Proj_Mean_GradTransVar_Kappa; delete [] Proj_Mean_GradTransVar_Edge; @@ -151,7 +149,7 @@ CAvgGrad_TransLM::~CAvgGrad_TransLM(void) { } void CAvgGrad_TransLM::ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config) { - /*--- This section is commented out on 04/11/2016 + /*--- This section is commented out on 04/11/2016 after review of the static scan ---*/ // su2double *Density_Grad_i = new su2double[nDim]; // su2double *Density_Grad_j = new su2double[nDim]; @@ -159,18 +157,18 @@ void CAvgGrad_TransLM::ComputeResidual(su2double *val_residual, su2double **Jaco // su2double *Conservative_Grad_j = new su2double[nDim]; // su2double *Primitive_Grad_i = new su2double[nDim]; // su2double *Primitive_Grad_j = new su2double[nDim]; - // + // // /*--- Intermediate values for combining viscosities ---*/ // su2double Inter_Viscosity_i, Inter_Viscosity_j, REth_Viscosity_i, REth_Viscosity_j, Inter_Viscosity_Mean, REth_Viscosity_Mean; - // + // // /*--- Model constants---*/ // su2double sigmaf = 1.0; // su2double sigma_thetat = 2.0; - // + // // /*--- Get density ---*/ // Density_i = U_i[0]; // Density_j = U_j[0]; - // + // // /*--- Construct combinations of viscosity ---*/ // Inter_Viscosity_i = (Laminar_Viscosity_i+Eddy_Viscosity_i/sigmaf); // Inter_Viscosity_j = (Laminar_Viscosity_j+Eddy_Viscosity_j/sigmaf); @@ -178,7 +176,7 @@ void CAvgGrad_TransLM::ComputeResidual(su2double *val_residual, su2double **Jaco // REth_Viscosity_i = sigma_thetat*(Laminar_Viscosity_i+Eddy_Viscosity_i); // REth_Viscosity_j = sigma_thetat*(Laminar_Viscosity_j+Eddy_Viscosity_j); // REth_Viscosity_Mean = 0.5*(REth_Viscosity_i+REth_Viscosity_j); - // + // ///*--- Compute vector going from iPoint to jPoint ---*/ //dist_ij_2 = 0; proj_vector_ij = 0; //for (iDim = 0; iDim < nDim; iDim++) { @@ -187,13 +185,13 @@ void CAvgGrad_TransLM::ComputeResidual(su2double *val_residual, su2double **Jaco // proj_vector_ij += Edge_Vector[iDim]*Normal[iDim]; //} //proj_vector_ij = proj_vector_ij/dist_ij_2; // to normalize vectors - // + // ///*--- Mean gradient approximation ---*/ //for (iVar = 0; iVar < nVar; iVar++) { // Proj_Mean_GradTransVar_Kappa[iVar] = 0.0; // // Proj_Mean_GradTransVar_Edge[iVar] = 0.0; // for (iDim = 0; iDim < nDim; iDim++) { - // + // // /* -- Compute primitive grad using chain rule -- */ // Density_Grad_i[iDim] = ConsVar_Grad_i[0][iDim]; // Density_Grad_j[iDim] = ConsVar_Grad_j[0][iDim]; @@ -201,16 +199,16 @@ void CAvgGrad_TransLM::ComputeResidual(su2double *val_residual, su2double **Jaco // Conservative_Grad_j[iDim] = TransVar_Grad_j[iVar][iDim]; // Primitive_Grad_i[iDim] = 1./Density_i*(Conservative_Grad_i[iDim]-TransVar_i[iVar]*Density_Grad_i[iDim]); // Primitive_Grad_j[iDim] = 1./Density_j*(Conservative_Grad_j[iDim]-TransVar_j[iVar]*Density_Grad_j[iDim]); - // + // // /*--- Compute the average primitive gradient and project it in the normal direction ---*/ // Mean_GradTransVar[iVar][iDim] = 0.5*(Primitive_Grad_i[iDim] + Primitive_Grad_j[iDim]); // Proj_Mean_GradTransVar_Kappa[iVar] += Mean_GradTransVar[iVar][iDim]*Normal[iDim]; // } //} - // + // //val_residual[0] = Inter_Viscosity_Mean*Proj_Mean_GradTransVar_Kappa[0]; //val_residual[1] = REth_Viscosity_Mean*Proj_Mean_GradTransVar_Kappa[1]; - // + // ///*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/ //if (implicit) { // Jacobian_i[0][0] = (0.5*Proj_Mean_GradTransVar_Kappa[0]-Inter_Viscosity_Mean*proj_vector_ij); @@ -218,7 +216,7 @@ void CAvgGrad_TransLM::ComputeResidual(su2double *val_residual, su2double **Jaco // Jacobian_i[1][1] = (0.5*Proj_Mean_GradTransVar_Kappa[1]-REth_Viscosity_Mean*proj_vector_ij); // Jacobian_j[1][1] = (0.5*Proj_Mean_GradTransVar_Kappa[1]+REth_Viscosity_Mean*proj_vector_ij); //} - // + // // /*--- Free locally allocated memory. For efficiency, these arrays // should really be allocated/deallocated in the constructor/destructor. ---*/ // delete [] Density_Grad_i; @@ -227,22 +225,22 @@ void CAvgGrad_TransLM::ComputeResidual(su2double *val_residual, su2double **Jaco // delete [] Conservative_Grad_j; // delete [] Primitive_Grad_i; // delete [] Primitive_Grad_j; - // + // } CAvgGradCorrected_TransLM::CAvgGradCorrected_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - + unsigned short iVar; - + implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - + Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; - + sigma = 2./3.; - + Edge_Vector = new su2double [nDim]; Proj_Mean_GradTurbVar_Kappa = new su2double [nVar]; Proj_Mean_GradTurbVar_Edge = new su2double [nVar]; @@ -253,9 +251,9 @@ CAvgGradCorrected_TransLM::CAvgGradCorrected_TransLM(unsigned short val_nDim, un } CAvgGradCorrected_TransLM::~CAvgGradCorrected_TransLM(void) { - + unsigned short iVar; - + delete [] Edge_Vector; delete [] Proj_Mean_GradTurbVar_Kappa; delete [] Proj_Mean_GradTurbVar_Edge; @@ -266,7 +264,7 @@ CAvgGradCorrected_TransLM::~CAvgGradCorrected_TransLM(void) { } void CAvgGradCorrected_TransLM::ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config) { - + // switch (config->GetKind_Turb_Model()) { // case SA : // /*--- Compute mean effective viscosity ---*/ @@ -312,10 +310,10 @@ void CAvgGradCorrected_TransLM::ComputeResidual(su2double *val_residual, su2doub CSourcePieceWise_TransLM::CSourcePieceWise_TransLM(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - + Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; - + /*--- Spalart-Allmaras closure constants ---*/ cv1_3 = pow(7.1,3.0); k2 = pow(0.41,2.0); @@ -325,7 +323,7 @@ CSourcePieceWise_TransLM::CSourcePieceWise_TransLM(unsigned short val_nDim, unsi sigma = 2./3.; cb2 = 0.622; cw1 = cb1/k2+(1+cb2)/sigma; - + /*-- Gamma-theta closure constants --*/ c_e1 = 1.0; c_a1 = 2.0; @@ -335,22 +333,23 @@ CSourcePieceWise_TransLM::CSourcePieceWise_TransLM(unsigned short val_nDim, unsi s1 = 2.0; c_theta = 0.03; sigmat = 2.0; - + /*-- Correlation constants --*/ flen_global = 12.0; alpha_global = 0.85; - + /*-- For debugging -AA --*/ debugme = 0; } CSourcePieceWise_TransLM::~CSourcePieceWise_TransLM(void) { } -void CSourcePieceWise_TransLM::ComputeResidual_TransLM(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config, su2double &gamma_sep) { +void CSourcePieceWise_TransLM::ComputeResidual_TransLM(su2double *val_residual, su2double **val_Jacobian_i, + su2double **val_Jacobian_j, CConfig *config, su2double &gamma_sep) { //************************************************// // Please do not delete //SU2_CPP2C comment lines // //************************************************// - + //SU2_CPP2C START CSourcePieceWise_TransLM::ComputeResidual_TransLM //SU2_CPP2C CALL_LIST START //SU2_CPP2C INVARS *TransVar_i @@ -358,30 +357,30 @@ void CSourcePieceWise_TransLM::ComputeResidual_TransLM(su2double *val_residual, //SU2_CPP2C VARS DOUBLE *U_i **PrimVar_Grad_i Laminar_Viscosity_i Eddy_Viscosity_i dist_i //SU2_CPP2C VARS DOUBLE SCALAR c_a1 c_e1 c_a2 c_e2 c_theta alpha_global flen_global //SU2_CPP2C CALL_LIST END - + //SU2_CPP2C DEFINE nDim - + //SU2_CPP2C DECL_LIST START //SU2_CPP2C VARS DOUBLE SCALAR Vorticity //SU2_CPP2C DECL_LIST END - + /*-- Local intermediate variables --*/ su2double rey_tc, flen, re_v, strain, f_onset1, f_onset2, f_onset3, f_onset, f_turb, tu; - + su2double prod, des; su2double f_lambda, re_theta = 0.0, re_theta_lim, r_t; su2double Velocity_Mag = 0.0, du_ds, theta, lambda, time_scale, var1, f_theta; su2double f_reattach; su2double dU_dx, dU_dy, dU_dz = 0.0; - + //SU2_CPP2C COMMENT START su2double val_residuald[2], TransVar_id[2]; - + //SU2_CPP2C COMMENT END - + val_residual[0] = 0.0; val_residual[1] = 0.0; - + //SU2_CPP2C COMMENT START implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); if (implicit) { @@ -391,7 +390,7 @@ void CSourcePieceWise_TransLM::ComputeResidual_TransLM(su2double *val_residual, val_Jacobian_i[1][1] = 0.0; } //SU2_CPP2C COMMENT END - + /* -- These lines included just so Tapenade doesn't complain --*/ // rey = 0.0; // mach = 0.0; @@ -402,73 +401,73 @@ void CSourcePieceWise_TransLM::ComputeResidual_TransLM(su2double *val_residual, // mach = config->GetMach(); tu = config->GetTurbulenceIntensity_FreeStream(); //SU2_CPP2C COMMENT END - + /*--- Compute vorticity and strain (TODO: Update for 3D) ---*/ Vorticity = fabs(PrimVar_Grad_i[1][1]-PrimVar_Grad_i[2][0]); - + /*-- Strain = sqrt(2*Sij*Sij) --*/ strain = sqrt(2.*( PrimVar_Grad_i[1][0]*PrimVar_Grad_i[1][0] + 0.5*pow(PrimVar_Grad_i[1][1]+PrimVar_Grad_i[2][0],2) + PrimVar_Grad_i[2][1]*PrimVar_Grad_i[2][1] )); - + /*-- Note: no incompressible for now! --*/ - + if (dist_i > 0.0) { // Only operate away from wall - + /*-- Intermittency eq.: --*/ - + rey_tc = (4.45*pow(tu,3) - 5.7*pow(tu,2) + 1.37*tu + 0.585)*TransVar_i[1]; flen = 0.171*pow(tu,2) - 0.0083*tu + 0.0306; - + re_v = U_i[0]*pow(dist_i,2.)/Laminar_Viscosity_i*strain; // Vorticity Reynolds number - + /*-- f_onset controls transition onset location --*/ r_t = Eddy_Viscosity_i/Laminar_Viscosity_i; f_onset1 = re_v / (2.193*rey_tc); f_onset2 = min(max(f_onset1, pow(f_onset1,4.)), 2.); f_onset3 = max(1. - pow(0.4*r_t,3),0.); f_onset = max(f_onset2 - f_onset3, 0.); - + f_turb = exp(-pow(0.25*r_t,4)); // Medida eq. 10 - + prod = flen*c_a1*U_i[0]*strain*sqrt(f_onset*TransVar_i[0]); prod = prod*(1. - c_e1*TransVar_i[0]); - + des = c_a2*U_i[0]*Vorticity*TransVar_i[0]*f_turb; des = des*(c_e2*TransVar_i[0] - 1.); - + val_residual[0] = prod - des; - + /*-- REtheta eq: --*/ if (nDim==2) { Velocity_Mag = sqrt(U_i[1]*U_i[1]+U_i[2]*U_i[2])/U_i[0]; } else if (nDim==3) { Velocity_Mag = sqrt(U_i[1]*U_i[1]+U_i[2]*U_i[2]+U_i[3]*U_i[3])/U_i[0]; } - + /*-- Gradient of velocity magnitude ---*/ dU_dx = 0.5*Velocity_Mag*( 2*U_i[1]/U_i[0]*PrimVar_Grad_i[1][0] +2*U_i[2]/U_i[0]*PrimVar_Grad_i[2][0]); if (nDim==3) dU_dx += 0.5*Velocity_Mag*( 2*U_i[3]/U_i[0]*PrimVar_Grad_i[3][0]); - + dU_dy = 0.5*Velocity_Mag*( 2*U_i[1]/U_i[0]*PrimVar_Grad_i[1][1] +2*U_i[2]/U_i[0]*PrimVar_Grad_i[2][1]); if (nDim==3) dU_dy += 0.5*Velocity_Mag*( 2*U_i[3]/U_i[0]*PrimVar_Grad_i[3][1]); - + if (nDim==3) dU_dz = 0.5*Velocity_Mag*( 2*U_i[1]/U_i[0]*PrimVar_Grad_i[1][2] +2*U_i[2]/U_i[0]*PrimVar_Grad_i[2][2] +2*U_i[3]/U_i[0]*PrimVar_Grad_i[3][2]); - + du_ds = U_i[1]/(U_i[0]*Velocity_Mag) * dU_dx + // Streamwise velocity derivative U_i[2]/(U_i[0]*Velocity_Mag) * dU_dy; if (nDim==3) du_ds += U_i[3]/(U_i[0]*Velocity_Mag) * dU_dz; - + re_theta_lim = 20.; - + /*-- Fixed-point iterations to solve REth correlation --*/ f_lambda = 1.; for (int iter=0; iter<10; iter++) { @@ -478,12 +477,12 @@ void CSourcePieceWise_TransLM::ComputeResidual_TransLM(su2double *val_residual, re_theta = 331.5 * f_lambda*pow(tu-0.5658,-0.671); } re_theta = max(re_theta, re_theta_lim); - + theta = re_theta * Laminar_Viscosity_i / (U_i[0]*Velocity_Mag); - + lambda = U_i[0]*theta*theta*du_ds / Laminar_Viscosity_i; lambda = min(max(-0.1, lambda),0.1); - + if (lambda<=0.0) { f_lambda = 1. - (-12.986*lambda - 123.66*lambda*lambda - 405.689*lambda*lambda*lambda)*exp(-pow(2./3*tu,1.5)); @@ -491,25 +490,25 @@ void CSourcePieceWise_TransLM::ComputeResidual_TransLM(su2double *val_residual, f_lambda = 1. + 0.275*(1.-exp(-35.*lambda))*exp(-2.*tu); } } - + /*-- Calculate blending function f_theta --*/ time_scale = 500.0*Laminar_Viscosity_i/(U_i[0]*Velocity_Mag*Velocity_Mag); - + // Deactivated the f_wake parameter... //theta_bl = TransVar_i[1]*Laminar_Viscosity_i / (U_i[0]*Velocity_Mag); //delta_bl = 7.5*theta_bl; //delta = 50.0*Vorticity*dist_i/Velocity_Mag*delta_bl + 1e-20; // //f_wake = 1.; - + var1 = (TransVar_i[0]-1./c_e2)/(1.0-1./c_e2); var1 = 1. - pow(var1,2); - + //f_theta = min(max(f_wake*exp(-pow(dist_i/delta,4)), var1),1.0); f_theta = min(var1,1.0); - + val_residual[1] = c_theta*U_i[0]/time_scale * (1.-f_theta) * (re_theta-TransVar_i[1]); - + //SU2_CPP2C COMMENT START cout << "val_res0: " << val_residual[0] << endl; cout << "val_res1: " << val_residual[1] << endl; @@ -532,23 +531,23 @@ void CSourcePieceWise_TransLM::ComputeResidual_TransLM(su2double *val_residual, cout << "r_t: " << r_t << endl; cout << "rey_tc: " << rey_tc << endl; cout << "re_theta: " << re_theta << endl; - + /*-- Calculate term for separation correction --*/ f_reattach = exp(-pow(0.05*r_t,4)); gamma_sep = s1*max(0., re_v/(3.235*rey_tc)-1.)*f_reattach; gamma_sep = min(gamma_sep,2.0)*f_theta; - + /*--- Implicit part ---*/ TransVar_id[0] = 1.0; TransVar_id[1] = 0.0; CSourcePieceWise_TransLM__ComputeResidual_TransLM_d(TransVar_i, TransVar_id, val_residual, val_residuald, config); val_Jacobian_i[0][0] = val_residuald[0]; val_Jacobian_i[1][0] = val_residuald[1]; - + TransVar_id[0] = 0.0; TransVar_id[1] = 1.0; CSourcePieceWise_TransLM__ComputeResidual_TransLM_d(TransVar_i, TransVar_id, val_residual, val_residuald, config); val_Jacobian_i[0][1] = val_residuald[0]; val_Jacobian_i[1][1] = val_residuald[1]; - + //SU2_CPP2C COMMENT END } //SU2_CPP2C END CSourcePieceWise_TransLM::ComputeResidual_TransLM @@ -729,7 +728,7 @@ void CSourcePieceWise_TransLM::CSourcePieceWise_TransLM__ComputeResidual_TransLM // //f_wake = 1.; var1d = TransVar_id[0]/(1.0-1./c_e2); - var1 = (TransVar_i[0]-1./c_e2)/(1.0-1./c_e2); + var1 = (TransVar_i[0]-1./c_e2)/(1.0-1./c_e2); result1 = pow(var1, 2.0); result1d = 2.0*var1d*pow(var1, 1.0); var1d = -result1d; @@ -747,5 +746,4 @@ void CSourcePieceWise_TransLM::CSourcePieceWise_TransLM__ComputeResidual_TransLM TransVar_i[1]); } else *val_residuald = 0.0; - } diff --git a/SU2_CFD/src/numerics/turbulent/turb_convection.cpp b/SU2_CFD/src/numerics/turbulent/turb_convection.cpp new file mode 100644 index 000000000000..09016b3b475c --- /dev/null +++ b/SU2_CFD/src/numerics/turbulent/turb_convection.cpp @@ -0,0 +1,145 @@ +/*! + * \file turb_convection.cpp + * \brief Implementation of numerics classes to compute convective + * fluxes in turbulence problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/numerics/turbulent/turb_convection.hpp" + +CUpwScalar::CUpwScalar(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig* config) : + CNumerics(val_nDim, val_nVar, config), + implicit(config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT), + incompressible(config->GetKind_Regime() == INCOMPRESSIBLE), + dynamic_grid(config->GetDynamic_Grid()) +{ + Flux = new su2double [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CUpwScalar::~CUpwScalar(void) { + + delete [] Flux; + if (Jacobian_i != nullptr) { + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Jacobian_i; + delete [] Jacobian_j; + } +} + +CNumerics::ResidualType<> CUpwScalar::ComputeResidual(const CConfig* config) { + + unsigned short iDim; + + AD::StartPreacc(); + AD::SetPreaccIn(Normal, nDim); + AD::SetPreaccIn(TurbVar_i, nVar); AD::SetPreaccIn(TurbVar_j, nVar); + if (dynamic_grid) { + AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); + } + + ExtraADPreaccIn(); + + Density_i = V_i[nDim+2]; + Density_j = V_j[nDim+2]; + + q_ij = 0.0; + if (dynamic_grid) { + for (iDim = 0; iDim < nDim; iDim++) { + su2double Velocity_i = V_i[iDim+1] - GridVel_i[iDim]; + su2double Velocity_j = V_j[iDim+1] - GridVel_j[iDim]; + q_ij += 0.5*(Velocity_i+Velocity_j)*Normal[iDim]; + } + } + else { + for (iDim = 0; iDim < nDim; iDim++) { + q_ij += 0.5*(V_i[iDim+1]+V_j[iDim+1])*Normal[iDim]; + } + } + + a0 = 0.5*(q_ij+fabs(q_ij)); + a1 = 0.5*(q_ij-fabs(q_ij)); + + FinishResidualCalc(config); + + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} + +CUpwSca_TurbSA::CUpwSca_TurbSA(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig* config) : + CUpwScalar(val_nDim, val_nVar, config) { } + +void CUpwSca_TurbSA::ExtraADPreaccIn() { + AD::SetPreaccIn(V_i, nDim+1); + AD::SetPreaccIn(V_j, nDim+1); +} + +void CUpwSca_TurbSA::FinishResidualCalc(const CConfig* config) { + + Flux[0] = a0*TurbVar_i[0]+a1*TurbVar_j[0]; + + if (implicit) { + Jacobian_i[0][0] = a0; + Jacobian_j[0][0] = a1; + } +} + +CUpwSca_TurbSST::CUpwSca_TurbSST(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig* config) : + CUpwScalar(val_nDim, val_nVar, config) { } + +void CUpwSca_TurbSST::ExtraADPreaccIn() { + AD::SetPreaccIn(V_i, nDim+3); + AD::SetPreaccIn(V_j, nDim+3); +} + +void CUpwSca_TurbSST::FinishResidualCalc(const CConfig* config) { + + Flux[0] = a0*Density_i*TurbVar_i[0]+a1*Density_j*TurbVar_j[0]; + Flux[1] = a0*Density_i*TurbVar_i[1]+a1*Density_j*TurbVar_j[1]; + + if (implicit) { + Jacobian_i[0][0] = a0; Jacobian_i[0][1] = 0.0; + Jacobian_i[1][0] = 0.0; Jacobian_i[1][1] = a0; + + Jacobian_j[0][0] = a1; Jacobian_j[0][1] = 0.0; + Jacobian_j[1][0] = 0.0; Jacobian_j[1][1] = a1; + } +} diff --git a/SU2_CFD/src/numerics/turbulent/turb_diffusion.cpp b/SU2_CFD/src/numerics/turbulent/turb_diffusion.cpp new file mode 100644 index 000000000000..c6f67ce28fc0 --- /dev/null +++ b/SU2_CFD/src/numerics/turbulent/turb_diffusion.cpp @@ -0,0 +1,257 @@ +/*! + * \file turb_diffusion.cpp + * \brief Implementation of numerics classes to compute viscous + * fluxes in turbulence problems. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/numerics/turbulent/turb_diffusion.hpp" + +CAvgGrad_Scalar::CAvgGrad_Scalar(unsigned short val_nDim, + unsigned short val_nVar, + bool correct_grad, + const CConfig* config) : + CNumerics(val_nDim, val_nVar, config), + correct_gradient(correct_grad), + implicit(config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT), + incompressible(config->GetKind_Regime() == INCOMPRESSIBLE) +{ + Proj_Mean_GradTurbVar_Normal = new su2double [nVar]; + Proj_Mean_GradTurbVar_Edge = new su2double [nVar]; + Proj_Mean_GradTurbVar = new su2double [nVar]; + + Flux = new su2double [nVar]; + Jacobian_i = new su2double* [nVar]; + Jacobian_j = new su2double* [nVar]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + Jacobian_i[iVar] = new su2double [nVar]; + Jacobian_j[iVar] = new su2double [nVar]; + } +} + +CAvgGrad_Scalar::~CAvgGrad_Scalar(void) { + + delete [] Proj_Mean_GradTurbVar_Normal; + delete [] Proj_Mean_GradTurbVar_Edge; + delete [] Proj_Mean_GradTurbVar; + + delete [] Flux; + if (Jacobian_i != nullptr) { + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + delete [] Jacobian_i[iVar]; + delete [] Jacobian_j[iVar]; + } + delete [] Jacobian_i; + delete [] Jacobian_j; + } +} + +CNumerics::ResidualType<> CAvgGrad_Scalar::ComputeResidual(const CConfig* config) { + + unsigned short iVar, iDim; + + AD::StartPreacc(); + AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); + AD::SetPreaccIn(Normal, nDim); + AD::SetPreaccIn(TurbVar_Grad_i, nVar, nDim); + AD::SetPreaccIn(TurbVar_Grad_j, nVar, nDim); + if (correct_gradient) { + AD::SetPreaccIn(TurbVar_i, nVar); AD::SetPreaccIn(TurbVar_j ,nVar); + } + ExtraADPreaccIn(); + + if (incompressible) { + AD::SetPreaccIn(V_i, nDim+6); AD::SetPreaccIn(V_j, nDim+6); + + Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+4]; Laminar_Viscosity_j = V_j[nDim+4]; + Eddy_Viscosity_i = V_i[nDim+5]; Eddy_Viscosity_j = V_j[nDim+5]; + } + else { + AD::SetPreaccIn(V_i, nDim+7); AD::SetPreaccIn(V_j, nDim+7); + + Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+5]; Laminar_Viscosity_j = V_j[nDim+5]; + Eddy_Viscosity_i = V_i[nDim+6]; Eddy_Viscosity_j = V_j[nDim+6]; + } + + /*--- Compute vector going from iPoint to jPoint ---*/ + + dist_ij_2 = 0; proj_vector_ij = 0; + for (iDim = 0; iDim < nDim; iDim++) { + Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; + dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; + proj_vector_ij += Edge_Vector[iDim]*Normal[iDim]; + } + if (dist_ij_2 == 0.0) proj_vector_ij = 0.0; + else proj_vector_ij = proj_vector_ij/dist_ij_2; + + /*--- Mean gradient approximation ---*/ + for (iVar = 0; iVar < nVar; iVar++) { + Proj_Mean_GradTurbVar_Normal[iVar] = 0.0; + Proj_Mean_GradTurbVar_Edge[iVar] = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + su2double Mean_GradTurbVar = 0.5*(TurbVar_Grad_i[iVar][iDim] + + TurbVar_Grad_j[iVar][iDim]); + + Proj_Mean_GradTurbVar_Normal[iVar] += Mean_GradTurbVar * Normal[iDim]; + + if (correct_gradient) + Proj_Mean_GradTurbVar_Edge[iVar] += Mean_GradTurbVar * Edge_Vector[iDim]; + } + Proj_Mean_GradTurbVar[iVar] = Proj_Mean_GradTurbVar_Normal[iVar]; + if (correct_gradient) { + Proj_Mean_GradTurbVar[iVar] -= Proj_Mean_GradTurbVar_Edge[iVar]*proj_vector_ij - + (TurbVar_j[iVar]-TurbVar_i[iVar])*proj_vector_ij; + } + } + + FinishResidualCalc(config); + + AD::SetPreaccOut(Flux, nVar); + AD::EndPreacc(); + + return ResidualType<>(Flux, Jacobian_i, Jacobian_j); + +} + +CAvgGrad_TurbSA::CAvgGrad_TurbSA(unsigned short val_nDim, unsigned short val_nVar, + bool correct_grad, const CConfig* config) : + CAvgGrad_Scalar(val_nDim, val_nVar, correct_grad, config) { } + +void CAvgGrad_TurbSA::ExtraADPreaccIn() { } + +void CAvgGrad_TurbSA::FinishResidualCalc(const CConfig* config) { + + /*--- Compute mean effective viscosity ---*/ + + su2double nu_i = Laminar_Viscosity_i/Density_i; + su2double nu_j = Laminar_Viscosity_j/Density_j; + su2double nu_e = 0.5*(nu_i+nu_j+TurbVar_i[0]+TurbVar_j[0]); + + Flux[0] = nu_e*Proj_Mean_GradTurbVar[0]/sigma; + + /*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/ + + if (implicit) { + Jacobian_i[0][0] = (0.5*Proj_Mean_GradTurbVar[0]-nu_e*proj_vector_ij)/sigma; + Jacobian_j[0][0] = (0.5*Proj_Mean_GradTurbVar[0]+nu_e*proj_vector_ij)/sigma; + } + +} + +CAvgGrad_TurbSA_Neg::CAvgGrad_TurbSA_Neg(unsigned short val_nDim, + unsigned short val_nVar, + bool correct_grad, + const CConfig* config) : + CAvgGrad_Scalar(val_nDim, val_nVar, correct_grad, config) { } + +void CAvgGrad_TurbSA_Neg::ExtraADPreaccIn() { } + +void CAvgGrad_TurbSA_Neg::FinishResidualCalc(const CConfig* config) { + + /*--- Compute mean effective viscosity ---*/ + + su2double nu_i = Laminar_Viscosity_i/Density_i; + su2double nu_j = Laminar_Viscosity_j/Density_j; + + su2double nu_ij = 0.5*(nu_i+nu_j); + su2double nu_tilde_ij = 0.5*(TurbVar_i[0]+TurbVar_j[0]); + + su2double nu_e; + + if (nu_tilde_ij > 0.0) { + nu_e = nu_ij + nu_tilde_ij; + } + else { + su2double Xi = nu_tilde_ij/nu_ij; + su2double fn = (cn1 + Xi*Xi*Xi)/(cn1 - Xi*Xi*Xi); + nu_e = nu_ij + fn*nu_tilde_ij; + } + + Flux[0] = nu_e*Proj_Mean_GradTurbVar_Normal[0]/sigma; + + /*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/ + + if (implicit) { + Jacobian_i[0][0] = (0.5*Proj_Mean_GradTurbVar[0]-nu_e*proj_vector_ij)/sigma; + Jacobian_j[0][0] = (0.5*Proj_Mean_GradTurbVar[0]+nu_e*proj_vector_ij)/sigma; + } + +} + +CAvgGrad_TurbSST::CAvgGrad_TurbSST(unsigned short val_nDim, + unsigned short val_nVar, + const su2double *constants, + bool correct_grad, + const CConfig* config) : + CAvgGrad_Scalar(val_nDim, val_nVar, correct_grad, config), + sigma_k1(constants[0]), + sigma_k2(constants[1]), + sigma_om1(constants[2]), + sigma_om2(constants[3]) { + +} + +void CAvgGrad_TurbSST::ExtraADPreaccIn() { + AD::SetPreaccIn(F1_i); AD::SetPreaccIn(F1_j); +} + +void CAvgGrad_TurbSST::FinishResidualCalc(const CConfig* config) { + + su2double sigma_kine_i, sigma_kine_j, sigma_omega_i, sigma_omega_j; + su2double diff_i_kine, diff_i_omega, diff_j_kine, diff_j_omega; + + /*--- Compute the blended constant for the viscous terms ---*/ + sigma_kine_i = F1_i*sigma_k1 + (1.0 - F1_i)*sigma_k2; + sigma_kine_j = F1_j*sigma_k1 + (1.0 - F1_j)*sigma_k2; + sigma_omega_i = F1_i*sigma_om1 + (1.0 - F1_i)*sigma_om2; + sigma_omega_j = F1_j*sigma_om1 + (1.0 - F1_j)*sigma_om2; + + /*--- Compute mean effective viscosity ---*/ + diff_i_kine = Laminar_Viscosity_i + sigma_kine_i*Eddy_Viscosity_i; + diff_j_kine = Laminar_Viscosity_j + sigma_kine_j*Eddy_Viscosity_j; + diff_i_omega = Laminar_Viscosity_i + sigma_omega_i*Eddy_Viscosity_i; + diff_j_omega = Laminar_Viscosity_j + sigma_omega_j*Eddy_Viscosity_j; + + su2double diff_kine = 0.5*(diff_i_kine + diff_j_kine); + su2double diff_omega = 0.5*(diff_i_omega + diff_j_omega); + + Flux[0] = diff_kine*Proj_Mean_GradTurbVar[0]; + Flux[1] = diff_omega*Proj_Mean_GradTurbVar[1]; + + /*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/ + if (implicit) { + su2double proj_on_rho = proj_vector_ij/Density_i; + + Jacobian_i[0][0] = -diff_kine*proj_on_rho; Jacobian_i[0][1] = 0.0; + Jacobian_i[1][0] = 0.0; Jacobian_i[1][1] = -diff_omega*proj_on_rho; + + proj_on_rho = proj_vector_ij/Density_j; + + Jacobian_j[0][0] = diff_kine*proj_on_rho; Jacobian_j[0][1] = 0.0; + Jacobian_j[1][0] = 0.0; Jacobian_j[1][1] = diff_omega*proj_on_rho; + } + +} diff --git a/SU2_CFD/src/numerics/turbulent/turb_sources.cpp b/SU2_CFD/src/numerics/turbulent/turb_sources.cpp new file mode 100644 index 000000000000..1210caecef87 --- /dev/null +++ b/SU2_CFD/src/numerics/turbulent/turb_sources.cpp @@ -0,0 +1,1105 @@ +/*! + * \file turb_sources.cpp + * \brief Implementation of numerics classes for integration of + * turbulence source-terms. + * \author F. Palacios, T. Economon + * \version 7.0.1 "Blackbird" + * + * SU2 Project Website: https://su2code.github.io + * + * The SU2 Project is maintained by the SU2 Foundation + * (http://su2foundation.org) + * + * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) + * + * SU2 is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * SU2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with SU2. If not, see . + */ + +#include "../../../include/numerics/turbulent/turb_sources.hpp" + +CSourceBase_TurbSA::CSourceBase_TurbSA(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig* config) : + CNumerics(val_nDim, val_nVar, config), + incompressible(config->GetKind_Regime() == INCOMPRESSIBLE), + rotating_frame(config->GetRotating_Frame()) +{ + /*--- Spalart-Allmaras closure constants ---*/ + + cv1_3 = pow(7.1, 3.0); + k2 = pow(0.41, 2.0); + cb1 = 0.1355; + cw2 = 0.3; + ct3 = 1.2; + ct4 = 0.5; + cw3_6 = pow(2.0, 6.0); + sigma = 2./3.; + cb2 = 0.622; + cb2_sigma = cb2/sigma; + cw1 = cb1/k2+(1.0+cb2)/sigma; + + /*--- Setup the Jacobian pointer, we need to return su2double** but + * we know the Jacobian is 1x1 so we use this "trick" to avoid + * having to dynamically allocate. ---*/ + + Jacobian_i = &Jacobian_Buffer; + +} + +CSourcePieceWise_TurbSA::CSourcePieceWise_TurbSA(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig* config) : + CSourceBase_TurbSA(val_nDim, val_nVar, config) { + + transition = (config->GetKind_Trans_Model() == BC); +} + +CNumerics::ResidualType<> CSourcePieceWise_TurbSA::ComputeResidual(const CConfig* config) { + +// AD::StartPreacc(); +// AD::SetPreaccIn(V_i, nDim+6); +// AD::SetPreaccIn(Vorticity_i, nDim); +// AD::SetPreaccIn(StrainMag_i); +// AD::SetPreaccIn(TurbVar_i[0]); +// AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); +// AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); + +// BC Transition Model variables + su2double vmag, rey, re_theta, re_theta_t, re_v; + su2double tu , nu_cr, nu_t, nu_BC, chi_1, chi_2, term1, term2, term_exponential; + + if (incompressible) { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+4]; + } + else { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+5]; + } + + Residual = 0.0; + Production = 0.0; + Destruction = 0.0; + CrossProduction = 0.0; + Jacobian_i[0] = 0.0; + + gamma_BC = 0.0; + vmag = 0.0; + tu = config->GetTurbulenceIntensity_FreeStream(); + rey = config->GetReynolds(); + + if (nDim==2) { + vmag = sqrt(V_i[1]*V_i[1]+V_i[2]*V_i[2]); + } + else { + vmag = sqrt(V_i[1]*V_i[1]+V_i[2]*V_i[2]+V_i[3]*V_i[3]); + } + + /*--- Evaluate Omega ---*/ + + Omega = sqrt(Vorticity_i[0]*Vorticity_i[0] + Vorticity_i[1]*Vorticity_i[1] + Vorticity_i[2]*Vorticity_i[2]); + + /*--- Rotational correction term ---*/ + + if (rotating_frame) { Omega += 2.0*min(0.0, StrainMag_i-Omega); } + + if (dist_i > 1e-10) { + + /*--- Production term ---*/ + + dist_i_2 = dist_i*dist_i; + nu = Laminar_Viscosity_i/Density_i; + Ji = TurbVar_i[0]/nu; + Ji_2 = Ji*Ji; + Ji_3 = Ji_2*Ji; + fv1 = Ji_3/(Ji_3+cv1_3); + fv2 = 1.0 - Ji/(1.0+Ji*fv1); + ft2 = ct3*exp(-ct4*Ji_2); + S = Omega; + inv_k2_d2 = 1.0/(k2*dist_i_2); + + Shat = S + TurbVar_i[0]*fv2*inv_k2_d2; + Shat = max(Shat, 1.0e-10); + inv_Shat = 1.0/Shat; + +// Original SA model +// Production = cb1*(1.0-ft2)*Shat*TurbVar_i[0]*Volume; + + if (transition) { + +// BC model constants + chi_1 = 0.002; + chi_2 = 5.0; + + nu_t = (TurbVar_i[0]*fv1); //S-A variable + nu_cr = chi_2/rey; + nu_BC = (nu_t)/(vmag*dist_i); + + re_v = ((Density_i*pow(dist_i,2.))/(Laminar_Viscosity_i))*Omega; + re_theta = re_v/2.193; + re_theta_t = (803.73 * pow((tu + 0.6067),-1.027)); //MENTER correlation + //re_theta_t = 163.0 + exp(6.91-tu); //ABU-GHANNAM & SHAW correlation + + term1 = sqrt(max(re_theta-re_theta_t,0.)/(chi_1*re_theta_t)); + term2 = sqrt(max(nu_BC-nu_cr,0.)/(nu_cr)); + term_exponential = (term1 + term2); + gamma_BC = 1.0 - exp(-term_exponential); + + Production = gamma_BC*cb1*Shat*TurbVar_i[0]*Volume; + } + else { + Production = cb1*Shat*TurbVar_i[0]*Volume; + } + + /*--- Destruction term ---*/ + + r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); + g = r + cw2*(pow(r,6.0)-r); + g_6 = pow(g,6.0); + glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); + fw = g*glim; + +// Original SA model +// Destruction = (cw1*fw-cb1*ft2/k2)*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; + + Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; + + /*--- Diffusion term ---*/ + + norm2_Grad = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; + + CrossProduction = cb2_sigma*norm2_Grad*Volume; + + Residual = Production - Destruction + CrossProduction; + + /*--- Implicit part, production term ---*/ + + dfv1 = 3.0*Ji_2*cv1_3/(nu*pow(Ji_3+cv1_3,2.)); + dfv2 = -(1/nu-Ji_2*dfv1)/pow(1.+Ji*fv1,2.); + if ( Shat <= 1.0e-10 ) dShat = 0.0; + else dShat = (fv2+TurbVar_i[0]*dfv2)*inv_k2_d2; + + if (transition) { + Jacobian_i[0] += gamma_BC*cb1*(TurbVar_i[0]*dShat+Shat)*Volume; + } + else { + Jacobian_i[0] += cb1*(TurbVar_i[0]*dShat+Shat)*Volume; + } + + /*--- Implicit part, destruction term ---*/ + + dr = (Shat-TurbVar_i[0]*dShat)*inv_Shat*inv_Shat*inv_k2_d2; + if (r == 10.0) dr = 0.0; + dg = dr*(1.+cw2*(6.0*pow(r,5.0)-1.0)); + dfw = dg*glim*(1.-g_6/(g_6+cw3_6)); + Jacobian_i[0] -= cw1*(dfw*TurbVar_i[0] + 2.0*fw)*TurbVar_i[0]/dist_i_2*Volume; + + } + +// AD::SetPreaccOut(Residual); +// AD::EndPreacc(); + + return ResidualType<>(&Residual, &Jacobian_i, nullptr); + +} + +CSourcePieceWise_TurbSA_COMP::CSourcePieceWise_TurbSA_COMP(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig* config) : + CSourceBase_TurbSA(val_nDim, val_nVar, config), c5(3.5) { } + +CNumerics::ResidualType<> CSourcePieceWise_TurbSA_COMP::ComputeResidual(const CConfig* config) { + + // AD::StartPreacc(); + // AD::SetPreaccIn(V_i, nDim+6); + // AD::SetPreaccIn(Vorticity_i, nDim); + // AD::SetPreaccIn(StrainMag_i); + // AD::SetPreaccIn(TurbVar_i[0]); + // AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); + // AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); + + if (incompressible) { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+4]; + } + else { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+5]; + } + + Residual = 0.0; + Production = 0.0; + Destruction = 0.0; + CrossProduction = 0.0; + Jacobian_i[0] = 0.0; + + /*--- Evaluate Omega ---*/ + + Omega = sqrt(Vorticity_i[0]*Vorticity_i[0] + Vorticity_i[1]*Vorticity_i[1] + Vorticity_i[2]*Vorticity_i[2]); + + /*--- Rotational correction term ---*/ + + if (rotating_frame) { Omega += 2.0*min(0.0, StrainMag_i-Omega); } + + if (dist_i > 1e-10) { + + /*--- Production term ---*/ + + dist_i_2 = dist_i*dist_i; + nu = Laminar_Viscosity_i/Density_i; + Ji = TurbVar_i[0]/nu; + Ji_2 = Ji*Ji; + Ji_3 = Ji_2*Ji; + fv1 = Ji_3/(Ji_3+cv1_3); + fv2 = 1.0 - Ji/(1.0+Ji*fv1); + ft2 = ct3*exp(-ct4*Ji_2); + S = Omega; + inv_k2_d2 = 1.0/(k2*dist_i_2); + + Shat = S + TurbVar_i[0]*fv2*inv_k2_d2; + Shat = max(Shat, 1.0e-10); + inv_Shat = 1.0/Shat; + + /*--- Production term ---*/; + + Production = cb1*Shat*TurbVar_i[0]*Volume; + + /*--- Destruction term ---*/ + + r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); + g = r + cw2*(pow(r,6.0)-r); + g_6 = pow(g,6.0); + glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); + fw = g*glim; + + Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; + + /*--- Diffusion term ---*/ + + norm2_Grad = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; + + CrossProduction = cb2_sigma*norm2_Grad*Volume; + + Residual = Production - Destruction + CrossProduction; + + /*--- Compressibility Correction term ---*/ + Pressure_i = V_i[nDim+1]; + SoundSpeed_i = sqrt(Pressure_i*Gamma/Density_i); + aux_cc=0; + for(iDim=0;iDim(&Residual, &Jacobian_i, nullptr); + +} + +CSourcePieceWise_TurbSA_E::CSourcePieceWise_TurbSA_E(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig* config) : + CSourceBase_TurbSA(val_nDim, val_nVar, config) { } + +CNumerics::ResidualType<> CSourcePieceWise_TurbSA_E::ComputeResidual(const CConfig* config) { + + unsigned short iDim, jDim; + + // AD::StartPreacc(); + // AD::SetPreaccIn(V_i, nDim+6); + // AD::SetPreaccIn(Vorticity_i, nDim); + // AD::SetPreaccIn(StrainMag_i); + // AD::SetPreaccIn(TurbVar_i[0]); + // AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); + // AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); + + if (incompressible) { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+4]; + } + else { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+5]; + } + + Residual = 0.0; + Production = 0.0; + Destruction = 0.0; + CrossProduction = 0.0; + Jacobian_i[0] = 0.0; + + /* + From NASA Turbulence model site. http://turbmodels.larc.nasa.gov/spalart.html + This form was developed primarily to improve the near-wall numerical behavior of the model (i.e., the goal was to improve the convergence behavior). The reference is: + Edwards, J. R. and Chandra, S. "Comparison of Eddy Viscosity-Transport Turbulence Models for Three-Dimensional, Shock-Separated Flowfields," AIAA Journal, Vol. 34, No. 4, 1996, pp. 756-763. + In this modificaton Omega is replaced by Strain Rate + */ + + /*--- Evaluate Omega, here Omega is the Strain Rate ---*/ + + Sbar = 0.0; + for(iDim=0;iDim 1e-10) { + + /*--- Production term ---*/ + + dist_i_2 = dist_i*dist_i; + nu = Laminar_Viscosity_i/Density_i; + Ji = TurbVar_i[0]/nu; + Ji_2 = Ji*Ji; + Ji_3 = Ji_2*Ji; + fv1 = Ji_3/(Ji_3+cv1_3); + fv2 = 1.0 - Ji/(1.0+Ji*fv1); + ft2 = ct3*exp(-ct4*Ji_2); + S = Omega; + inv_k2_d2 = 1.0/(k2*dist_i_2); + + //Shat = S + TurbVar_i[0]*fv2*inv_k2_d2; + Shat = max(S*((1.0/max(Ji,1.0e-16))+fv1),1.0e-16); + + Shat = max(Shat, 1.0e-10); + inv_Shat = 1.0/Shat; + + /*--- Production term ---*/; + + Production = cb1*Shat*TurbVar_i[0]*Volume; + + /*--- Destruction term ---*/ + + r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); + r=tanh(r)/tanh(1.0); + + g = r + cw2*(pow(r,6.0)-r); + g_6 = pow(g,6.0); + glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); + fw = g*glim; + + Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; + + /*--- Diffusion term ---*/ + + norm2_Grad = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; + + CrossProduction = cb2_sigma*norm2_Grad*Volume; + + Residual = Production - Destruction + CrossProduction; + + /*--- Implicit part, production term ---*/ + + dfv1 = 3.0*Ji_2*cv1_3/(nu*pow(Ji_3+cv1_3,2.)); + dfv2 = -(1/nu-Ji_2*dfv1)/pow(1.+Ji*fv1,2.); + + if ( Shat <= 1.0e-10 ) dShat = 0.0; + else dShat = -S*pow(Ji,-2.0)/nu + S*dfv1; + Jacobian_i[0] += cb1*(TurbVar_i[0]*dShat+Shat)*Volume; + + /*--- Implicit part, destruction term ---*/ + + dr = (Shat-TurbVar_i[0]*dShat)*inv_Shat*inv_Shat*inv_k2_d2; + dr=(1-pow(tanh(r),2.0))*(dr)/tanh(1.0); + dg = dr*(1.+cw2*(6.0*pow(r,5.0)-1.0)); + dfw = dg*glim*(1.-g_6/(g_6+cw3_6)); + Jacobian_i[0] -= cw1*(dfw*TurbVar_i[0] + 2.0*fw)*TurbVar_i[0]/dist_i_2*Volume; + + } + + // AD::SetPreaccOut(Residual); + // AD::EndPreacc(); + + return ResidualType<>(&Residual, &Jacobian_i, nullptr); + +} + +CSourcePieceWise_TurbSA_E_COMP::CSourcePieceWise_TurbSA_E_COMP(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig* config) : + CSourceBase_TurbSA(val_nDim, val_nVar, config) { } + +CNumerics::ResidualType<> CSourcePieceWise_TurbSA_E_COMP::ComputeResidual(const CConfig* config) { + + unsigned short iDim; + + // AD::StartPreacc(); + // AD::SetPreaccIn(V_i, nDim+6); + // AD::SetPreaccIn(Vorticity_i, nDim); + // AD::SetPreaccIn(StrainMag_i); + // AD::SetPreaccIn(TurbVar_i[0]); + // AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); + // AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); + + if (incompressible) { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+4]; + } + else { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+5]; + } + + Residual = 0.0; + Production = 0.0; + Destruction = 0.0; + CrossProduction = 0.0; + Jacobian_i[0] = 0.0; + + /* + From NASA Turbulence model site. http://turbmodels.larc.nasa.gov/spalart.html + This form was developed primarily to improve the near-wall numerical behavior of the model (i.e., the goal was to improve the convergence behavior). The reference is: + Edwards, J. R. and Chandra, S. "Comparison of Eddy Viscosity-Transport Turbulence Models for Three-Dimensional, Shock-Separated Flowfields," AIAA Journal, Vol. 34, No. 4, 1996, pp. 756-763. + In this modificaton Omega is replaced by Strain Rate + */ + + /*--- Evaluate Omega, here Omega is the Strain Rate ---*/ + + Sbar = 0.0; + for(iDim=0;iDim 1e-10) { + + /*--- Production term ---*/ + + dist_i_2 = dist_i*dist_i; + nu = Laminar_Viscosity_i/Density_i; + Ji = TurbVar_i[0]/nu; + Ji_2 = Ji*Ji; + Ji_3 = Ji_2*Ji; + fv1 = Ji_3/(Ji_3+cv1_3); + fv2 = 1.0 - Ji/(1.0+Ji*fv1); + ft2 = ct3*exp(-ct4*Ji_2); + S = Omega; + inv_k2_d2 = 1.0/(k2*dist_i_2); + + Shat = max(S*((1.0/max(Ji,1.0e-16))+fv1),1.0e-16); + + Shat = max(Shat, 1.0e-10); + inv_Shat = 1.0/Shat; + + /*--- Production term ---*/; + + Production = cb1*Shat*TurbVar_i[0]*Volume; + + /*--- Destruction term ---*/ + + r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); + r=tanh(r)/tanh(1.0); + + g = r + cw2*(pow(r,6.0)-r); + g_6 = pow(g,6.0); + glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); + fw = g*glim; + + Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; + + /*--- Diffusion term ---*/ + + norm2_Grad = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; + + CrossProduction = cb2_sigma*norm2_Grad*Volume; + + Residual = Production - Destruction + CrossProduction; + + /*--- Compressibility Correction term ---*/ + Pressure_i = V_i[nDim+1]; + SoundSpeed_i = sqrt(Pressure_i*Gamma/Density_i); + aux_cc=0; + for(iDim=0;iDim(&Residual, &Jacobian_i, nullptr); + +} + +CSourcePieceWise_TurbSA_Neg::CSourcePieceWise_TurbSA_Neg(unsigned short val_nDim, + unsigned short val_nVar, + const CConfig* config) : + CSourceBase_TurbSA(val_nDim, val_nVar, config) { } + +CNumerics::ResidualType<> CSourcePieceWise_TurbSA_Neg::ComputeResidual(const CConfig* config) { + + unsigned short iDim; + +// AD::StartPreacc(); +// AD::SetPreaccIn(V_i, nDim+6); +// AD::SetPreaccIn(Vorticity_i, nDim); +// AD::SetPreaccIn(StrainMag_i); +// AD::SetPreaccIn(TurbVar_i[0]); +// AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); +// AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); + + if (incompressible) { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+4]; + } + else { + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+5]; + } + + Residual = 0.0; + Production = 0.0; + Destruction = 0.0; + CrossProduction = 0.0; + Jacobian_i[0] = 0.0; + + /*--- Evaluate Omega ---*/ + + Omega = sqrt(Vorticity_i[0]*Vorticity_i[0] + Vorticity_i[1]*Vorticity_i[1] + Vorticity_i[2]*Vorticity_i[2]); + + /*--- Rotational correction term ---*/ + + if (rotating_frame) { Omega += 2.0*min(0.0, StrainMag_i-Omega); } + + if (dist_i > 1e-10) { + + if (TurbVar_i[0] > 0.0) { + + /*--- Production term ---*/ + + dist_i_2 = dist_i*dist_i; + nu = Laminar_Viscosity_i/Density_i; + Ji = TurbVar_i[0]/nu; + Ji_2 = Ji*Ji; + Ji_3 = Ji_2*Ji; + fv1 = Ji_3/(Ji_3+cv1_3); + fv2 = 1.0 - Ji/(1.0+Ji*fv1); + ft2 = ct3*exp(-ct4*Ji_2); + S = Omega; + inv_k2_d2 = 1.0/(k2*dist_i_2); + + Shat = S + TurbVar_i[0]*fv2*inv_k2_d2; + Shat = max(Shat, 1.0e-10); + inv_Shat = 1.0/Shat; + + /*--- Production term ---*/; + + // Original SA model + // Production = cb1*(1.0-ft2)*Shat*TurbVar_i[0]*Volume; + + Production = cb1*Shat*TurbVar_i[0]*Volume; + + /*--- Destruction term ---*/ + + r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); + g = r + cw2*(pow(r,6.0)-r); + g_6 = pow(g,6.0); + glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); + fw = g*glim; + + Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; + + /*--- Diffusion term ---*/ + + norm2_Grad = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; + + CrossProduction = cb2_sigma*norm2_Grad*Volume; + + Residual = Production - Destruction + CrossProduction; + + /*--- Implicit part, production term ---*/ + + dfv1 = 3.0*Ji_2*cv1_3/(nu*pow(Ji_3+cv1_3,2.)); + dfv2 = -(1/nu-Ji_2*dfv1)/pow(1.+Ji*fv1,2.); + if ( Shat <= 1.0e-10 ) dShat = 0.0; + else dShat = (fv2+TurbVar_i[0]*dfv2)*inv_k2_d2; + Jacobian_i[0] += cb1*(TurbVar_i[0]*dShat+Shat)*Volume; + + /*--- Implicit part, destruction term ---*/ + + dr = (Shat-TurbVar_i[0]*dShat)*inv_Shat*inv_Shat*inv_k2_d2; + if (r == 10.0) dr = 0.0; + dg = dr*(1.+cw2*(6.0*pow(r,5.0)-1.0)); + dfw = dg*glim*(1.-g_6/(g_6+cw3_6)); + Jacobian_i[0] -= cw1*(dfw*TurbVar_i[0] + 2.0*fw)*TurbVar_i[0]/dist_i_2*Volume; + + } + + else { + + /*--- Production term ---*/ + + dist_i_2 = dist_i*dist_i; + + /*--- Production term ---*/; + + Production = cb1*(1.0-ct3)*Omega*TurbVar_i[0]*Volume; + + /*--- Destruction term ---*/ + + Destruction = cw1*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; + + /*--- Diffusion term ---*/ + + norm2_Grad = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; + + CrossProduction = cb2_sigma*norm2_Grad*Volume; + + Residual = Production + Destruction + CrossProduction; + + /*--- Implicit part, production term ---*/ + + Jacobian_i[0] += cb1*(1.0-ct3)*Omega*Volume; + + /*--- Implicit part, destruction term ---*/ + + Jacobian_i[0] += 2.0*cw1*TurbVar_i[0]/dist_i_2*Volume; + + } + + } + +// AD::SetPreaccOut(Residual); +// AD::EndPreacc(); + + return ResidualType<>(&Residual, &Jacobian_i, nullptr); + +} + +CSourcePieceWise_TurbSST::CSourcePieceWise_TurbSST(unsigned short val_nDim, + unsigned short val_nVar, + const su2double *constants, + su2double val_kine_Inf, + su2double val_omega_Inf, + const CConfig* config) : + CNumerics(val_nDim, val_nVar, config) { + + incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); + sustaining_terms = (config->GetKind_Turb_Model() == SST_SUST); + + /*--- Closure constants ---*/ + beta_star = constants[6]; + sigma_omega_1 = constants[2]; + sigma_omega_2 = constants[3]; + beta_1 = constants[4]; + beta_2 = constants[5]; + alfa_1 = constants[8]; + alfa_2 = constants[9]; + a1 = constants[7]; + + /*--- Set the ambient values of k and omega to the free stream values. ---*/ + kAmb = val_kine_Inf; + omegaAmb = val_omega_Inf; + + /*--- "Allocate" the Jacobian using the static buffer. ---*/ + Jacobian_i[0] = Jacobian_Buffer; + Jacobian_i[1] = Jacobian_Buffer+2; + +} + +CNumerics::ResidualType<> CSourcePieceWise_TurbSST::ComputeResidual(const CConfig* config) { + + AD::StartPreacc(); + AD::SetPreaccIn(StrainMag_i); + AD::SetPreaccIn(TurbVar_i, nVar); + AD::SetPreaccIn(TurbVar_Grad_i, nVar, nDim); + AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); + AD::SetPreaccIn(F1_i); AD::SetPreaccIn(F2_i); AD::SetPreaccIn(CDkw_i); + AD::SetPreaccIn(PrimVar_Grad_i, nDim+1, nDim); + + unsigned short iDim; + su2double alfa_blended, beta_blended; + su2double diverg, pk, pw, zeta; + + if (incompressible) { + AD::SetPreaccIn(V_i, nDim+6); + + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+4]; + Eddy_Viscosity_i = V_i[nDim+5]; + } + else { + AD::SetPreaccIn(V_i, nDim+7); + + Density_i = V_i[nDim+2]; + Laminar_Viscosity_i = V_i[nDim+5]; + Eddy_Viscosity_i = V_i[nDim+6]; + } + + Residual[0] = 0.0; Residual[1] = 0.0; + Jacobian_i[0][0] = 0.0; Jacobian_i[0][1] = 0.0; + Jacobian_i[1][0] = 0.0; Jacobian_i[1][1] = 0.0; + + /*--- Computation of blended constants for the source terms---*/ + + alfa_blended = F1_i*alfa_1 + (1.0 - F1_i)*alfa_2; + beta_blended = F1_i*beta_1 + (1.0 - F1_i)*beta_2; + + if (dist_i > 1e-10) { + + /*--- Production ---*/ + + diverg = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + diverg += PrimVar_Grad_i[iDim+1][iDim]; + + /* if using UQ methodolgy, calculate production using perturbed Reynolds stress matrix */ + + if (using_uq){ + SetReynoldsStressMatrix(TurbVar_i[0]); + SetPerturbedRSM(TurbVar_i[0], config); + SetPerturbedStrainMag(TurbVar_i[0]); + pk = Eddy_Viscosity_i*PerturbedStrainMag*PerturbedStrainMag + - 2.0/3.0*Density_i*TurbVar_i[0]*diverg; + } + else { + pk = Eddy_Viscosity_i*StrainMag_i*StrainMag_i - 2.0/3.0*Density_i*TurbVar_i[0]*diverg; + } + + + pk = min(pk,20.0*beta_star*Density_i*TurbVar_i[1]*TurbVar_i[0]); + pk = max(pk,0.0); + + zeta = max(TurbVar_i[1], StrainMag_i*F2_i/a1); + + /* if using UQ methodolgy, calculate production using perturbed Reynolds stress matrix */ + + if (using_uq){ + pw = PerturbedStrainMag * PerturbedStrainMag - 2.0/3.0*zeta*diverg; + } + else { + pw = StrainMag_i*StrainMag_i - 2.0/3.0*zeta*diverg; + } + pw = alfa_blended*Density_i*max(pw,0.0); + + /*--- Sustaining terms, if desired. Note that if the production terms are + larger equal than the sustaining terms, the original formulation is + obtained again. This is in contrast to the version in literature + where the sustaining terms are simply added. This latter approach could + lead to problems for very big values of the free-stream turbulence + intensity. ---*/ + + if ( sustaining_terms ) { + const su2double sust_k = beta_star*Density_i*kAmb*omegaAmb; + const su2double sust_w = beta_blended*Density_i*omegaAmb*omegaAmb; + + pk = max(pk, sust_k); + pw = max(pw, sust_w); + } + + /*--- Add the production terms to the residuals. ---*/ + + Residual[0] += pk*Volume; + Residual[1] += pw*Volume; + + /*--- Dissipation ---*/ + + Residual[0] -= beta_star*Density_i*TurbVar_i[1]*TurbVar_i[0]*Volume; + Residual[1] -= beta_blended*Density_i*TurbVar_i[1]*TurbVar_i[1]*Volume; + + /*--- Cross diffusion ---*/ + + Residual[1] += (1.0 - F1_i)*CDkw_i*Volume; + + /*--- Implicit part ---*/ + + Jacobian_i[0][0] = -beta_star*TurbVar_i[1]*Volume; + Jacobian_i[0][1] = -beta_star*TurbVar_i[0]*Volume; + Jacobian_i[1][0] = 0.0; + Jacobian_i[1][1] = -2.0*beta_blended*TurbVar_i[1]*Volume; + } + + AD::SetPreaccOut(Residual, nVar); + AD::EndPreacc(); + + return ResidualType<>(Residual, Jacobian_i, nullptr); + +} + +void CSourcePieceWise_TurbSST::GetMeanRateOfStrainMatrix(su2double **S_ij) +{ + /* --- Calculate the rate of strain tensor, using mean velocity gradients --- */ + + if (nDim == 3){ + S_ij[0][0] = PrimVar_Grad_i[1][0]; + S_ij[1][1] = PrimVar_Grad_i[2][1]; + S_ij[2][2] = PrimVar_Grad_i[3][2]; + S_ij[0][1] = 0.5 * (PrimVar_Grad_i[1][1] + PrimVar_Grad_i[2][0]); + S_ij[0][2] = 0.5 * (PrimVar_Grad_i[1][2] + PrimVar_Grad_i[3][0]); + S_ij[1][2] = 0.5 * (PrimVar_Grad_i[2][2] + PrimVar_Grad_i[3][1]); + S_ij[1][0] = S_ij[0][1]; + S_ij[2][1] = S_ij[1][2]; + S_ij[2][0] = S_ij[0][2]; + } + else { + S_ij[0][0] = PrimVar_Grad_i[1][0]; + S_ij[1][1] = PrimVar_Grad_i[2][1]; + S_ij[2][2] = 0.0; + S_ij[0][1] = 0.5 * (PrimVar_Grad_i[1][1] + PrimVar_Grad_i[2][0]); + S_ij[0][2] = 0.0; + S_ij[1][2] = 0.0; + S_ij[1][0] = S_ij[0][1]; + S_ij[2][1] = S_ij[1][2]; + S_ij[2][0] = S_ij[0][2]; + + } +} + +void CSourcePieceWise_TurbSST::SetReynoldsStressMatrix(su2double turb_ke){ + unsigned short iDim, jDim; + su2double **S_ij = new su2double* [3]; + su2double divVel = 0; + su2double TWO3 = 2.0/3.0; + + + + for (iDim = 0; iDim < 3; iDim++){ + S_ij[iDim] = new su2double [3]; + } + + GetMeanRateOfStrainMatrix(S_ij); + + /* --- Using rate of strain matrix, calculate Reynolds stress tensor --- */ + + for (iDim = 0; iDim < 3; iDim++){ + divVel += S_ij[iDim][iDim]; + } + + for (iDim = 0; iDim < 3; iDim++){ + for (jDim = 0; jDim < 3; jDim++){ + MeanReynoldsStress[iDim][jDim] = TWO3 * turb_ke * delta3[iDim][jDim] + - Eddy_Viscosity_i / Density_i * (2 * S_ij[iDim][jDim] - TWO3 * divVel * delta3[iDim][jDim]); + } + } + + for (iDim = 0; iDim < 3; iDim++) + delete [] S_ij[iDim]; + delete [] S_ij; +} + +void CSourcePieceWise_TurbSST::SetPerturbedRSM(su2double turb_ke, const CConfig* config){ + + unsigned short iDim,jDim; + + /* --- Calculate anisotropic part of Reynolds Stress tensor --- */ + + for (iDim = 0; iDim< 3; iDim++){ + for (jDim = 0; jDim < 3; jDim++){ + A_ij[iDim][jDim] = .5 * MeanReynoldsStress[iDim][jDim] / turb_ke - delta3[iDim][jDim] / 3.0; + Eig_Vec[iDim][jDim] = A_ij[iDim][jDim]; + } + } + + /* --- Get ordered eigenvectors and eigenvalues of A_ij --- */ + + EigenDecomposition(A_ij, Eig_Vec, Eig_Val, 3); + + /* compute convex combination coefficients */ + su2double c1c = Eig_Val[2] - Eig_Val[1]; + su2double c2c = 2.0 * (Eig_Val[1] - Eig_Val[0]); + su2double c3c = 3.0 * Eig_Val[0] + 1.0; + + /* define barycentric traingle corner points */ + Corners[0][0] = 1.0; + Corners[0][1] = 0.0; + Corners[1][0] = 0.0; + Corners[1][1] = 0.0; + Corners[2][0] = 0.5; + Corners[2][1] = 0.866025; + + /* define barycentric coordinates */ + Barycentric_Coord[0] = Corners[0][0] * c1c + Corners[1][0] * c2c + Corners[2][0] * c3c; + Barycentric_Coord[1] = Corners[0][1] * c1c + Corners[1][1] * c2c + Corners[2][1] * c3c; + + if (Eig_Val_Comp == 1) { + /* 1C turbulence */ + New_Coord[0] = Corners[0][0]; + New_Coord[1] = Corners[0][1]; + } + else if (Eig_Val_Comp == 2) { + /* 2C turbulence */ + New_Coord[0] = Corners[1][0]; + New_Coord[1] = Corners[1][1]; + } + else if (Eig_Val_Comp == 3) { + /* 3C turbulence */ + New_Coord[0] = Corners[2][0]; + New_Coord[1] = Corners[2][1]; + } + else { + /* 2C turbulence */ + New_Coord[0] = Corners[1][0]; + New_Coord[1] = Corners[1][1]; + } + /* calculate perturbed barycentric coordinates */ + + Barycentric_Coord[0] = Barycentric_Coord[0] + (uq_delta_b) * (New_Coord[0] - Barycentric_Coord[0]); + Barycentric_Coord[1] = Barycentric_Coord[1] + (uq_delta_b) * (New_Coord[1] - Barycentric_Coord[1]); + + /* rebuild c1c,c2c,c3c based on new barycentric coordinates */ + c3c = Barycentric_Coord[1] / Corners[2][1]; + c1c = Barycentric_Coord[0] - Corners[2][0] * c3c; + c2c = 1 - c1c - c3c; + + /* build new anisotropy eigenvalues */ + Eig_Val[0] = (c3c - 1) / 3.0; + Eig_Val[1] = 0.5 *c2c + Eig_Val[0]; + Eig_Val[2] = c1c + Eig_Val[1]; + + /* permute eigenvectors if required */ + if (uq_permute) { + for (iDim=0; iDim<3; iDim++) { + for (jDim=0; jDim<3; jDim++) { + New_Eig_Vec[iDim][jDim] = Eig_Vec[2-iDim][jDim]; + } + } + } + + else { + for (iDim=0; iDim<3; iDim++) { + for (jDim=0; jDim<3; jDim++) { + New_Eig_Vec[iDim][jDim] = Eig_Vec[iDim][jDim]; + } + } + } + + EigenRecomposition(newA_ij, New_Eig_Vec, Eig_Val, 3); + + /* compute perturbed Reynolds stress matrix; use under-relaxation factor (urlx)*/ + for (iDim = 0; iDim< 3; iDim++){ + for (jDim = 0; jDim < 3; jDim++){ + MeanPerturbedRSM[iDim][jDim] = 2.0 * turb_ke * (newA_ij[iDim][jDim] + 1.0/3.0 * delta3[iDim][jDim]); + MeanPerturbedRSM[iDim][jDim] = MeanReynoldsStress[iDim][jDim] + + uq_urlx*(MeanPerturbedRSM[iDim][jDim] - MeanReynoldsStress[iDim][jDim]); + } + } + +} + +void CSourcePieceWise_TurbSST::SetPerturbedStrainMag(su2double turb_ke){ + unsigned short iDim, jDim; + PerturbedStrainMag = 0; + su2double **StrainRate = new su2double* [nDim]; + for (iDim= 0; iDim< nDim; iDim++){ + StrainRate[iDim] = new su2double [nDim]; + } + + /* compute perturbed strain rate tensor */ + + for (iDim = 0; iDim < nDim; iDim++){ + for (jDim =0; jDim < nDim; jDim++){ + StrainRate[iDim][jDim] = MeanPerturbedRSM[iDim][jDim] + - TWO3 * turb_ke * delta[iDim][jDim]; + StrainRate[iDim][jDim] = - StrainRate[iDim][jDim] * Density_i / (2 * Eddy_Viscosity_i); + } + } + + /*--- Add diagonal part ---*/ + + for (iDim = 0; iDim < nDim; iDim++) { + PerturbedStrainMag += pow(StrainRate[iDim][iDim], 2.0); + } + + /*--- Add off diagonals ---*/ + + PerturbedStrainMag += 2.0*pow(StrainRate[1][0], 2.0); + + if (nDim == 3) { + PerturbedStrainMag += 2.0*pow(StrainRate[0][2], 2.0); + PerturbedStrainMag += 2.0*pow(StrainRate[1][2], 2.0); + } + + PerturbedStrainMag = sqrt(2.0*PerturbedStrainMag); + + for (iDim= 0; iDim< nDim; iDim++){ + delete [] StrainRate[iDim]; + } + + delete [] StrainRate; +} diff --git a/SU2_CFD/src/numerics_adjoint_mean.cpp b/SU2_CFD/src/numerics_adjoint_mean.cpp deleted file mode 100644 index beb0a038c31f..000000000000 --- a/SU2_CFD/src/numerics_adjoint_mean.cpp +++ /dev/null @@ -1,1598 +0,0 @@ -/*! - * \file numerics_adjoint_mean.cpp - * \brief This file contains the numerical methods for adjoint compressible flow. - * \author F. Palacios, T. Economon - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - - -#include "../include/numerics_structure.hpp" -#include - -CUpwRoe_AdjFlow::CUpwRoe_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); - grid_movement = config->GetGrid_Movement(); - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Residual_Roe = new su2double [nVar]; - RoeVelocity = new su2double [nDim]; - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - Lambda = new su2double [nVar]; - P_Tensor = new su2double* [nVar]; - invP_Tensor = new su2double* [nVar]; - ProjFlux_i = new su2double*[nVar]; - ProjFlux_j = new su2double*[nVar]; - Proj_ModJac_Tensor = new su2double*[nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - P_Tensor[iVar] = new su2double [nVar]; - invP_Tensor[iVar] = new su2double [nVar]; - ProjFlux_i[iVar] = new su2double[nVar]; - ProjFlux_j[iVar] = new su2double[nVar]; - Proj_ModJac_Tensor[iVar] = new su2double[nVar]; - } - -} - -CUpwRoe_AdjFlow::~CUpwRoe_AdjFlow(void) { - - delete [] Residual_Roe; - delete [] RoeVelocity; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] Lambda; - for (iVar = 0; iVar < nVar; iVar++) { - delete [] P_Tensor[iVar]; - delete [] invP_Tensor[iVar]; - delete [] ProjFlux_i[iVar]; - delete [] ProjFlux_j[iVar]; - delete [] Proj_ModJac_Tensor[iVar]; - } - delete [] P_Tensor; - delete [] invP_Tensor; - delete [] ProjFlux_i; - delete [] ProjFlux_j; - delete [] Proj_ModJac_Tensor; - -} - -void CUpwRoe_AdjFlow::ComputeResidual (su2double *val_residual_i, su2double *val_residual_j, su2double **val_Jacobian_ii, - su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { - - /*--- Compute the area ---*/ - - area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - area += Normal[iDim]*Normal[iDim]; - area = sqrt(area); - rarea = 1.0 / area; - - /*--- Components of the normal & unit normal vector of the current face ---*/ - - Sx = Normal[0]; - Sy = Normal[1]; - Sz = 0.0; if (nDim == 3) Sz = Normal[2]; - nx = Sx * rarea; - ny = Sy * rarea; - nz = Sz * rarea; - - /*--- Flow variable states at point i (left, _l) and j (right, _r)---*/ - - rho_l = V_i[nDim+2]; rho_r = V_j[nDim+2]; - u_l = V_i[1]; v_l = V_i[2]; w_l = 0.0; if (nDim == 3) w_l = V_i[3]; - u_r = V_j[1]; v_r = V_j[2]; w_r = 0.0; if (nDim == 3) w_r = V_j[3]; - h_l = V_i[nDim+3]; h_r = V_j[nDim+3]; - - /*--- One-half speed squared ---*/ - - q_l = ONE2 * ((u_l*u_l) + (v_l*v_l) + (w_l*w_l)); - q_r = ONE2 * ((u_r*u_r) + (v_r*v_r) + (w_r*w_r)); - - /*--- Projected velocity ---*/ - - Q_l = (u_l * Sx) + (v_l * Sy) + (w_l * Sz); - Q_r = (u_r * Sx) + (v_r * Sy) + (w_r * Sz); - - /*--- Mean adjoint variables ---*/ - - psi1 = ONE2 * (Psi_i[0] + Psi_j[0]); - psi2 = ONE2 * (Psi_i[1] + Psi_j[1]); - psi3 = ONE2 * (Psi_i[2] + Psi_j[2]); - psi4 = 0.0; if (nDim == 3) psi4 = ONE2 * (Psi_i[3] + Psi_j[3]); - psi5 = ONE2 * (Psi_i[nVar-1] + Psi_j[nVar-1]); - - /*--- Left state ---*/ - - l1psi = (Sx * psi2) + (Sy * psi3) + (Sz * psi4) + (Q_l * psi5); - l2psi = psi1 + (u_l * psi2) + (v_l * psi3) + (w_l * psi4) + (h_l * psi5); - - val_residual_i[0] = Q_l * psi1 - l2psi * Q_l + l1psi * Gamma_Minus_One * q_l; - val_residual_i[1] = Q_l * psi2 + l2psi * Sx - l1psi * Gamma_Minus_One * u_l; - val_residual_i[2] = Q_l * psi3 + l2psi * Sy - l1psi * Gamma_Minus_One * v_l; - if (nDim == 3) val_residual_i[3] = Q_l * psi4 + l2psi * Sz - l1psi * Gamma_Minus_One * w_l; - val_residual_i[nVar-1] = Q_l * psi5 + l1psi * Gamma_Minus_One; - - /*--- Right state ---*/ - - l1psi = (Sx * psi2) + (Sy * psi3) + (Sz * psi4) + (Q_r * psi5); - l2psi = psi1 + (u_r * psi2) + (v_r * psi3) + (w_r * psi4) + (h_r * psi5); - - val_residual_j[0] = -(Q_r * psi1 - l2psi * Q_r + l1psi * Gamma_Minus_One * q_r); - val_residual_j[1] = -(Q_r * psi2 + l2psi * Sx - l1psi * Gamma_Minus_One * u_r); - val_residual_j[2] = -(Q_r * psi3 + l2psi * Sy - l1psi * Gamma_Minus_One * v_r); - if (nDim == 3) val_residual_j[3] = -(Q_r * psi4 + l2psi * Sz - l1psi * Gamma_Minus_One * w_r); - val_residual_j[nVar-1] = -(Q_r * psi5 + l1psi * Gamma_Minus_One); - - - /*--- f_{roe} = P^{-T} |lambda| P^T \delta \psi ---*/ - - psi1_l = Psi_i[0]; - psi2_l = Psi_i[1]; - psi3_l = Psi_i[2]; - psi4_l = 0.0; if (nDim == 3) psi4_l = Psi_i[3]; - psi5_l = Psi_i[nVar-1]; - - psi1_r = Psi_j[0]; - psi2_r = Psi_j[1]; - psi3_r = Psi_j[2]; - psi4_r = 0.0; if (nDim == 3) psi4_r = Psi_j[3]; - psi5_r = Psi_j[nVar-1]; - - /*--- Roe averaging ---*/ - - rrho_l = 1.0 / rho_l; - weight = sqrt(rho_r * rrho_l); - rweight1 = 1.0 / (1.0 + weight); - weight *= rweight1; - - h = h_l * rweight1 + weight * h_r; - u = u_l * rweight1 + weight * u_r; - v = v_l * rweight1 + weight * v_r; - w = w_l * rweight1 + weight * w_r; - - psi1 = ONE2 * (psi1_r - psi1_l); - psi2 = ONE2 * (psi2_r - psi2_l); - psi3 = ONE2 * (psi3_r - psi3_l); - psi4 = ONE2 * (psi4_r - psi4_l); - psi5 = ONE2 * (psi5_r - psi5_l); - - q2 = (u*u) + (v*v) + (w*w); - Q = (u * Sx) + (v * Sy) + (w * Sz); - vn = nx * u + ny * v + nz * w; - cc = Gamma_Minus_One * h - 0.5 * Gamma_Minus_One * q2; - c = sqrt(cc); - - /*--- Contribution to velocity projection due to grid movement ---*/ - - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - Q -= ProjGridVel; - } - - /*--- Eigenvalues from the primal solution ---*/ - - absQ = fabs(Q); - absQp = fabs(Q + c * area); - absQm = fabs(Q - c * area); - - alpha = ONE2 * Gamma_Minus_One * q2 / cc; - beta_u = psi2 + u * psi5; - beta_v = psi3 + v * psi5; - beta_w = psi4 + w * psi5; - eta = Gamma_Minus_One / cc; - l1psi = (nx * psi2) + (ny * psi3) + (nz * psi4) + (vn * psi5); - l2psi = psi1 + (u * psi2) + (v * psi3) + (w * psi4) + (h * psi5); - l1l2p = (l2psi + c * l1psi) * absQp; - l1l2m = (l2psi - c * l1psi) * absQm; - - /*--- adjoint flux computation in the x, y and z coordinate system ---*/ - - Residual_Roe[0] = ((1.0-alpha)*l2psi - (1.0-alpha)*cc/Gamma_Minus_One*psi5 - - u*beta_u*(1.0-(nx*nx)) - v*beta_v*(1.0-(ny*ny)) - - w*beta_w*(1.0-(nz*nz)) + ny*nz*(w*beta_v + v*beta_w) - + nx*nz*(w*beta_u + u*beta_w) + ny*nx*(v*beta_u + u*beta_v) ) * absQ - - ONE2 / c * vn * (l1l2p - l1l2m) + ONE2 * alpha * (l1l2p + l1l2m); - - Residual_Roe[1] = (l2psi*u*eta - u*psi5 + beta_u*(1.0-(nx*nx)) - - nx*(beta_v*ny + beta_w*nz) ) * absQ + ONE2*nx/c * (l1l2p - l1l2m ) - - ONE2*eta*u * (l1l2p + l1l2m ); - - Residual_Roe[2] = (l2psi*v*eta - v*psi5 + beta_v*(1.0-(ny*ny)) - - ny*(beta_w*nz + beta_u*nx) ) * absQ + ONE2*ny/c * (l1l2p - l1l2m ) - - ONE2*eta*v * (l1l2p + l1l2m ); - - if (nDim == 3) Residual_Roe[3] = (l2psi*w*eta - w*psi5 + beta_w*(1.0-(nz*nz)) - nz*(beta_u*nx + beta_v*ny) ) * absQ - + ONE2*nz/c * (l1l2p - l1l2m ) - ONE2*eta*w * (l1l2p + l1l2m ); - - Residual_Roe[nVar-1] = (psi5 - l2psi*eta) * absQ + ONE2*eta*(l1l2p + l1l2m); - - for (iVar = 0; iVar < nVar; iVar++) { - val_residual_i[iVar] += Residual_Roe[iVar]; - val_residual_j[iVar] -= Residual_Roe[iVar]; - } - - /*--- Flux contribution due to grid movement ---*/ - - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - for (iVar = 0; iVar < nVar; iVar++) { - val_residual_i[iVar] -= ProjGridVel * 0.5*(Psi_i[iVar]+Psi_j[iVar]); - val_residual_j[iVar] += ProjGridVel * 0.5*(Psi_i[iVar]+Psi_j[iVar]); - } - } - - /*--- Implicit Contributions ---*/ - - if (implicit) { - - /*--- Prepare variables for use in matrix routines ---*/ - - RoeDensity = V_i[nDim+2]*sqrt(V_j[nDim+2]/V_i[nDim+2]); - RoeSoundSpeed = c; - UnitNormal[0] = nx; UnitNormal[1] = ny; if (nDim == 3 ) UnitNormal[2] = nz; - RoeVelocity[0] = u; RoeVelocity[1] = v; if (nDim == 3 ) RoeVelocity[2] = w; - Velocity_i[0] = u_l; Velocity_i[1] = v_l; if (nDim == 3 ) Velocity_i[2] = w_l; - Velocity_j[0] = u_r; Velocity_j[1] = v_r; if (nDim == 3 ) Velocity_j[2] = w_r; - - Pressure_i = V_i[nDim+1]; - Density_i = V_i[nDim+2]; - Enthalpy_i = V_i[nDim+3]; - Energy_i = Enthalpy_i - Pressure_i/Density_i; - - Pressure_j = V_i[nDim+1]; - Density_j = V_i[nDim+2]; - Enthalpy_j = V_i[nDim+3]; - Energy_j = Enthalpy_j - Pressure_j/Density_j; - - /*--- Jacobians of the inviscid flux, scaled by - 0.5 because val_resconv ~ 0.5*(fc_i+fc_j)*Normal ---*/ - - GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5, ProjFlux_i); - GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5, ProjFlux_j); - - /*--- Compute P, inverse P, and store eigenvalues ---*/ - - GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); - GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, P_Tensor); - - /*--- Flow eigenvalues ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - Lambda[iDim] = absQ; - Lambda[nVar-2] = absQp; - Lambda[nVar-1] = absQm; - - /*--- Roe's Flux approximation ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - Proj_ModJac_Tensor_ij = 0.0; - - /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ - - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; - Proj_ModJac_Tensor[iVar][jVar] = 0.5*Proj_ModJac_Tensor_ij*area; - } - } - - /*--- Transpose the matrices and store the Jacobians. Note the negative - sign for the ji and jj Jacobians bc the normal direction is flipped. ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_ii[jVar][iVar] = ProjFlux_i[iVar][jVar] - Proj_ModJac_Tensor[iVar][jVar]; - val_Jacobian_ij[jVar][iVar] = ProjFlux_i[iVar][jVar] + Proj_ModJac_Tensor[iVar][jVar]; - val_Jacobian_ji[jVar][iVar] = -(ProjFlux_j[iVar][jVar] - Proj_ModJac_Tensor[iVar][jVar]); - val_Jacobian_jj[jVar][iVar] = -(ProjFlux_j[iVar][jVar] + Proj_ModJac_Tensor[iVar][jVar]); - } - } - - /*--- Jacobian contribution due to grid movement ---*/ - - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - for (iVar = 0; iVar < nVar; iVar++) { - - /*--- Adjust Jacobian main diagonal ---*/ - - val_Jacobian_ii[iVar][iVar] -= 0.5*ProjGridVel; - val_Jacobian_ij[iVar][iVar] -= 0.5*ProjGridVel; - val_Jacobian_ji[iVar][iVar] += 0.5*ProjGridVel; - val_Jacobian_jj[iVar][iVar] += 0.5*ProjGridVel; - } - } - - } -} - -CCentJST_AdjFlow::CCentJST_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - grid_movement = config->GetGrid_Movement(); - - Diff_Psi = new su2double [nVar]; Diff_Lapl = new su2double [nVar]; - Velocity_i = new su2double [nDim]; Velocity_j = new su2double [nDim]; - MeanPhi = new su2double [nDim]; - - Param_p = 0.3; - Param_Kappa_2 = config->GetKappa_2nd_AdjFlow(); - Param_Kappa_4 = config->GetKappa_4th_AdjFlow(); - implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); - -} - -CCentJST_AdjFlow::~CCentJST_AdjFlow(void) { - - delete [] Diff_Psi; delete [] Diff_Lapl; - delete [] Velocity_i; delete [] Velocity_j; - delete [] MeanPhi; -} - -void CCentJST_AdjFlow::ComputeResidual (su2double *val_resconv_i, su2double *val_resvisc_i, su2double *val_resconv_j, su2double *val_resvisc_j, - su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, - CConfig *config) { - - /*--- Mean Values ---*/ - - MeanPsiRho = 0.5*(Psi_i[0]+Psi_j[0]); - for (iDim = 0; iDim < nDim; iDim++) - MeanPhi[iDim] = 0.5*(Psi_i[iDim+1]+Psi_j[iDim+1]); - MeanPsiE = 0.5*(Psi_i[nVar-1]+Psi_j[nVar-1]); - - /*--- Point i convective residual evaluation ---*/ - - ProjVelocity_i = 0; ProjPhi = 0; ProjPhi_Vel = 0; sq_vel = 0; Area = 0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = U_i[iDim+1] / U_i[0]; - ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; - ProjPhi += MeanPhi[iDim]*Normal[iDim]; - ProjPhi_Vel += MeanPhi[iDim]*Velocity_i[iDim]; - sq_vel += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; - Area += Normal[iDim]*Normal[iDim]; - } - Area = sqrt(Area); - phis1 = ProjPhi + ProjVelocity_i*MeanPsiE; - phis2 = MeanPsiRho + ProjPhi_Vel + Enthalpy_i*MeanPsiE; - - val_resconv_i[0] = ProjVelocity_i*MeanPsiRho - phis2*ProjVelocity_i + Gamma_Minus_One*phis1*sq_vel; - for (iDim = 0; iDim < nDim; iDim++) - val_resconv_i[iDim+1] = ProjVelocity_i*MeanPhi[iDim] + phis2*Normal[iDim] - Gamma_Minus_One*phis1*Velocity_i[iDim]; - val_resconv_i[nVar-1] = ProjVelocity_i*MeanPsiE + Gamma_Minus_One*phis1; - - /*--- Flux contributions due to grid movement at point i ---*/ - - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - val_resconv_i[0] -= ProjGridVel*MeanPsiRho; - for (iDim = 0; iDim < nDim; iDim++) - val_resconv_i[iDim+1] -= ProjGridVel*MeanPhi[iDim]; - val_resconv_i[nVar-1] -= ProjGridVel*MeanPsiE; - } - - /*--- Jacobians of the inviscid flux ---*/ - - if (implicit) { - val_Jacobian_ii[0][0] = 0.0; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_ii[0][jDim+1] = -0.5*ProjVelocity_i*Velocity_i[jDim] + Gamma_Minus_One*sq_vel*0.5*Normal[jDim]; - val_Jacobian_ii[0][nVar-1] = 0.5*ProjVelocity_i*(Gamma_Minus_One*sq_vel - Enthalpy_i); - for (iDim = 0; iDim < nDim; iDim++) { - val_Jacobian_ii[iDim+1][0] = 0.5*Normal[iDim]; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_ii[iDim+1][jDim+1] = 0.5*Normal[iDim]*Velocity_i[jDim] - 0.5*Gamma_Minus_One*Velocity_i[iDim]*Normal[jDim]; - val_Jacobian_ii[iDim+1][iDim+1] += 0.5*ProjVelocity_i; - val_Jacobian_ii[iDim+1][nVar-1] = 0.5*Enthalpy_i*Normal[iDim] - 0.5*Gamma_Minus_One*Velocity_i[iDim]*ProjVelocity_i; - } - val_Jacobian_ii[nVar-1][0] = 0; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_ii[nVar-1][jDim+1] = 0.5*Gamma_Minus_One*Normal[jDim]; - val_Jacobian_ii[nVar-1][nVar-1] = 0.5*Gamma*ProjVelocity_i; - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_ij[iVar][jVar] = val_Jacobian_ii[iVar][jVar]; - - /*--- Jacobian contributions due to grid movement at point i ---*/ - - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - for (iVar = 0; iVar < nVar; iVar++) { - val_Jacobian_ii[iVar][iVar] -= 0.5*ProjGridVel; - val_Jacobian_ij[iVar][iVar] -= 0.5*ProjGridVel; - } - } - } - - - /*--- Point j convective residual evaluation ---*/ - - ProjVelocity_j = 0; ProjPhi_Vel = 0; sq_vel = 0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_j[iDim] = U_j[iDim+1] / U_j[0]; - ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; - ProjPhi_Vel += MeanPhi[iDim]*Velocity_j[iDim]; - sq_vel += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; - } - - phis1 = ProjPhi + ProjVelocity_j*MeanPsiE; - phis2 = MeanPsiRho + ProjPhi_Vel + Enthalpy_j*MeanPsiE; - - val_resconv_j[0] = -(ProjVelocity_j*MeanPsiRho - phis2*ProjVelocity_j + Gamma_Minus_One*phis1*sq_vel); - for (iDim = 0; iDim < nDim; iDim++) - val_resconv_j[iDim+1] = -(ProjVelocity_j*MeanPhi[iDim] + phis2*Normal[iDim] - Gamma_Minus_One*phis1*Velocity_j[iDim]); - val_resconv_j[nVar-1] = -(ProjVelocity_j*MeanPsiE + Gamma_Minus_One*phis1); - - /*--- Flux contributions due to grid motion at point j ---*/ - - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - val_resconv_j[0] += ProjGridVel*MeanPsiRho; - for (iDim = 0; iDim < nDim; iDim++) - val_resconv_j[iDim+1] += ProjGridVel*MeanPhi[iDim]; - val_resconv_j[nVar-1] += ProjGridVel*MeanPsiE; - } - - /*--- Jacobians of the inviscid flux ---*/ - - if (implicit) { - val_Jacobian_jj[0][0] = 0.0; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_jj[0][jDim+1] = 0.5*ProjVelocity_j*Velocity_j[jDim] - Gamma_Minus_One*sq_vel*0.5*Normal[jDim]; - val_Jacobian_jj[0][nVar-1] = -0.5*ProjVelocity_j*(Gamma_Minus_One*sq_vel - Enthalpy_j); - for (iDim = 0; iDim < nDim; iDim++) { - val_Jacobian_jj[iDim+1][0] = -0.5*Normal[iDim]; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_jj[iDim+1][jDim+1] = -0.5*Normal[iDim]*Velocity_j[jDim] + 0.5*Gamma_Minus_One*Velocity_j[iDim]*Normal[jDim]; - val_Jacobian_jj[iDim+1][iDim+1] -= 0.5*ProjVelocity_j; - val_Jacobian_jj[iDim+1][nVar-1] = -0.5*Enthalpy_j*Normal[iDim] + 0.5*Gamma_Minus_One*Velocity_j[iDim]*ProjVelocity_j; - } - val_Jacobian_jj[nVar-1][0] = 0; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_jj[nVar-1][jDim+1] = -0.5*Gamma_Minus_One*Normal[jDim]; - val_Jacobian_jj[nVar-1][nVar-1] = -0.5*Gamma*ProjVelocity_j; - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_ji[iVar][jVar] = val_Jacobian_jj[iVar][jVar]; - - /*--- Jacobian contributions due to grid motion at point j ---*/ - - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - for (iVar = 0; iVar < nVar; iVar++) { - val_Jacobian_jj[iVar][iVar] += 0.5*ProjGridVel; - val_Jacobian_ji[iVar][iVar] += 0.5*ProjGridVel; - } - } - } - - /*--- Computes differences btw. variables and Laplacians ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Diff_Lapl[iVar] = Und_Lapl_i[iVar]-Und_Lapl_j[iVar]; - Diff_Psi[iVar] = Psi_i[iVar]-Psi_j[iVar]; - } - - /*--- Adjustment to projected velocity due to grid motion ---*/ - - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - } - ProjVelocity_i -= ProjGridVel; - ProjVelocity_j += ProjGridVel; - } - - /*--- Compute the spectral radius and stretching factor ---*/ - - Local_Lambda_i = (fabs(ProjVelocity_i)+SoundSpeed_i*Area); - Local_Lambda_j = (fabs(ProjVelocity_j)+SoundSpeed_j*Area); - MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); - - Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); - Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); - StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); - - su2double sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); - sc4 = sc2*sc2/4.0; - Epsilon_2 = Param_Kappa_2*0.5*(Sensor_i+Sensor_j)*sc2; - Epsilon_4 = max(0.0, Param_Kappa_4-Epsilon_2)*sc4; - - /*--- Compute viscous residual 1st- & 3rd-order dissipation ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Residual = (Epsilon_2*Diff_Psi[iVar]-Epsilon_4*Diff_Lapl[iVar])*StretchingFactor*MeanLambda; - val_resvisc_i[iVar] = -Residual; - val_resvisc_j[iVar] = Residual; - if (implicit) { - val_Jacobian_ii[iVar][iVar] -= Epsilon_2 + su2double(Neighbor_i+1)*Epsilon_4*StretchingFactor*MeanLambda; - val_Jacobian_ij[iVar][iVar] += Epsilon_2 + su2double(Neighbor_j+1)*Epsilon_4*StretchingFactor*MeanLambda; - val_Jacobian_ji[iVar][iVar] += Epsilon_2 + su2double(Neighbor_i+1)*Epsilon_4*StretchingFactor*MeanLambda; - val_Jacobian_jj[iVar][iVar] -= Epsilon_2 + su2double(Neighbor_j+1)*Epsilon_4*StretchingFactor*MeanLambda; - } - } - -} - -CCentLax_AdjFlow::CCentLax_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Diff_Psi = new su2double [nVar]; MeanPhi = new su2double [nDim]; - Velocity_i = new su2double [nDim]; Velocity_j = new su2double [nDim]; - - implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); - - grid_movement = config->GetGrid_Movement(); - - Param_p = 0.3; - Param_Kappa_0 = config->GetKappa_1st_AdjFlow(); - -} - -CCentLax_AdjFlow::~CCentLax_AdjFlow(void) { - - delete [] Diff_Psi; delete [] MeanPhi; - delete [] Velocity_i; delete [] Velocity_j; - -} - -void CCentLax_AdjFlow::ComputeResidual (su2double *val_resconv_i, su2double *val_resvisc_i, su2double *val_resconv_j, su2double *val_resvisc_j, - su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, - CConfig *config) { - - /*--- Mean value of the adjoint variables ---*/ - MeanPsiRho = 0.5*(Psi_i[0]+Psi_j[0]); - for (iDim = 0; iDim < nDim; iDim++) - MeanPhi[iDim] = 0.5*(Psi_i[iDim+1]+Psi_j[iDim+1]); - MeanPsiE = 0.5*(Psi_i[nVar-1]+Psi_j[nVar-1]); - - /*--- Evaluation at point i ---*/ - ProjVelocity_i = 0; ProjPhi = 0; ProjPhi_Vel = 0; sq_vel = 0; Area = 0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = U_i[iDim+1] / U_i[0]; - ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; - ProjPhi += MeanPhi[iDim]*Normal[iDim]; - ProjPhi_Vel += MeanPhi[iDim]*Velocity_i[iDim]; - sq_vel += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; - Area += Normal[iDim]*Normal[iDim]; - } - Area = sqrt(Area); - phis1 = ProjPhi + ProjVelocity_i*MeanPsiE; - phis2 = MeanPsiRho + ProjPhi_Vel + Enthalpy_i*MeanPsiE; - - /*--- Compute inviscid residual at point i ---*/ - val_resconv_i[0] = ProjVelocity_i*MeanPsiRho - phis2*ProjVelocity_i + Gamma_Minus_One*phis1*sq_vel; - for (iDim = 0; iDim < nDim; iDim++) - val_resconv_i[iDim+1] = ProjVelocity_i*MeanPhi[iDim] + phis2*Normal[iDim] - Gamma_Minus_One*phis1*Velocity_i[iDim]; - val_resconv_i[nVar-1] = ProjVelocity_i*MeanPsiE + Gamma_Minus_One*phis1; - - /*--- Flux contributions due to grid motion at point i ---*/ - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - val_resconv_i[0] -= ProjGridVel*MeanPsiRho; - for (iDim = 0; iDim < nDim; iDim++) - val_resconv_i[iDim+1] -= ProjGridVel*MeanPhi[iDim]; - val_resconv_i[nVar-1] -= ProjGridVel*MeanPsiE; - } - - /*--- Inviscid contribution to the implicit part ---*/ - if (implicit) { - val_Jacobian_ii[0][0] = 0.0; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_ii[0][jDim+1] = -0.5*ProjVelocity_i*Velocity_i[jDim] + Gamma_Minus_One*sq_vel*0.5*Normal[jDim]; - val_Jacobian_ii[0][nVar-1] = 0.5*ProjVelocity_i*(Gamma_Minus_One*sq_vel - Enthalpy_i); - for (iDim = 0; iDim < nDim; iDim++) { - val_Jacobian_ii[iDim+1][0] = 0.5*Normal[iDim]; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_ii[iDim+1][jDim+1] = 0.5*Normal[iDim]*Velocity_i[jDim] - 0.5*Gamma_Minus_One*Velocity_i[iDim]*Normal[jDim]; - val_Jacobian_ii[iDim+1][iDim+1] += 0.5*ProjVelocity_i; - val_Jacobian_ii[iDim+1][nVar-1] = 0.5*Enthalpy_i*Normal[iDim] - 0.5*Gamma_Minus_One*Velocity_i[iDim]*ProjVelocity_i; - } - val_Jacobian_ii[nVar-1][0] = 0; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_ii[nVar-1][jDim+1] = 0.5*Gamma_Minus_One*Normal[jDim]; - val_Jacobian_ii[nVar-1][nVar-1] = 0.5*Gamma*ProjVelocity_i; - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_ij[iVar][jVar] = val_Jacobian_ii[iVar][jVar]; - - /*--- Jacobian contributions due to grid motion at point i ---*/ - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - for (iVar = 0; iVar < nVar; iVar++) { - val_Jacobian_ii[iVar][iVar] -= 0.5*ProjGridVel; - val_Jacobian_ij[iVar][iVar] -= 0.5*ProjGridVel; - } - } - } - - /*--- Evaluation at point j ---*/ - ProjVelocity_j = 0; ProjPhi_Vel = 0; sq_vel = 0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_j[iDim] = U_j[iDim+1] / U_j[0]; - ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; - ProjPhi_Vel += MeanPhi[iDim]*Velocity_j[iDim]; - sq_vel += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; - } - - phis1 = ProjPhi + ProjVelocity_j*MeanPsiE; - phis2 = MeanPsiRho + ProjPhi_Vel + Enthalpy_j*MeanPsiE; - - /*--- Compute inviscid residual at point j ---*/ - val_resconv_j[0] = -(ProjVelocity_j*MeanPsiRho - phis2*ProjVelocity_j + Gamma_Minus_One*phis1*sq_vel); - for (iDim = 0; iDim < nDim; iDim++) - val_resconv_j[iDim+1] = -(ProjVelocity_j*MeanPhi[iDim] + phis2*Normal[iDim] - Gamma_Minus_One*phis1*Velocity_j[iDim]); - val_resconv_j[nVar-1] = -(ProjVelocity_j*MeanPsiE + Gamma_Minus_One*phis1); - - /*--- Flux contributions due to grid movement at point j ---*/ - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - val_resconv_j[0] += ProjGridVel*MeanPsiRho; - for (iDim = 0; iDim < nDim; iDim++) - val_resconv_j[iDim+1] += ProjGridVel*MeanPhi[iDim]; - val_resconv_j[nVar-1] += ProjGridVel*MeanPsiE; - } - - /*--- Inviscid contribution to the implicit part ---*/ - if (implicit) { - val_Jacobian_jj[0][0] = 0.0; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_jj[0][jDim+1] = 0.5*ProjVelocity_j*Velocity_j[jDim] - Gamma_Minus_One*sq_vel*0.5*Normal[jDim]; - val_Jacobian_jj[0][nVar-1] = -0.5*ProjVelocity_j*(Gamma_Minus_One*sq_vel - Enthalpy_j); - for (iDim = 0; iDim < nDim; iDim++) { - val_Jacobian_jj[iDim+1][0] = -0.5*Normal[iDim]; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_jj[iDim+1][jDim+1] = -0.5*Normal[iDim]*Velocity_j[jDim] + 0.5*Gamma_Minus_One*Velocity_j[iDim]*Normal[jDim]; - val_Jacobian_jj[iDim+1][iDim+1] -= 0.5*ProjVelocity_j; - val_Jacobian_jj[iDim+1][nVar-1] = -0.5*Enthalpy_j*Normal[iDim] + 0.5*Gamma_Minus_One*Velocity_j[iDim]*ProjVelocity_j; - } - val_Jacobian_jj[nVar-1][0] = 0; - for (jDim = 0; jDim < nDim; jDim++) - val_Jacobian_jj[nVar-1][jDim+1] = -0.5*Gamma_Minus_One*Normal[jDim]; - val_Jacobian_jj[nVar-1][nVar-1] = -0.5*Gamma*ProjVelocity_j; - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_ji[iVar][jVar] = val_Jacobian_jj[iVar][jVar]; - - /*--- Jacobian contributions due to grid movement at point j ---*/ - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - for (iVar = 0; iVar < nVar; iVar++) { - val_Jacobian_jj[iVar][iVar] += 0.5*ProjGridVel; - val_Jacobian_ji[iVar][iVar] += 0.5*ProjGridVel; - } - } - } - - /*--- Computes differences btw. variables ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Diff_Psi[iVar] = Psi_i[iVar]-Psi_j[iVar]; - - /*--- Adjustment to projected velocity due to grid motion ---*/ - if (grid_movement) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - ProjVelocity_i -= ProjGridVel; - ProjVelocity_j += ProjGridVel; - } - - /*--- Compute spectral radius ---*/ - Local_Lambda_i = (fabs(ProjVelocity_i)+SoundSpeed_i*Area); - Local_Lambda_j = (fabs(ProjVelocity_j)+SoundSpeed_j*Area); - MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); - - /*--- Compute streching factor ---*/ - Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); - Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); - StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); - - sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); - Epsilon_0 = Param_Kappa_0*sc2*su2double(nDim)/3.0; - - /*--- Artifical dissipation evaluation ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - Residual = Epsilon_0*StretchingFactor*MeanLambda*Diff_Psi[iVar]; - val_resvisc_i[iVar] = -Residual; - val_resvisc_j[iVar] = Residual; - } - - /*--- Contribution to implicit part ---*/ - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - val_Jacobian_ii[iVar][iVar] -= Epsilon_0*StretchingFactor*MeanLambda; - val_Jacobian_ij[iVar][iVar] += Epsilon_0*StretchingFactor*MeanLambda; - val_Jacobian_ji[iVar][iVar] += Epsilon_0*StretchingFactor*MeanLambda; - val_Jacobian_jj[iVar][iVar] -= Epsilon_0*StretchingFactor*MeanLambda; - } - } - -} - -CAvgGrad_AdjFlow::CAvgGrad_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - unsigned short iDim; - - implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - Mean_Velocity = new su2double [nDim]; - Mean_GradPhi = new su2double* [nDim]; - for (iDim = 0; iDim < nDim; iDim++) - Mean_GradPhi[iDim] = new su2double [nDim]; - Mean_GradPsiE = new su2double [nDim]; - Edge_Vector = new su2double [nDim]; - -} - -CAvgGrad_AdjFlow::~CAvgGrad_AdjFlow(void) { - delete [] Velocity_i; - delete [] Velocity_j; - delete [] Mean_Velocity; - delete [] Edge_Vector; - delete [] Mean_GradPsiE; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - delete [] Mean_GradPhi[iDim]; -} - -void CAvgGrad_AdjFlow::ComputeResidual(su2double *val_residual_i, su2double *val_residual_j, - su2double **val_Jacobian_ii, su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, su2double **val_Jacobian_jj, CConfig *config) { - unsigned short iDim, jDim; - su2double sq_vel_i, ViscDens_i, XiDens_i; - su2double sq_vel_j, ViscDens_j, XiDens_j; - su2double dist_ij_2, dPhiE_dn; - - su2double Prandtl_Lam = config->GetPrandtl_Lam(); - su2double Prandtl_Turb = config->GetPrandtl_Turb(); - - /*--- States in point i ---*/ - - sq_vel_i = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; - } - Pressure_i = V_i[nDim+1]; - Density_i = V_i[nDim+2]; - Enthalpy_i = V_i[nDim+3]; - SoundSpeed_i = sqrt(fabs(Pressure_i*Gamma/Density_i)); - - /*--- Laminar and Eddy viscosity ---*/ - - Laminar_Viscosity_i = V_i[nDim+5]; - Eddy_Viscosity_i = V_i[nDim+6]; - - ViscDens_i = (Laminar_Viscosity_i + Eddy_Viscosity_i) / Density_i; - XiDens_i = Gamma*(Laminar_Viscosity_i/Prandtl_Lam + Eddy_Viscosity_i/Prandtl_Turb) / Density_i; - - /*--- States in point j ---*/ - - sq_vel_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_j[iDim] = V_j[iDim+1]; - sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; - } - Pressure_j = V_j[nDim+1]; - Density_j = V_j[nDim+2]; - Enthalpy_j = V_j[nDim+3]; - SoundSpeed_j = sqrt(fabs(Pressure_j*Gamma/Density_j)); - - /*--- Laminar and Eddy viscosity ---*/ - - Laminar_Viscosity_j = V_j[nDim+5]; - Eddy_Viscosity_j = V_j[nDim+6]; - - ViscDens_j = (Laminar_Viscosity_j + Eddy_Viscosity_j) / Density_j; - XiDens_j = Gamma*(Laminar_Viscosity_j/Prandtl_Lam + Eddy_Viscosity_j/Prandtl_Turb) / Density_j; - - /*--- Compute vector going from iPoint to jPoint ---*/ - - dist_ij_2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; - dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; - } - - /*--- Average of the derivatives of the adjoint variables ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - Mean_GradPsiE[iDim] = 0.5*(PsiVar_Grad_i[nVar-1][iDim]+PsiVar_Grad_j[nVar-1][iDim]); - for (jDim = 0; jDim < nDim; jDim++) - Mean_GradPhi[iDim][jDim] = 0.5*(PsiVar_Grad_i[iDim+1][jDim]+PsiVar_Grad_j[iDim+1][jDim]); - } - - dPhiE_dn = 0; - for (iDim = 0; iDim < nDim; iDim++) - dPhiE_dn += Mean_GradPsiE[iDim]*Normal[iDim]; - - /*--- Compute the viscous residual and jacobian ---*/ - - GetAdjViscousFlux_Jac(Pressure_i, Pressure_j, Density_i, Density_j, - ViscDens_i, ViscDens_j, Velocity_i, Velocity_j, sq_vel_i, sq_vel_j, - XiDens_i, XiDens_j, Mean_GradPhi, Mean_GradPsiE, - dPhiE_dn, Normal, Edge_Vector, dist_ij_2, val_residual_i, val_residual_j, - val_Jacobian_ii, val_Jacobian_ij, val_Jacobian_ji, val_Jacobian_jj, - implicit); - -} - -CAvgGradCorrected_AdjFlow::CAvgGradCorrected_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - Mean_Velocity = new su2double [nDim]; - - Mean_GradPsiVar = new su2double* [nVar]; - for (unsigned short iVar = 0; iVar < nVar; iVar++) - Mean_GradPsiVar[iVar] = new su2double [nDim]; - - Edge_Vector = new su2double [nDim]; - Proj_Mean_GradPsiVar_Edge = new su2double [nVar]; - - Mean_GradPhi = new su2double* [nDim]; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Mean_GradPhi[iDim] = new su2double [nDim]; - Mean_GradPsiE = new su2double [nDim]; - -} - -CAvgGradCorrected_AdjFlow::~CAvgGradCorrected_AdjFlow(void) { - - delete [] Velocity_i; - delete [] Velocity_j; - delete [] Mean_Velocity; - delete [] Edge_Vector; - delete [] Proj_Mean_GradPsiVar_Edge; - - for (unsigned short iVar = 0; iVar < nVar; iVar++) - delete [] Mean_GradPsiVar[iVar]; - delete [] Mean_GradPsiVar; - - for (unsigned short iDim = 0; iDim < nDim; iDim++) - delete [] Mean_GradPhi[iDim]; - delete [] Mean_GradPhi; - delete [] Mean_GradPsiE; - -} - -void CAvgGradCorrected_AdjFlow::ComputeResidual(su2double *val_residual_i, - su2double *val_residual_j, - su2double **val_Jacobian_ii, - su2double **val_Jacobian_ij, - su2double **val_Jacobian_ji, - su2double **val_Jacobian_jj, - CConfig *config) { - - unsigned short iVar, iDim, jDim; - su2double Density_i, sq_vel_i, Pressure_i, ViscDens_i, XiDens_i; - su2double Density_j, sq_vel_j, Pressure_j, ViscDens_j, XiDens_j; - su2double dist_ij_2, dPhiE_dn; - - su2double Prandtl_Lam = config->GetPrandtl_Lam(); - su2double Prandtl_Turb = config->GetPrandtl_Turb(); - - /*--- States in point i ---*/ - - sq_vel_i = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; - } - Pressure_i = V_i[nDim+1]; - Density_i = V_i[nDim+2]; - Enthalpy_i = V_i[nDim+3]; - - /*--- Laminar and Eddy viscosity ---*/ - - Laminar_Viscosity_i = V_i[nDim+5]; - Eddy_Viscosity_i = V_i[nDim+6]; - - ViscDens_i = (Laminar_Viscosity_i + Eddy_Viscosity_i) / Density_i; - XiDens_i = Gamma*(Laminar_Viscosity_i/Prandtl_Lam + - Eddy_Viscosity_i/Prandtl_Turb) / Density_i; - - /*--- States in point j ---*/ - - sq_vel_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_j[iDim] = V_j[iDim+1]; - sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; - } - Pressure_j = V_j[nDim+1]; - Density_j = V_j[nDim+2]; - Enthalpy_j = V_j[nDim+3]; - - /*--- Laminar and Eddy viscosity ---*/ - - Laminar_Viscosity_j = V_j[nDim+5]; - Eddy_Viscosity_j = V_j[nDim+6]; - - ViscDens_j = (Laminar_Viscosity_j + Eddy_Viscosity_j) / Density_j; - XiDens_j = Gamma*(Laminar_Viscosity_j/Prandtl_Lam + - Eddy_Viscosity_j/Prandtl_Turb) / Density_j; - - /*--- Compute vector going from iPoint to jPoint ---*/ - - dist_ij_2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Mean_Velocity[iDim] = 0.5*(Velocity_i[iDim]+Velocity_j[iDim]); - Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; - dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; - } - - /*--- Mean gradient approximation. Projection of the mean gradient in the direction of the edge, weiss correction ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Proj_Mean_GradPsiVar_Edge[iVar] = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Mean_GradPsiVar[iVar][iDim] = 0.5*(PsiVar_Grad_i[iVar][iDim] + PsiVar_Grad_j[iVar][iDim]); - Proj_Mean_GradPsiVar_Edge[iVar] += Mean_GradPsiVar[iVar][iDim]*Edge_Vector[iDim]; - } - for (iDim = 0; iDim < nDim; iDim++) - Mean_GradPsiVar[iVar][iDim] -= (Proj_Mean_GradPsiVar_Edge[iVar] - - (Psi_j[iVar]-Psi_i[iVar]))*Edge_Vector[iDim]/dist_ij_2; - } - - /*--- Average of the derivatives of the adjoint variables ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - Mean_GradPsiE[iDim] = Mean_GradPsiVar[nVar-1][iDim]; - for (jDim = 0; jDim < nDim; jDim++) - Mean_GradPhi[iDim][jDim] = Mean_GradPsiVar[iDim+1][jDim]; - } - - dPhiE_dn = 0; - for (iDim = 0; iDim < nDim; iDim++) - dPhiE_dn += Mean_GradPsiE[iDim]*Normal[iDim]; - - /*--- Compute the viscous residual and jacobian ---*/ - - GetAdjViscousFlux_Jac(Pressure_i, Pressure_j, Density_i, Density_j, - ViscDens_i, ViscDens_j, Velocity_i, Velocity_j, sq_vel_i, sq_vel_j, - XiDens_i, XiDens_j, Mean_GradPhi, Mean_GradPsiE, - dPhiE_dn, Normal, Edge_Vector, dist_ij_2, val_residual_i, val_residual_j, - val_Jacobian_ii, val_Jacobian_ij, val_Jacobian_ji, val_Jacobian_jj, - implicit); - -} - -CSourceViscous_AdjFlow::CSourceViscous_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - unsigned short iDim; - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Velocity = new su2double [nVar]; - GradDensity = new su2double [nDim]; - GradInvDensity = new su2double [nDim]; - dPoDensity2 = new su2double [nDim]; - alpha = new su2double [nDim]; - beta = new su2double [nDim]; - Sigma_5_vec = new su2double [nDim]; - - GradVel_o_Rho = new su2double* [nDim]; - sigma = new su2double* [nDim]; - Sigma_phi = new su2double* [nDim]; - Sigma_5_Tensor = new su2double* [nDim]; - Sigma = new su2double* [nDim]; - - for (iDim = 0; iDim < nDim; iDim++) { - GradVel_o_Rho[iDim] = new su2double [nDim]; - sigma[iDim] = new su2double [nDim]; - Sigma_phi[iDim] = new su2double [nDim]; - Sigma_5_Tensor[iDim] = new su2double [nDim]; - Sigma[iDim] = new su2double [nDim]; - } - -} - -CSourceViscous_AdjFlow::~CSourceViscous_AdjFlow(void) { - unsigned short iDim; - - for (iDim = 0; iDim < nDim; iDim++) { - delete [] GradVel_o_Rho[iDim]; - delete [] sigma[iDim]; - delete [] Sigma_phi[iDim]; - delete [] Sigma_5_Tensor[iDim]; - delete [] Sigma[iDim]; - } - - delete [] GradVel_o_Rho; - delete [] sigma; - delete [] Sigma_phi; - delete [] Sigma_5_Tensor; - delete [] Sigma; - - delete [] Velocity; - delete [] GradDensity; - delete [] GradInvDensity; - delete [] dPoDensity2; - delete [] alpha; - delete [] beta; - delete [] Sigma_5_vec; - -} - -void CSourceViscous_AdjFlow::ComputeResidual (su2double *val_residual, CConfig *config) { - - unsigned short iDim, jDim; - -// su2double Temperature = V_i[0]; - su2double Pressure = V_i[nDim+1]; - su2double Density = V_i[nDim+2]; -// su2double Enthalpy = V_i[nDim+3]; - su2double Laminar_Viscosity = V_i[nDim+5]; - su2double Eddy_Viscosity = V_i[nDim+6]; - -// su2double Energy = Enthalpy - Pressure/Density; - su2double invDensity = 1.0/Density; - su2double invDensitysq = invDensity*invDensity; - su2double invDensitycube = invDensitysq*invDensity; - su2double Prandtl_Lam = config->GetPrandtl_Lam(); - su2double Prandtl_Turb = config->GetPrandtl_Turb(); - su2double mu_tot_1 = Laminar_Viscosity + Eddy_Viscosity; - su2double mu_tot_2 = Laminar_Viscosity/Prandtl_Lam + Eddy_Viscosity/Prandtl_Turb; -// su2double Gas_Constant = config->GetGas_ConstantND(); - - /*--- Required gradients of the flow variables, point j ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - - /*--- Gradient density ---*/ - - GradDensity[iDim] = PrimVar_Grad_i[nDim+2][iDim]; - - /*--- Gradient (1/rho) ---*/ - - GradInvDensity[iDim] = -GradDensity[iDim]*invDensitysq; - - /*--- Computation of the derivatives of P/(Density^2) ---*/ - - dPoDensity2[iDim] = (PrimVar_Grad_i[nVar-1][iDim]*Density - 2.0*GradDensity[iDim]*Pressure)*invDensitycube; - - /*--- Abbreviations: alpha, beta, sigma_5_vec ---*/ - - alpha[iDim] = Gamma*mu_tot_2*GradInvDensity[iDim]; - beta[iDim] = Gamma*mu_tot_2*dPoDensity2[iDim]/Gamma_Minus_One; - Sigma_5_vec[iDim] = Gamma*mu_tot_2*PsiVar_Grad_i[nVar-1][iDim]; - - } - - /*--- Definition of tensors and derivatives of velocity over density ---*/ - - su2double div_vel = 0.0, div_phi = 0.0, vel_gradpsi5 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - div_vel += PrimVar_Grad_i[iDim+1][iDim]; - div_phi += PsiVar_Grad_i[iDim+1][iDim]; - vel_gradpsi5 += V_i[iDim+1]*PsiVar_Grad_i[nVar-1][iDim]; - for (jDim = 0; jDim < nDim; jDim++) { - sigma[iDim][jDim] = mu_tot_1*(PrimVar_Grad_i[iDim+1][jDim]+PrimVar_Grad_i[jDim+1][iDim]); - Sigma_phi[iDim][jDim] = mu_tot_1*(PsiVar_Grad_i[iDim+1][jDim]+PsiVar_Grad_i[jDim+1][iDim]); - Sigma_5_Tensor[iDim][jDim] = mu_tot_1*(V_i[jDim+1]*PsiVar_Grad_i[nVar-1][iDim]+V_i[iDim+1]*PsiVar_Grad_i[nVar-1][jDim]); - GradVel_o_Rho[iDim][jDim] = (PrimVar_Grad_i[iDim+1][jDim]*Density - V_i[iDim+1]*GradDensity[jDim])*invDensitysq; - } - } - - for (iDim = 0; iDim < nDim; iDim++) { - sigma[iDim][iDim] -= TWO3*mu_tot_1*div_vel; - Sigma_phi[iDim][iDim] -= TWO3*mu_tot_1*div_phi; - Sigma_5_Tensor[iDim][iDim] -= TWO3*mu_tot_1*vel_gradpsi5; - } - - for (iDim = 0; iDim < nDim; iDim++) { - for (jDim = 0; jDim < nDim; jDim++) { - Sigma[iDim][jDim] = Sigma_phi[iDim][jDim] + Sigma_5_Tensor[iDim][jDim]; - } - } - - /*--- Vector-Tensors products ---*/ - - su2double gradT_gradpsi5 = 0.0, sigma_gradpsi = 0.0, vel_sigma_gradpsi5 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - gradT_gradpsi5 += PrimVar_Grad_i[0][iDim]*PsiVar_Grad_i[nVar-1][iDim]; - for (jDim = 0; jDim < nDim; jDim++) { - sigma_gradpsi += sigma[iDim][jDim]*PsiVar_Grad_i[jDim+1][iDim]; - vel_sigma_gradpsi5 += V_i[iDim+1]*sigma[iDim][jDim]*PsiVar_Grad_i[nVar-1][jDim]; - } - } - - /*--- Residuals ---*/ - - su2double alpha_gradpsi5 = 0.0, beta_gradpsi5 = 0.0, Sigma_gradvel_o_rho = 0.0, Sigma5_vel_gradvel = 0.0, sq_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - alpha_gradpsi5 += alpha[iDim]*PsiVar_Grad_i[nVar-1][iDim]; - beta_gradpsi5 += beta[iDim]*PsiVar_Grad_i[nVar-1][iDim]; - for (jDim = 0; jDim < nDim; jDim++) { - Sigma_gradvel_o_rho += Sigma[iDim][jDim]*GradVel_o_Rho[iDim][jDim]; - Sigma5_vel_gradvel += Sigma_5_vec[iDim]*(V_i[jDim+1]*PrimVar_Grad_i[jDim+1][iDim]); - } - sq_vel += V_i[iDim+1]*V_i[iDim+1]; - } - - val_residual[0] = (-vel_sigma_gradpsi5*invDensity + 0.5*sq_vel*alpha_gradpsi5 - - beta_gradpsi5) * Volume; - for (iDim = 0; iDim < nDim; iDim++) { - val_residual[iDim+1] = 0.0; - for (jDim = 0; jDim < nDim; jDim++) { - val_residual[iDim+1] += (sigma[iDim][jDim]*PsiVar_Grad_i[nVar-1][jDim]*invDensity - V_i[iDim+1]*alpha[jDim]*PsiVar_Grad_i[nVar-1][jDim]) * Volume; - } - } - val_residual[nVar-1] = alpha_gradpsi5 * Volume; - -// val_residual[0] += (Sigma5_vel_gradvel*invDensity - Sigma_gradvel_o_rho) * Volume; -// for (iDim = 0; iDim < nDim; iDim++) { -// for (jDim = 0; jDim < nDim; jDim++) { -// val_residual[iDim+1] += (Sigma[iDim][jDim]*GradInvDensity[jDim] - -// Sigma_5_vec[jDim]*PrimVar_Grad_i[iDim+1][jDim]*invDensity) * Volume; -// } -// } - - /*--- Laminar viscosity sensitivity for NS ---*/ - - if (config->GetKind_Solver() != ADJ_RANS) { - -// su2double Temperature_Ref = config->GetTemperature_Ref(); -// su2double Temperature_Dim = Temperature*Temperature_Ref; -// -// su2double S = 0.0; -// if (config->GetSystemMeasurements() == SI) { S = 110.4; } -// if (config->GetSystemMeasurements() == US) { S = 198.72; } -// su2double dVisc_T = ((Laminar_Viscosity)/(2.0*Temperature_Dim*(Temperature_Dim + S)))*(Temperature_Dim + 3.0*S)*Temperature_Ref; -// -// su2double Cp = (Gamma/Gamma_Minus_One)*Gas_Constant; -// su2double kappa_psi = (sigma_gradpsi + vel_sigma_gradpsi5)/mu_tot_1; -// su2double theta = (kappa_psi + Cp/Prandtl_Lam*gradT_gradpsi5)*dVisc_T*Gamma_Minus_One/(Gas_Constant*Density); -// -// val_residual[0] += (theta*(sq_vel-Energy))*Volume; -// for (iDim = 0; iDim < nDim; iDim++) -// val_residual[iDim+1] -= theta*V_i[iDim+1]*Volume; -// val_residual[nVar-1] += theta*Volume; - - } - -// /*--- Coupling terms coming from the continuous adjoint turbulent equations ---*/ -// -// if ((config->GetKind_Solver() == ADJ_RANS) && (!config->GetFrozen_Visc_Cont())) { -// -// /*--- Closure constants ---*/ -// -// su2double cv1_3 = 7.1*7.1*7.1; -// su2double k2 = 0.41*0.41; -// su2double cb1 = 0.1355; -// su2double cw2 = 0.3; -// su2double cw3_6 = pow(2.0,6.0); -// su2double sigma = 2./3.; -// su2double cb2 = 0.622; -// su2double cw1 = cb1/k2+(1+cb2)/sigma; -// -// su2double nu, Ji, Ji_2, Ji_3, fv1; -// nu = Laminar_Viscosity/Density; -// Ji = TurbVar_i[0]/nu; -// Ji_2 = Ji*Ji; -// Ji_3 = Ji_2*Ji; -// fv1 = Ji_3/(Ji_3+cv1_3); -// -// /*--- Contributions due to variation of viscosities ---*/ -// -// su2double Temperature_Ref = config->GetTemperature_Ref(); -// su2double Temperature_Dim = Temperature*Temperature_Ref; -// -// su2double S = 0.0; -// if (config->GetSystemMeasurements() == SI) { S = 110.4; } -// if (config->GetSystemMeasurements() == US) { S = 198.72; } -// su2double dVisc_T = ((Laminar_Viscosity)/(2.0*Temperature_Dim*(Temperature_Dim + S)))*(Temperature_Dim + 3.0*S)*Temperature_Ref; -// -// su2double Cp = (Gamma/Gamma_Minus_One)*Gas_Constant; -// su2double kappa_psi = (sigma_gradpsi + vel_sigma_gradpsi5)/mu_tot_1 + Cp/Prandtl_Turb*gradT_gradpsi5; -// su2double cv1_const = 3.0*cv1_3/(Ji_3+cv1_3); -// su2double theta = (kappa_psi*(1.0-Eddy_Viscosity/Laminar_Viscosity*cv1_const) - -// Cp/Prandtl_Turb*gradT_gradpsi5*(1.0-Prandtl_Turb/Prandtl_Lam))*dVisc_T*Gamma_Minus_One/(Gas_Constant*Density); -// su2double xi = kappa_psi*(1.0+cv1_const)*Eddy_Viscosity/Density; -// -// val_residual[0] += (theta*(sq_vel-Energy) + xi)*Volume; -// for (iDim = 0; iDim < nDim; iDim++) -// val_residual[iDim+1] -= theta*V_i[iDim+1]*Volume; -// val_residual[nVar-1] += theta*Volume; -// -// /*--- Coupling residuals ---*/ -// -// if (dist_i > 0.0) { -// su2double fv2, Omega, Shat, dist_0_2, one_o_oneplusJifv1; -// su2double r, g, g_6, glim, fw; -// su2double dfw_g, dg_r, dr_nuhat, dr_Shat; -// su2double dShat_fv2, dfv2_fv1, dfv1_Ji, dJi_nu, dJi_nuhat, dfv2_Ji; -// -// /*--- Vorticity ---*/ -// Omega = (PrimVar_Grad_i[1][1]-PrimVar_Grad_i[2][0])*(PrimVar_Grad_i[1][1]-PrimVar_Grad_i[2][0]); -// if (nDim == 3) Omega += (PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0])*(PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0]) + -// (PrimVar_Grad_i[2][2]-PrimVar_Grad_i[3][1])*(PrimVar_Grad_i[2][2]-PrimVar_Grad_i[3][1]); -// Omega = sqrt(Omega); -// -// dist_0_2 = dist_i*dist_i; -// one_o_oneplusJifv1 = 1.0/(1.0+Ji*fv1); -// fv2 = 1.0 - Ji*one_o_oneplusJifv1; -// Shat = max(Omega + TurbVar_i[0]*fv2/(k2*dist_0_2), TURB_EPS); -// -// r = min(TurbVar_i[0]/(Shat*k2*dist_0_2), 10.); -// g = r + cw2*(pow(r,6.)-r); -// g_6 = pow(g,6.); -// glim = pow((1+cw3_6)/(g_6+cw3_6),1./6.); -// fw = g*glim; -// -// dfw_g = glim*cw3_6/(g_6+cw3_6); -// dg_r = 1.0 + cw2*(6.0*pow(r,5.0)-1.0); -// dr_nuhat = 1.0/(Shat*k2*dist_0_2); -// dr_Shat = -dr_nuhat*TurbVar_i[0]/Shat; -// -// dShat_fv2 = TurbVar_i[0]/(k2*dist_0_2); -// dfv2_fv1 = Ji_2*one_o_oneplusJifv1*one_o_oneplusJifv1; -// dfv1_Ji = 3.0*cv1_3*Ji_2/((Ji_3+cv1_3)*(Ji_3+cv1_3)); -// dJi_nuhat = 1.0/nu; -// dJi_nu = -Ji/nu; -// dfv2_Ji = -one_o_oneplusJifv1*one_o_oneplusJifv1; -// -// /*--- Terms 1 & 2: -Fcv\B7nabla(TurbPsi_i) - Fs\B7TurbPsi_i ---*/ -// -// su2double gradTurbVar_gradTurbPsi = 0, vel_gradTurbPsi = 0; -// for (iDim = 0; iDim < nDim; iDim++) { -// gradTurbVar_gradTurbPsi += TurbVar_Grad_i[0][iDim]*TurbPsi_Grad_i[0][iDim]; -// vel_gradTurbPsi += V_i[iDim+1]*TurbPsi_Grad_i[0][iDim]; -// } -// -// su2double alpha_coeff = Gamma_Minus_One/(Gas_Constant*Density)*dVisc_T; -// su2double beta_coeff = alpha_coeff*(sq_vel-Energy)-Laminar_Viscosity_i/Density; -// su2double Fs_coeff = TurbPsi_i[0]*(cb1*TurbVar_i[0]-cw1*TurbVar_i[0]*TurbVar_i[0]/dist_0_2*dfw_g*dg_r*dr_Shat)* -// dShat_fv2*(dfv2_Ji+dfv2_fv1*dfv1_Ji)*dJi_nu; -// su2double Gamma = Fs_coeff - gradTurbVar_gradTurbPsi/sigma; -// -// val_residual[0] -= (Gamma*beta_coeff - TurbVar_i[0]*vel_gradTurbPsi)/Density*Volume; -// for (iDim = 0; iDim < nDim; iDim++) -// val_residual[iDim+1] += (Gamma*alpha_coeff*V_i[iDim+1] - TurbVar_i[0]*TurbPsi_Grad_i[0][iDim])/Density*Volume; -// val_residual[nVar-1] -= (Gamma*alpha_coeff)/Density*Volume; -// -// // this should improve stability (when commented): -// /*--- Terms 3: -partial{T^s}_GradVel x GradN ---*/ -// // su2double Ms_coeff = (cb1*TurbVar_i[0]-cw1*TurbVar_i[0]*TurbVar_i[0]/dist_0_2*dfw_g*dg_r*dr_Shat); -// // Ms_coeff *= TurbPsi_i[0]/(Omega + TURB_EPS); -// // -// // for (iDim = 0; iDim < nDim; iDim++) { -// // for (jDim = 0; jDim < nDim; jDim++) { -// // val_residual[0] += Ms_coeff*(PrimVar_Grad_i[iDim+1][jDim]-PrimVar_Grad_i[jDim+1][iDim])* -// // GradVel_o_Rho[iDim][jDim]*dV; -// // val_residual[iDim+1] -= Ms_coeff*(PrimVar_Grad_i[iDim+1][jDim]-PrimVar_Grad_i[jDim+1][iDim])* -// // GradInvDensity[jDim]*dV; -// // } -// // } -// -// } -// } - -} - -CSourceConservative_AdjFlow::CSourceConservative_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Velocity = new su2double [nDim]; - Residual_i = new su2double [nVar]; - Residual_j = new su2double [nVar]; - Mean_Residual = new su2double [nVar]; - - Mean_PrimVar_Grad = new su2double* [nVar]; - for (unsigned short iVar = 0; iVar < nVar; iVar++) - Mean_PrimVar_Grad[iVar] = new su2double [nDim]; -} - -CSourceConservative_AdjFlow::~CSourceConservative_AdjFlow(void) { - delete [] Mean_Residual; - delete [] Residual_j; - delete [] Residual_i; - delete [] Velocity; - - for (unsigned short iVar = 0; iVar < nVar; iVar++) - delete [] Mean_PrimVar_Grad[iVar]; - delete [] Mean_PrimVar_Grad; -} - -void CSourceConservative_AdjFlow::ComputeResidual (su2double *val_residual, CConfig *config) { - unsigned short iDim, jDim, iVar; - su2double rho, nu, Ji, fv1, fv2, Omega, Shat, dist_sq, Ji_2, Ji_3, one_o_oneplusJifv1; - su2double r, g, g_6, glim, dfw_g, dg_r, dr_nuhat, dr_Shat, Ms_coeff, invOmega; - - su2double cv1_3 = 7.1*7.1*7.1; - su2double k2 = 0.41*0.41; - su2double cb1 = 0.1355; - su2double cw2 = 0.3; - su2double cw3_6 = pow(2.0,6.0); - su2double sigma = 2./3.; - su2double cb2 = 0.622; - su2double cw1 = cb1/k2+(1+cb2)/sigma; - - for (iVar = 0; iVar < nVar; iVar++) { - Residual_i[iVar] = 0.0; - Residual_j[iVar] = 0.0; - } - - /*--- iPoint ---*/ - - /*--- Density and velocities ---*/ - - rho = U_i[0]; - for (iDim = 0; iDim < nDim; iDim++) - Velocity[iDim] = U_i[iDim+1]/rho; - - /*--- Vorticity ---*/ - - Omega = (PrimVar_Grad_i[1][1]-PrimVar_Grad_i[2][0])*(PrimVar_Grad_i[1][1]-PrimVar_Grad_i[2][0]); - if (nDim == 3) Omega += (PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0])*(PrimVar_Grad_i[1][2]-PrimVar_Grad_i[3][0]) + - (PrimVar_Grad_i[2][2]-PrimVar_Grad_i[3][1])*(PrimVar_Grad_i[2][2]-PrimVar_Grad_i[3][1]); - Omega = sqrt(Omega); - invOmega = 1.0/(Omega + TURB_EPS); - - /*--- Compute Ms_coeff -> coming from partial derivatives ---*/ - - Ms_coeff = 0.0; - if (dist_i > 0) { - dist_sq = dist_i*dist_i; - nu = Laminar_Viscosity_i/rho; - Ji = TurbVar_i[0]/nu; - Ji_2 = Ji*Ji; - Ji_3 = Ji_2*Ji; - fv1 = Ji_3/(Ji_3+cv1_3); - one_o_oneplusJifv1 = 1.0/(1.0+Ji*fv1); - fv2 = 1.0 - Ji*one_o_oneplusJifv1; - Shat = max(Omega + TurbVar_i[0]*fv2/(k2*dist_sq), TURB_EPS); - - r = min(TurbVar_i[0]/(Shat*k2*dist_sq),10.); - g = r + cw2*(pow(r,6.)-r); - g_6 = pow(g,6.); - glim = pow((1+cw3_6)/(g_6+cw3_6),1./6.); - - dfw_g = glim*cw3_6/(g_6+cw3_6); - dg_r = 1.0 + cw2*(6.0*pow(r,5.0)-1.0); - dr_nuhat = 1.0/(Shat*k2*dist_sq); - dr_Shat = -dr_nuhat*TurbVar_i[0]/Shat; - - Ms_coeff = (cb1*TurbVar_i[0]-cw1*TurbVar_i[0]*TurbVar_i[0]/dist_sq*dfw_g*dg_r*dr_Shat); - } - Ms_coeff *= TurbPsi_i[0]*invOmega/rho; - - /*--- Compute residual of iPoint ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - for (jDim = 0; jDim < nDim; jDim++) { - Residual_i[0] -= Ms_coeff*(Velocity[jDim]*PrimVar_Grad_i[jDim+1][iDim]*Normal[iDim] - - Velocity[jDim]*PrimVar_Grad_i[iDim+1][jDim]*Normal[iDim]); - Residual_i[iDim+1] += Ms_coeff*(PrimVar_Grad_i[iDim+1][jDim]*Normal[jDim] - - PrimVar_Grad_i[jDim+1][iDim]*Normal[jDim]); - } - } - - /*--- jPoint ---*/ - - /*--- Density and velocities ---*/ - - rho = U_j[0]; - for (iDim = 0; iDim < nDim; iDim++) - Velocity[iDim] = U_j[iDim+1]/rho; - - /*--- Vorticity ---*/ - - Omega = (PrimVar_Grad_j[1][1]-PrimVar_Grad_j[2][0])*(PrimVar_Grad_j[1][1]-PrimVar_Grad_j[2][0]); - if (nDim == 3) Omega += (PrimVar_Grad_j[1][2]-PrimVar_Grad_j[3][0])*(PrimVar_Grad_j[1][2]-PrimVar_Grad_j[3][0]) + - (PrimVar_Grad_j[2][2]-PrimVar_Grad_j[3][1])*(PrimVar_Grad_j[2][2]-PrimVar_Grad_j[3][1]); - Omega = sqrt(Omega); - invOmega = 1.0/(Omega + TURB_EPS); - - /*--- Compute Ms_coeff -> coming from partial derivatives ---*/ - - Ms_coeff = 0.0; - if (dist_j > 0) { - dist_sq = dist_j*dist_j; - nu = Laminar_Viscosity_j/rho; - Ji = TurbVar_j[0]/nu; - Ji_2 = Ji*Ji; - Ji_3 = Ji_2*Ji; - fv1 = Ji_3/(Ji_3+cv1_3); - one_o_oneplusJifv1 = 1.0/(1.0+Ji*fv1); - fv2 = 1.0 - Ji*one_o_oneplusJifv1; - Shat = max(Omega + TurbVar_j[0]*fv2/(k2*dist_sq), TURB_EPS); - - r = min(TurbVar_j[0]/(Shat*k2*dist_sq),10.); - g = r + cw2*(pow(r,6.)-r); - g_6 = pow(g,6.); - glim = pow((1+cw3_6)/(g_6+cw3_6),1./6.); - - dfw_g = glim*cw3_6/(g_6+cw3_6); - dg_r = 1.0 + cw2*(6.0*pow(r,5.0)-1.0); - dr_nuhat = 1.0/(Shat*k2*dist_sq); - dr_Shat = -dr_nuhat*TurbVar_j[0]/Shat; - - Ms_coeff = (cb1*TurbVar_j[0]-cw1*TurbVar_j[0]*TurbVar_j[0]/dist_sq*dfw_g*dg_r*dr_Shat); - } - Ms_coeff *= TurbPsi_j[0]*invOmega/rho; - - /*--- Compute residual of jPoint ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - for (jDim = 0; jDim < nDim; jDim++) { - Residual_j[0] -= Ms_coeff*(Velocity[jDim]*PrimVar_Grad_j[jDim+1][iDim]*Normal[iDim] - - Velocity[jDim]*PrimVar_Grad_j[iDim+1][jDim]*Normal[iDim]); - Residual_j[iDim+1] += Ms_coeff*(PrimVar_Grad_j[iDim+1][jDim]*Normal[jDim] - - PrimVar_Grad_j[jDim+1][iDim]*Normal[jDim]); - } - } - - /*--- Compute the mean residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] = 0.5*(Residual_i[iVar] + Residual_j[iVar]); - -} - -CSourceRotatingFrame_AdjFlow::CSourceRotatingFrame_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { } - -CSourceRotatingFrame_AdjFlow::~CSourceRotatingFrame_AdjFlow(void) { } - -void CSourceRotatingFrame_AdjFlow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) { - - unsigned short iDim, iVar, jVar; - su2double Omega[3] = {0,0,0}, Phi[3] = {0,0,0}; - bool implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); - - /*--- Retrieve the angular velocity vector from config. ---*/ - - for (iDim = 0; iDim < 3; iDim++){ - Omega[iDim] = config->GetRotation_Rate(iDim)/config->GetOmega_Ref(); - } - - /*--- Get the adjoint velocity vector at the current node. ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - Phi[iDim] = Psi_i[iDim+1]; - - /*--- Compute the source term as the Jacobian of the rotating frame - source term multiplied by the adjoint state and the dual cell volume. ---*/ - - if (nDim == 2) { - val_residual[0] = 0.0; - val_residual[1] = Omega[2]*Phi[1]*Volume; - val_residual[2] = -Omega[2]*Phi[0]*Volume; - val_residual[3] = 0.0; - } else { - val_residual[0] = 0.0; - val_residual[1] = (Omega[2]*Phi[1] - Omega[1]*Phi[2])*Volume; - val_residual[2] = (Omega[0]*Phi[2] - Omega[2]*Phi[0])*Volume; - val_residual[3] = (Omega[1]*Phi[0] - Omega[0]*Phi[1])*Volume; - val_residual[4] = 0.0; - } - - /*--- Calculate the source term Jacobian ---*/ - - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_i[iVar][jVar] = 0.0; - if (nDim == 2) { - val_Jacobian_i[1][2] = Omega[2]*Volume; - val_Jacobian_i[2][1] = -Omega[2]*Volume; - } else { - val_Jacobian_i[1][2] = Omega[2]*Volume; - val_Jacobian_i[1][3] = -Omega[1]*Volume; - val_Jacobian_i[2][1] = -Omega[2]*Volume; - val_Jacobian_i[2][3] = Omega[0]*Volume; - val_Jacobian_i[3][1] = Omega[1]*Volume; - val_Jacobian_i[3][2] = -Omega[0]*Volume; - } - } - -} - -CSourceAxisymmetric_AdjFlow::CSourceAxisymmetric_AdjFlow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { } - -CSourceAxisymmetric_AdjFlow::~CSourceAxisymmetric_AdjFlow(void) { } - -void CSourceAxisymmetric_AdjFlow::ComputeResidual(su2double *val_residual, su2double **Jacobian_ii, CConfig *config) { - - su2double yinv; - su2double Jacobian_Axisymmetric[4][4]; - - if (Coord_i[1] > 0.0) yinv = 1.0/Coord_i[1]; - else yinv = 0.0; - - Jacobian_Axisymmetric[0][0] = 0; - Jacobian_Axisymmetric[0][1] = 0; - Jacobian_Axisymmetric[0][2] = 1.; - Jacobian_Axisymmetric[0][3] = 0; - - Jacobian_Axisymmetric[1][0] = -U_i[1]*U_i[2]/(U_i[0]*U_i[0]); - Jacobian_Axisymmetric[1][1] = U_i[2]/U_i[0]; - Jacobian_Axisymmetric[1][2] = U_i[1]/U_i[0]; - Jacobian_Axisymmetric[1][3] = 0; - - Jacobian_Axisymmetric[2][0] = -U_i[2]*U_i[2]/(U_i[0]*U_i[0]); - Jacobian_Axisymmetric[2][1] = 0; - Jacobian_Axisymmetric[2][2] = 2*U_i[2]/U_i[0]; - Jacobian_Axisymmetric[2][3] = 0; - - Jacobian_Axisymmetric[3][0] = -Gamma*U_i[2]*U_i[3]/(U_i[0]*U_i[0]) + (Gamma-1)*U_i[2]*(U_i[1]*U_i[1]+U_i[2]*U_i[2])/(U_i[0]*U_i[0]*U_i[0]); - Jacobian_Axisymmetric[3][1] = -(Gamma-1)*U_i[2]*U_i[1]/(U_i[0]*U_i[0]); - Jacobian_Axisymmetric[3][2] = Gamma*U_i[3]/U_i[0] - 1/2*(Gamma-1)*( (U_i[1]*U_i[1]+U_i[2]*U_i[2])/(U_i[0]*U_i[0]) + 2*U_i[2]*U_i[2]/(U_i[0]*U_i[0]) ); - Jacobian_Axisymmetric[3][3] = Gamma*U_i[2]/U_i[0]; - - for (int iVar=0; iVar<4; iVar++) - for (int jVar=0; jVar<4; jVar++) - Jacobian_Axisymmetric[iVar][jVar] *= yinv*Volume; - - /* -- Residual = transpose(Jacobian) * psi --*/ - for (int iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = 0.0; - for (int jVar = 0; jVar < nVar; jVar++) { - val_residual[iVar] += Jacobian_Axisymmetric[jVar][iVar]*Psi_i[jVar]; - Jacobian_ii[iVar][jVar] = Jacobian_Axisymmetric[jVar][iVar]; - } - } -} diff --git a/SU2_CFD/src/numerics_direct_mean.cpp b/SU2_CFD/src/numerics_direct_mean.cpp deleted file mode 100644 index 828cd6883de5..000000000000 --- a/SU2_CFD/src/numerics_direct_mean.cpp +++ /dev/null @@ -1,5210 +0,0 @@ -/*! - * \file numerics_direct_mean.cpp - * \brief This file contains the numerical methods for compressible flow. - * \author F. Palacios, T. Economon - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - - -#include "../include/numerics_structure.hpp" -#include - -CCentBase_Flow::CCentBase_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : - CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - /* 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(); - fix_factor = config->GetCent_Jac_Fix_Factor(); - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - /*--- Allocate required structures ---*/ - Diff_U = new su2double [nVar]; - Diff_Lapl = new su2double [nVar]; - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - MeanVelocity = new su2double [nDim]; - ProjFlux = new su2double [nVar]; -} - -CCentBase_Flow::~CCentBase_Flow(void) { - delete [] Diff_U; - delete [] Diff_Lapl; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] MeanVelocity; - delete [] ProjFlux; -} - -void CCentBase_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, - CConfig *config) { - - su2double U_i[5] = {0.0,0.0,0.0,0.0,0.0}, U_j[5] = {0.0,0.0,0.0,0.0,0.0}; - - bool preacc = SetPreaccInVars(); - - if (preacc) { - AD::SetPreaccIn(Normal, nDim); - AD::SetPreaccIn(V_i, nDim+5); AD::SetPreaccIn(V_j, nDim+5); - AD::SetPreaccIn(Lambda_i); AD::SetPreaccIn(Lambda_j); - if (dynamic_grid) { - AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); - } - } - - /*--- Pressure, density, enthalpy, energy, and velocity at points i and j ---*/ - - Pressure_i = V_i[nDim+1]; Pressure_j = V_j[nDim+1]; - Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; - Enthalpy_i = V_i[nDim+3]; Enthalpy_j = V_j[nDim+3]; - SoundSpeed_i = V_i[nDim+4]; SoundSpeed_j = V_j[nDim+4]; - Energy_i = Enthalpy_i - Pressure_i/Density_i; Energy_j = Enthalpy_j - Pressure_j/Density_j; - - sq_vel_i = 0.0; sq_vel_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity_j[iDim] = V_j[iDim+1]; - sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; - sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; - } - - /*--- Recompute conservative variables ---*/ - - U_i[0] = Density_i; U_j[0] = Density_j; - for (iDim = 0; iDim < nDim; iDim++) { - U_i[iDim+1] = Density_i*Velocity_i[iDim]; U_j[iDim+1] = Density_j*Velocity_j[iDim]; - } - U_i[nDim+1] = Density_i*Energy_i; U_j[nDim+1] = Density_j*Energy_j; - - /*--- Compute mean values of the variables ---*/ - - MeanDensity = 0.5*(Density_i+Density_j); - MeanPressure = 0.5*(Pressure_i+Pressure_j); - MeanEnthalpy = 0.5*(Enthalpy_i+Enthalpy_j); - for (iDim = 0; iDim < nDim; iDim++) - MeanVelocity[iDim] = 0.5*(Velocity_i[iDim]+Velocity_j[iDim]); - MeanEnergy = 0.5*(Energy_i+Energy_j); - - /*--- Get projected flux tensor ---*/ - - GetInviscidProjFlux(&MeanDensity, MeanVelocity, &MeanPressure, &MeanEnthalpy, Normal, ProjFlux); - - /*--- Residual of the inviscid flux ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] = ProjFlux[iVar]; - - /*--- Jacobians of the inviscid flux, scale = 0.5 because val_residual ~ 0.5*(fc_i+fc_j)*Normal ---*/ - - if (implicit) { - GetInviscidProjJac(MeanVelocity, &MeanEnergy, Normal, 0.5, val_Jacobian_i); - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_j[iVar][jVar] = val_Jacobian_i[iVar][jVar]; - } - - /*--- Adjustment due to grid motion ---*/ - - if (dynamic_grid) { - ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] -= ProjGridVel * 0.5*(U_i[iVar] + U_j[iVar]); - if (implicit) { - val_Jacobian_i[iVar][iVar] -= 0.5*ProjGridVel; - val_Jacobian_j[iVar][iVar] -= 0.5*ProjGridVel; - } - } - } - - /*--- Compute the local spectral radius and the stretching factor ---*/ - - ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; - Area += Normal[iDim]*Normal[iDim]; - } - Area = sqrt(Area); - - /*--- Adjustment due to mesh motion ---*/ - - if (dynamic_grid) { - ProjVelocity_i -= ProjGridVel; - ProjVelocity_j -= ProjGridVel; - } - - /*--- Dissipation term ---*/ - - Local_Lambda_i = (fabs(ProjVelocity_i)+SoundSpeed_i*Area); - Local_Lambda_j = (fabs(ProjVelocity_j)+SoundSpeed_j*Area); - MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); - - Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); - Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); - StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); - - /*--- Compute differences btw. conservative variables, with a correction for enthalpy ---*/ - - for (iVar = 0; iVar < nVar-1; iVar++) { - Diff_U[iVar] = U_i[iVar]-U_j[iVar]; - } - Diff_U[nVar-1] = Density_i*Enthalpy_i-Density_j*Enthalpy_j; - - DissipationTerm(val_residual, val_Jacobian_i, val_Jacobian_j); - - if (preacc) { - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - } -} - -void CCentBase_Flow::ScalarDissipationJacobian(su2double **val_Jacobian_i, su2double **val_Jacobian_j) { - - /*--- n-1 diagonal entries ---*/ - - for (iVar = 0; iVar < (nVar-1); iVar++) { - val_Jacobian_i[iVar][iVar] += fix_factor*cte_0; - val_Jacobian_j[iVar][iVar] -= fix_factor*cte_1; - } - - /*--- Last row of Jacobian_i ---*/ - - val_Jacobian_i[nVar-1][0] += fix_factor*cte_0*Gamma_Minus_One*sq_vel_i; - for (iDim = 0; iDim < nDim; iDim++) - val_Jacobian_i[nVar-1][iDim+1] -= fix_factor*cte_0*Gamma_Minus_One*Velocity_i[iDim]; - val_Jacobian_i[nVar-1][nVar-1] += fix_factor*cte_0*Gamma; - - /*--- Last row of Jacobian_j ---*/ - - val_Jacobian_j[nVar-1][0] -= fix_factor*cte_1*Gamma_Minus_One*sq_vel_j; - for (iDim = 0; iDim < nDim; iDim++) - val_Jacobian_j[nVar-1][iDim+1] += fix_factor*cte_1*Gamma_Minus_One*Velocity_j[iDim]; - val_Jacobian_j[nVar-1][nVar-1] -= fix_factor*cte_1*Gamma; - -} - -CCentJST_Flow::CCentJST_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : - CCentBase_Flow(val_nDim, val_nVar, config) { - - /*--- Artifical dissipation parameters ---*/ - Param_p = 0.3; - Param_Kappa_2 = config->GetKappa_2nd_Flow(); - Param_Kappa_4 = config->GetKappa_4th_Flow(); - -} - -CCentJST_Flow::~CCentJST_Flow(void) { - -} - -void CCentJST_Flow::DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) { - - /*--- Compute differences btw. Laplacians ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Diff_Lapl[iVar] = Und_Lapl_i[iVar]-Und_Lapl_j[iVar]; - } - - /*--- Compute dissipation coefficients ---*/ - - sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); - sc4 = sc2*sc2/4.0; - - Epsilon_2 = Param_Kappa_2*0.5*(Sensor_i+Sensor_j)*sc2; - Epsilon_4 = max(0.0, Param_Kappa_4-Epsilon_2)*sc4; - - /*--- Compute viscous part of the residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] += (Epsilon_2*Diff_U[iVar] - Epsilon_4*Diff_Lapl[iVar])*StretchingFactor*MeanLambda; - - /*--- Jacobian computation ---*/ - - if (implicit) { - - cte_0 = (Epsilon_2 + Epsilon_4*su2double(Neighbor_i+1))*StretchingFactor*MeanLambda; - cte_1 = (Epsilon_2 + Epsilon_4*su2double(Neighbor_j+1))*StretchingFactor*MeanLambda; - - ScalarDissipationJacobian(val_Jacobian_i, val_Jacobian_j); - } -} - -bool CCentJST_Flow::SetPreaccInVars(void) { - AD::StartPreacc(); - AD::SetPreaccIn(Sensor_i); AD::SetPreaccIn(Und_Lapl_i, nVar); - AD::SetPreaccIn(Sensor_j); AD::SetPreaccIn(Und_Lapl_j, nVar); - return true; -} - -CCentJST_KE_Flow::CCentJST_KE_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : - CCentBase_Flow(val_nDim, val_nVar, config) { - - /*--- Artifical dissipation parameters ---*/ - Param_p = 0.3; - Param_Kappa_2 = config->GetKappa_2nd_Flow(); - -} - -CCentJST_KE_Flow::~CCentJST_KE_Flow(void) { - -} - -void CCentJST_KE_Flow::DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) { - - /*--- Compute dissipation coefficient ---*/ - - sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); - Epsilon_2 = Param_Kappa_2*0.5*(Sensor_i+Sensor_j)*sc2; - - /*--- Compute viscous part of the residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] += Epsilon_2*(Diff_U[iVar])*StretchingFactor*MeanLambda; - - /*--- Jacobian computation ---*/ - - if (implicit) { - - cte_0 = Epsilon_2*StretchingFactor*MeanLambda; - cte_1 = cte_0; - - ScalarDissipationJacobian(val_Jacobian_i, val_Jacobian_j); - } -} - -bool CCentJST_KE_Flow::SetPreaccInVars(void) { - AD::StartPreacc(); - AD::SetPreaccIn(Sensor_i); AD::SetPreaccIn(Sensor_j); - return true; -} - -CCentLax_Flow::CCentLax_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : - CCentBase_Flow(val_nDim, val_nVar, config) { - - /*--- Artifical dissipation parameters ---*/ - Param_p = 0.3; - Param_Kappa_0 = config->GetKappa_1st_Flow(); - -} - -CCentLax_Flow::~CCentLax_Flow(void) { - -} - -void CCentLax_Flow::DissipationTerm(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j) { - - /*--- Compute dissipation coefficient ---*/ - - sc0 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); - Epsilon_0 = Param_Kappa_0*sc0*su2double(nDim)/3.0; - - /*--- Compute viscous part of the residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] += Epsilon_0*Diff_U[iVar]*StretchingFactor*MeanLambda; - - /*--- Jacobian computation ---*/ - - if (implicit) { - - cte_0 = Epsilon_0*StretchingFactor*MeanLambda; - cte_1 = cte_0; - - ScalarDissipationJacobian(val_Jacobian_i, val_Jacobian_j); - } -} - -bool CCentLax_Flow::SetPreaccInVars(void) { - AD::StartPreacc(); - return true; -} - -CUpwCUSP_Flow::CUpwCUSP_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - if (config->GetDynamic_Grid() && (SU2_MPI::GetRank() == MASTER_NODE)) - cout << "WARNING: Grid velocities are NOT yet considered by the CUSP scheme." << endl; - - /*--- Allocate some structures ---*/ - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - ProjFlux_i = new su2double [nVar]; - ProjFlux_j = new su2double [nVar]; -} - -CUpwCUSP_Flow::~CUpwCUSP_Flow(void) { - delete [] Velocity_i; - delete [] Velocity_j; - delete [] ProjFlux_i; - delete [] ProjFlux_j; -} - -void CUpwCUSP_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, - CConfig *config) { - - unsigned short iDim, iVar; - su2double Diff_U[5] = {0.0,0.0,0.0,0.0,0.0}; - - AD::SetPreaccIn(Normal, nDim); - AD::SetPreaccIn(V_i, nDim+4); - AD::SetPreaccIn(V_j, nDim+4); - - /*--- Pressure, density, enthalpy, energy, and velocity at points i and j ---*/ - - Pressure_i = V_i[nDim+1]; Pressure_j = V_j[nDim+1]; - Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; - Enthalpy_i = V_i[nDim+3]; Enthalpy_j = V_j[nDim+3]; - su2double Energy_i = Enthalpy_i - Pressure_i/Density_i; - su2double Energy_j = Enthalpy_j - Pressure_j/Density_j; - - su2double sq_vel_i = 0.0, sq_vel_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity_j[iDim] = V_j[iDim+1]; - sq_vel_i += Velocity_i[iDim]*Velocity_i[iDim]; - sq_vel_j += Velocity_j[iDim]*Velocity_j[iDim]; - } - - /*-- Face area and unit normal ---*/ - - 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; - - /*--- Computes differences of conservative variables, with a correction for the enthalpy ---*/ - - Diff_U[0] = Density_i - Density_j; - for (iDim = 0; iDim < nDim; iDim++) - Diff_U[iDim+1] = Density_i*Velocity_i[iDim] - Density_j*Velocity_j[iDim]; - Diff_U[nVar-1] = Density_i*Enthalpy_i - Density_j*Enthalpy_j; - - /*--- Get left and right fluxes ---*/ - - GetInviscidProjFlux(&Density_i, Velocity_i, &Pressure_i, &Enthalpy_i, UnitNormal, ProjFlux_i); - GetInviscidProjFlux(&Density_j, Velocity_j, &Pressure_j, &Enthalpy_j, UnitNormal, ProjFlux_j); - - /*--- Compute dissipation parameters based on Roe-averaged values ---*/ - - su2double Beta, Nu_c; - - su2double R = sqrt(Density_j/Density_i), ProjVelocity = 0.0, sq_vel = 0.0; - - for (iDim = 0; iDim < nDim; iDim++) { - su2double MeanVel = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1.0); - ProjVelocity += MeanVel*UnitNormal[iDim]; - sq_vel += MeanVel*MeanVel; - } - su2double MeanEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1.0); - su2double MeanSoundSpeed = sqrt(Gamma_Minus_One*fabs(MeanEnthalpy-0.5*sq_vel)); - - su2double Mach = ProjVelocity / MeanSoundSpeed; - - su2double tmp1 = 0.5*(Gamma+1.0)/Gamma*ProjVelocity; - su2double tmp2 = sqrt(pow(tmp1-ProjVelocity/Gamma, 2.0) + pow(MeanSoundSpeed,2.0)/Gamma); - su2double LamdaNeg = tmp1 - tmp2, LamdaPos = tmp1 + tmp2; - - if (fabs(Mach) >= 1.0) Beta = Mach/fabs(Mach); - else if (Mach >= 0.0) Beta = max(0.0, (ProjVelocity + LamdaNeg)/(ProjVelocity - LamdaNeg)); - else Beta =-max(0.0, (ProjVelocity + LamdaPos)/(ProjVelocity - LamdaPos)); - - if (fabs(Mach) >= 1.0) Nu_c = 0.0; - else { - if (Beta > 0.0) Nu_c =-(1.0+Beta)*LamdaNeg; - else if (Beta < 0.0) Nu_c = (1.0-Beta)*LamdaPos; - /*--- Limit the minimum scalar dissipation ---*/ - else Nu_c = max(fabs(ProjVelocity), config->GetEntropyFix_Coeff()*MeanSoundSpeed); - } - - /*--- Compute the residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] = 0.5*((1.0+Beta)*ProjFlux_i[iVar] + (1.0-Beta)*ProjFlux_j[iVar] + Nu_c*Diff_U[iVar])*Area; - - /*--- Jacobian computation ---*/ - - if (implicit) { - - /*--- Flux average and difference contributions ---*/ - - GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5*(1.0+Beta), val_Jacobian_i); - GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5*(1.0-Beta), val_Jacobian_j); - - /*--- Solution difference (scalar dissipation) contribution ---*/ - - su2double cte_0 = 0.5*Nu_c*Area*config->GetCent_Jac_Fix_Factor(); - - /*--- n-1 diagonal entries ---*/ - - for (iVar = 0; iVar < (nVar-1); iVar++) { - val_Jacobian_i[iVar][iVar] += cte_0; - val_Jacobian_j[iVar][iVar] -= cte_0; - } - - /*--- Last rows ---*/ - - val_Jacobian_i[nVar-1][0] += cte_0*Gamma_Minus_One*0.5*sq_vel_i; - for (iDim = 0; iDim < nDim; iDim++) - val_Jacobian_i[nVar-1][iDim+1] -= cte_0*Gamma_Minus_One*Velocity_i[iDim]; - val_Jacobian_i[nVar-1][nVar-1] += cte_0*Gamma; - - val_Jacobian_j[nVar-1][0] -= cte_0*Gamma_Minus_One*0.5*sq_vel_j; - for (iDim = 0; iDim < nDim; iDim++) - val_Jacobian_j[nVar-1][iDim+1] += cte_0*Gamma_Minus_One*Velocity_j[iDim]; - val_Jacobian_j[nVar-1][nVar-1] -= cte_0*Gamma; - - } - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); -} - -CUpwAUSM_Flow::CUpwAUSM_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - if (config->GetDynamic_Grid() && (SU2_MPI::GetRank() == MASTER_NODE)) - cout << "WARNING: Grid velocities are NOT yet considered in AUSM-type schemes." << endl; - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Diff_U = new su2double [nVar]; - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - RoeVelocity = new su2double [nDim]; - delta_vel = new su2double [nDim]; - delta_wave = new su2double [nVar]; - ProjFlux_i = new su2double [nVar]; - ProjFlux_j = new su2double [nVar]; - Lambda = new su2double [nVar]; - Epsilon = new su2double [nVar]; - P_Tensor = new su2double* [nVar]; - invP_Tensor = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - P_Tensor[iVar] = new su2double [nVar]; - invP_Tensor[iVar] = new su2double [nVar]; - } -} - -CUpwAUSM_Flow::~CUpwAUSM_Flow(void) { - - delete [] Diff_U; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] RoeVelocity; - delete [] delta_vel; - delete [] delta_wave; - delete [] ProjFlux_i; - delete [] ProjFlux_j; - delete [] Lambda; - delete [] Epsilon; - for (iVar = 0; iVar < nVar; iVar++) { - delete [] P_Tensor[iVar]; - delete [] invP_Tensor[iVar]; - } - delete [] P_Tensor; - delete [] invP_Tensor; - -} - -void CUpwAUSM_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - AD::StartPreacc(); - AD::SetPreaccIn(Normal, nDim); - AD::SetPreaccIn(V_i, nDim+4); - AD::SetPreaccIn(V_j, nDim+4); - - /*--- Face area (norm or the normal vector) ---*/ - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim]*Normal[iDim]; - Area = sqrt(Area); - - /*-- Unit Normal ---*/ - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = Normal[iDim]/Area; - - /*--- Primitive variables at point i ---*/ - sq_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - sq_vel += Velocity_i[iDim]*Velocity_i[iDim]; - } - Pressure_i = V_i[nDim+1]; - Density_i = V_i[nDim+2]; - Enthalpy_i = V_i[nDim+3]; - Energy_i = Enthalpy_i - Pressure_i/Density_i; - SoundSpeed_i = sqrt(fabs(Gamma*Gamma_Minus_One*(Energy_i-0.5*sq_vel))); - - /*--- Primitive variables at point j ---*/ - sq_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_j[iDim] = V_j[iDim+1]; - sq_vel += Velocity_j[iDim]*Velocity_j[iDim]; - } - Pressure_j = V_j[nDim+1]; - Density_j = V_j[nDim+2]; - Enthalpy_j = V_j[nDim+3]; - Energy_j = Enthalpy_j - Pressure_j/Density_j; - SoundSpeed_j = sqrt(fabs(Gamma*Gamma_Minus_One*(Energy_j-0.5*sq_vel))); - - /*--- Projected velocities ---*/ - ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; - } - - mL = ProjVelocity_i/SoundSpeed_i; - mR = ProjVelocity_j/SoundSpeed_j; - - if (fabs(mL) <= 1.0) mLP = 0.25*(mL+1.0)*(mL+1.0); - else mLP = 0.5*(mL+fabs(mL)); - - if (fabs(mR) <= 1.0) mRM = -0.25*(mR-1.0)*(mR-1.0); - else mRM = 0.5*(mR-fabs(mR)); - - mF = mLP + mRM; - - if (fabs(mL) <= 1.0) pLP = 0.25*Pressure_i*(mL+1.0)*(mL+1.0)*(2.0-mL); - else pLP = 0.5*Pressure_i*(mL+fabs(mL))/mL; - - if (fabs(mR) <= 1.0) pRM = 0.25*Pressure_j*(mR-1.0)*(mR-1.0)*(2.0+mR); - else pRM = 0.5*Pressure_j*(mR-fabs(mR))/mR; - - pF = pLP + pRM; - Phi = fabs(mF); - - val_residual[0] = 0.5*(mF*((Density_i*SoundSpeed_i)+(Density_j*SoundSpeed_j))-Phi*((Density_j*SoundSpeed_j)-(Density_i*SoundSpeed_i))); - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = 0.5*(mF*((Density_i*SoundSpeed_i*Velocity_i[iDim])+(Density_j*SoundSpeed_j*Velocity_j[iDim])) - -Phi*((Density_j*SoundSpeed_j*Velocity_j[iDim])-(Density_i*SoundSpeed_i*Velocity_i[iDim])))+UnitNormal[iDim]*pF; - val_residual[nVar-1] = 0.5*(mF*((Density_i*SoundSpeed_i*Enthalpy_i)+(Density_j*SoundSpeed_j*Enthalpy_j))-Phi*((Density_j*SoundSpeed_j*Enthalpy_j)-(Density_i*SoundSpeed_i*Enthalpy_i))); - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] *= Area; - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - - /*--- Roe's Jacobian for AUSM (this must be fixed) ---*/ - if (implicit) { - - /*--- Mean Roe variables iPoint and jPoint ---*/ - R = sqrt(fabs(Density_j/Density_i)); - RoeDensity = R*Density_i; - sq_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); - sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; - } - RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); - RoeSoundSpeed = sqrt(fabs((Gamma-1)*(RoeEnthalpy-0.5*sq_vel))); - - /*--- Compute P and Lambda (do it with the Normal) ---*/ - GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, P_Tensor); - - ProjVelocity = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; - ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; - } - - /*--- Flow eigenvalues and Entropy correctors ---*/ - for (iDim = 0; iDim < nDim; iDim++) - Lambda[iDim] = ProjVelocity; - Lambda[nVar-2] = ProjVelocity + RoeSoundSpeed; - Lambda[nVar-1] = ProjVelocity - RoeSoundSpeed; - - /*--- Compute inverse P ---*/ - GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); - - /*--- Jacobias of the inviscid flux, scale = 0.5 because val_residual ~ 0.5*(fc_i+fc_j)*Normal ---*/ - GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5, val_Jacobian_i); - GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5, val_Jacobian_j); - - /*--- Roe's Flux approximation ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - Proj_ModJac_Tensor_ij = 0.0; - /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*fabs(Lambda[kVar])*invP_Tensor[kVar][jVar]; - val_Jacobian_i[iVar][jVar] += 0.5*Proj_ModJac_Tensor_ij*Area; - val_Jacobian_j[iVar][jVar] -= 0.5*Proj_ModJac_Tensor_ij*Area; - } - } - } -} - -CUpwAUSMPLUS_SLAU_Base_Flow::CUpwAUSMPLUS_SLAU_Base_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : - CNumerics(val_nDim, val_nVar, config) { - - if (config->GetDynamic_Grid() && (SU2_MPI::GetRank() == MASTER_NODE)) - cout << "WARNING: Grid velocities are NOT yet considered in AUSM-type schemes." << endl; - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - UseAccurateJacobian = config->GetUse_Accurate_Jacobians(); - HasAnalyticalDerivatives = false; - FinDiffStep = 1e-4; - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - psi_i = new su2double [nVar]; - psi_j = new su2double [nVar]; - - RoeVelocity = new su2double [nDim]; - Lambda = new su2double [nVar]; - Epsilon = new su2double [nVar]; - P_Tensor = new su2double* [nVar]; - invP_Tensor = new su2double* [nVar]; - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - P_Tensor[iVar] = new su2double [nVar]; - invP_Tensor[iVar] = new su2double [nVar]; - } -} - -CUpwAUSMPLUS_SLAU_Base_Flow::~CUpwAUSMPLUS_SLAU_Base_Flow(void) { - - delete [] Velocity_i; - delete [] Velocity_j; - delete [] psi_i; - delete [] psi_j; - - delete [] RoeVelocity; - delete [] Lambda; - delete [] Epsilon; - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - delete [] P_Tensor[iVar]; - delete [] invP_Tensor[iVar]; - } - delete [] P_Tensor; - delete [] invP_Tensor; - -} - -void CUpwAUSMPLUS_SLAU_Base_Flow::ComputeMassAndPressureFluxes(CConfig *config, su2double &mdot, su2double &pressure) -{ - /*--- For schemes that fit in the general form of AUSM+up and SLAU schemes you can inherit from this class - and implement only the specifics, which should be the face mass flux (per unit area) and the face pressure. - For implicit solution methods this class can either approximate the flux Jacobians (using those of the Roe - scheme) or compute accurate ones. This is done either numerically, differentiating "mdot" and "pressure" - using 1st order finite differences, or analytically if you use this function to set the values of - "dmdot_dVi/j", "dpres_dVi/j" and set "HasAnalyticalDerivatives" to true in the ctor of the derived class. - For accurate numerical differentiation "mdot" and "pressure" can be functions of, at most, the velocities, - pressures, densities, and enthalpies at nodes i/j. This is also the order expected for the partial derivatives - of "mdot" and "pressure" in "d?_dVi/j" (in case they are known analytically, see the AUSM+up implementation). - ---*/ -} - -void CUpwAUSMPLUS_SLAU_Base_Flow::ApproximateJacobian(su2double **val_Jacobian_i, su2double **val_Jacobian_j) { - - unsigned short iDim, iVar, jVar, kVar; - su2double R, RoeDensity, RoeEnthalpy, RoeSoundSpeed, ProjVelocity, sq_vel, Energy_i, Energy_j; - - Energy_i = Enthalpy_i - Pressure_i/Density_i; - Energy_j = Enthalpy_j - Pressure_j/Density_j; - - /*--- Mean Roe variables iPoint and jPoint ---*/ - - R = sqrt(fabs(Density_j/Density_i)); - RoeDensity = R*Density_i; - ProjVelocity = 0.0; - sq_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); - ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; - sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; - } - RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); - RoeSoundSpeed = sqrt(fabs((Gamma-1)*(RoeEnthalpy-0.5*sq_vel))); - - /*--- Compute P and Lambda (do it with the Normal) ---*/ - - GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, P_Tensor); - - /*--- Flow eigenvalues and Entropy correctors ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - Lambda[iDim] = ProjVelocity; - Lambda[nVar-2] = ProjVelocity + RoeSoundSpeed; - Lambda[nVar-1] = ProjVelocity - RoeSoundSpeed; - - /*--- Compute inverse P ---*/ - GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); - - /*--- Jacobians of the inviscid flux, scale = 0.5 because val_residual ~ 0.5*(fc_i+fc_j)*Normal ---*/ - GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5, val_Jacobian_i); - GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5, val_Jacobian_j); - - /*--- Roe's Flux approximation ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - su2double Proj_ModJac_Tensor_ij = 0.0; - /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*fabs(Lambda[kVar])*invP_Tensor[kVar][jVar]; - val_Jacobian_i[iVar][jVar] += 0.5*Proj_ModJac_Tensor_ij*Area; - val_Jacobian_j[iVar][jVar] -= 0.5*Proj_ModJac_Tensor_ij*Area; - } - } - -} - -void CUpwAUSMPLUS_SLAU_Base_Flow::AccurateJacobian(CConfig *config, su2double **val_Jacobian_i, su2double **val_Jacobian_j) { - - /*--- Compute Jacobians using a mixed (numerical/analytical) formulation ---*/ - - unsigned short iDim, iVar, jVar; - - /*--- If not computed analytically, numerically differentiate the fluxes wrt primitives ---*/ - - if (!HasAnalyticalDerivatives) { - - /*--- Create arrays of pointers to the primitive variables so - we can loop through and perturb them in a general way. ---*/ - - su2double *primitives_i[6], *primitives_j[6]; - - for (iDim = 0; iDim < nDim; ++iDim) { - primitives_i[iDim] = &Velocity_i[iDim]; - primitives_j[iDim] = &Velocity_j[iDim]; - } - primitives_i[ nDim ] = &Pressure_i; primitives_j[ nDim ] = &Pressure_j; - primitives_i[nDim+1] = &Density_i; primitives_j[nDim+1] = &Density_j; - primitives_i[nDim+2] = &Enthalpy_i; primitives_j[nDim+2] = &Enthalpy_j; - - /*--- Initialize the gradient arrays with the negative of the quantity, - then for forward finite differences we add to it and divide. ---*/ - - for (iVar = 0; iVar < 6; ++iVar) { - dmdot_dVi[iVar] = -MassFlux; dpres_dVi[iVar] = -Pressure; - dmdot_dVj[iVar] = -MassFlux; dpres_dVj[iVar] = -Pressure; - } - - for (iVar = 0; iVar < nDim+3; ++iVar) { - /*--- Perturb side i ---*/ - su2double epsilon = FinDiffStep * max(1.0, fabs(*primitives_i[iVar])); - *primitives_i[iVar] += epsilon; - ComputeMassAndPressureFluxes(config, MassFlux, Pressure); - dmdot_dVi[iVar] += MassFlux; dpres_dVi[iVar] += Pressure; - dmdot_dVi[iVar] /= epsilon; dpres_dVi[iVar] /= epsilon; - *primitives_i[iVar] -= epsilon; - - /*--- Perturb side j ---*/ - epsilon = FinDiffStep * max(1.0, fabs(*primitives_j[iVar])); - *primitives_j[iVar] += epsilon; - ComputeMassAndPressureFluxes(config, MassFlux, Pressure); - dmdot_dVj[iVar] += MassFlux; dpres_dVj[iVar] += Pressure; - dmdot_dVj[iVar] /= epsilon; dpres_dVj[iVar] /= epsilon; - *primitives_j[iVar] -= epsilon; - } - } - - /*--- Differentiation of fluxes wrt conservatives assuming ideal gas ---*/ - - su2double dmdot_dUi[5], dmdot_dUj[5], dpres_dUi[5], dpres_dUj[5]; - su2double sq_veli = 0.0, sq_velj = 0.0, dHi_drhoi = 0.0, dHj_drhoj = 0.0; - su2double oneOnRhoi = 1.0/Density_i, oneOnRhoj = 1.0/Density_j; - - for (jVar = 0; jVar < nVar; ++jVar) { - - /*--- Partial derivatives of the primitives wrt conservative "jVar" ---*/ - su2double dVi_dUi[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; - su2double dVj_dUj[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; - - if (jVar == 0) { // Density - for (iDim = 0; iDim < nDim; ++iDim) { - // -u,v,w / rho - dVi_dUi[iDim] = -Velocity_i[iDim] * oneOnRhoi; - dVj_dUj[iDim] = -Velocity_j[iDim] * oneOnRhoj; - // ||V||^2 - sq_veli += Velocity_i[iDim] * Velocity_i[iDim]; - sq_velj += Velocity_j[iDim] * Velocity_j[iDim]; - } - dVi_dUi[nDim] = 0.5*Gamma_Minus_One*sq_veli; - dVj_dUj[nDim] = 0.5*Gamma_Minus_One*sq_velj; - - dVi_dUi[nDim+1] = dVj_dUj[nDim+1] = 1.0; - - dHi_drhoi = 0.5*(Gamma-2.0)*sq_veli - Gamma*Pressure_i/((Gamma-1.0)*Density_i); - dHj_drhoj = 0.5*(Gamma-2.0)*sq_velj - Gamma*Pressure_j/((Gamma-1.0)*Density_j); - dVi_dUi[nDim+2] = dHi_drhoi * oneOnRhoi; - dVj_dUj[nDim+2] = dHj_drhoj * oneOnRhoj; - } - else if (jVar == nVar-1) { // rho*Energy - dVi_dUi[nDim] = dVj_dUj[nDim] = Gamma_Minus_One; - dVi_dUi[nDim+2] = Gamma * oneOnRhoi; - dVj_dUj[nDim+2] = Gamma * oneOnRhoj; - } - else { // Momentum - dVi_dUi[jVar-1] = oneOnRhoi; - dVj_dUj[jVar-1] = oneOnRhoj; - - dVi_dUi[nDim] = -Gamma_Minus_One*Velocity_i[jVar-1]; - dVj_dUj[nDim] = -Gamma_Minus_One*Velocity_j[jVar-1]; - - dVi_dUi[nDim+2] = dVi_dUi[nDim] * oneOnRhoi; - dVj_dUj[nDim+2] = dVj_dUj[nDim] * oneOnRhoj; - } - - /*--- Dot product to complete chain rule ---*/ - dmdot_dUi[jVar] = 0.0; dpres_dUi[jVar] = 0.0; - dmdot_dUj[jVar] = 0.0; dpres_dUj[jVar] = 0.0; - for (iVar = 0; iVar < 6; ++iVar) { - dmdot_dUi[jVar] += dmdot_dVi[iVar]*dVi_dUi[iVar]; - dpres_dUi[jVar] += dpres_dVi[iVar]*dVi_dUi[iVar]; - dmdot_dUj[jVar] += dmdot_dVj[iVar]*dVj_dUj[iVar]; - dpres_dUj[jVar] += dpres_dVj[iVar]*dVj_dUj[iVar]; - } - } - - /*--- Assemble final Jacobians (assuming phi = |mdot|) ---*/ - - su2double mdot_hat, psi_hat[5]; - - if (MassFlux > 0.0) { - mdot_hat = Area*MassFlux*oneOnRhoi; - for (iVar = 0; iVar < nVar; ++iVar) psi_hat[iVar] = Area*psi_i[iVar]; - } - else { - mdot_hat = Area*MassFlux*oneOnRhoj; - for (iVar = 0; iVar < nVar; ++iVar) psi_hat[iVar] = Area*psi_j[iVar]; - } - - /*--- Contribution from the mass flux derivatives ---*/ - for (iVar = 0; iVar < nVar; ++iVar) { - for (jVar = 0; jVar < nVar; ++jVar) { - val_Jacobian_i[iVar][jVar] = psi_hat[iVar] * dmdot_dUi[jVar]; - val_Jacobian_j[iVar][jVar] = psi_hat[iVar] * dmdot_dUj[jVar]; - } - } - - /*--- Contribution from the pressure derivatives ---*/ - for (iDim = 0; iDim < nDim; ++iDim) { - for (jVar = 0; jVar < nVar; ++jVar) { - val_Jacobian_i[iDim+1][jVar] += Normal[iDim] * dpres_dUi[jVar]; - val_Jacobian_j[iDim+1][jVar] += Normal[iDim] * dpres_dUj[jVar]; - } - } - - /*--- Contributions from the derivatives of PSI wrt the conservatives ---*/ - if (MassFlux > 0.0) { - /*--- Velocity terms ---*/ - for (iDim = 0; iDim < nDim; ++iDim) { - val_Jacobian_i[iDim+1][0] -= mdot_hat*Velocity_i[iDim]; - val_Jacobian_i[iDim+1][iDim+1] += mdot_hat; - val_Jacobian_i[nVar-1][iDim+1] -= mdot_hat*Gamma_Minus_One*Velocity_i[iDim]; - } - /*--- Energy terms ---*/ - val_Jacobian_i[nVar-1][0] += mdot_hat*dHi_drhoi; - val_Jacobian_i[nVar-1][nVar-1] += mdot_hat*Gamma; - } - else { - /*--- Velocity terms ---*/ - for (iDim = 0; iDim < nDim; ++iDim) { - val_Jacobian_j[iDim+1][0] -= mdot_hat*Velocity_j[iDim]; - val_Jacobian_j[iDim+1][iDim+1] += mdot_hat; - val_Jacobian_j[nVar-1][iDim+1] -= mdot_hat*Gamma_Minus_One*Velocity_j[iDim]; - } - /*--- Energy terms ---*/ - val_Jacobian_j[nVar-1][0] += mdot_hat*dHj_drhoj; - val_Jacobian_j[nVar-1][nVar-1] += mdot_hat*Gamma; - } - -} - -void CUpwAUSMPLUS_SLAU_Base_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - unsigned short iDim, iVar; - - /*--- Space to start preaccumulation ---*/ - - AD::StartPreacc(); - AD::SetPreaccIn(Normal, nDim); - AD::SetPreaccIn(V_i, nDim+4); - AD::SetPreaccIn(V_j, nDim+4); - - /*--- Variables for the general form and primitives for mass flux and pressure calculation. ---*/ - /*--- F_{1/2} = ||A|| ( 0.5 * mdot * (psi_i+psi_j) - 0.5 * |mdot| * (psi_i-psi_j) + N * pf ) ---*/ - - psi_i[0] = 1.0; psi_j[0] = 1.0; - - for (iDim = 0; iDim < nDim; iDim++) { - /*--- Velocities ---*/ - Velocity_i[iDim] = psi_i[iDim+1] = V_i[iDim+1]; - Velocity_j[iDim] = psi_j[iDim+1] = V_j[iDim+1]; - } - - /*--- Pressure and Density ---*/ - Pressure_i = V_i[nDim+1]; Pressure_j = V_j[nDim+1]; - Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; - - /*--- Enthalpy ---*/ - Enthalpy_i = psi_i[nVar-1] = V_i[nDim+3]; - Enthalpy_j = psi_j[nVar-1] = V_j[nDim+3]; - - /*--- Face area (norm or the normal vector) ---*/ - - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim]*Normal[iDim]; - Area = sqrt(Area); - - /*-- Unit Normal ---*/ - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = Normal[iDim]/Area; - - /*--- Mass and pressure fluxes defined by derived classes ---*/ - - ComputeMassAndPressureFluxes(config, MassFlux, Pressure); - DissFlux = fabs(MassFlux); - - val_residual[0] = MassFlux; - - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = 0.5*MassFlux*(psi_i[iDim+1]+psi_j[iDim+1]) + - 0.5*DissFlux*(psi_i[iDim+1]-psi_j[iDim+1]) + - UnitNormal[iDim]*Pressure; - - val_residual[nVar-1] = 0.5*MassFlux*(psi_i[nVar-1]+psi_j[nVar-1]) + - 0.5*DissFlux*(psi_i[nVar-1]-psi_j[nVar-1]); - - for (iVar = 0; iVar < nVar; iVar++) val_residual[iVar] *= Area; - - /*--- Space to end preaccumulation ---*/ - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - - /*--- If required, compute Jacobians, either approximately (Roe) or numerically ---*/ - - if (!implicit) return; - - if (UseAccurateJacobian) - AccurateJacobian(config, val_Jacobian_i, val_Jacobian_j); - else - ApproximateJacobian(val_Jacobian_i, val_Jacobian_j); - -} - - -CUpwAUSMPLUSUP_Flow::CUpwAUSMPLUSUP_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : - CUpwAUSMPLUS_SLAU_Base_Flow(val_nDim, val_nVar, config) { - - HasAnalyticalDerivatives = true; - Minf = config->GetMach(); - Kp = 0.25; - Ku = 0.75; - sigma = 1.0; - - if (Minf < EPS) - SU2_MPI::Error("AUSM+Up requires a reference Mach number (\"MACH_NUMBER\") greater than 0.", CURRENT_FUNCTION); -} - -CUpwAUSMPLUSUP_Flow::~CUpwAUSMPLUSUP_Flow(void) { - -} - -void CUpwAUSMPLUSUP_Flow::ComputeMassAndPressureFluxes(CConfig *config, su2double &mdot, su2double &pressure) { - - /*--- Projected velocities ---*/ - - su2double ProjVelocity_i = 0.0, ProjVelocity_j = 0.0; - - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; - } - - /*--- Compute interface speed of sound (aF) ---*/ - - su2double astarL = sqrt(2.0*(Gamma-1.0)/(Gamma+1.0)*Enthalpy_i); - su2double astarR = sqrt(2.0*(Gamma-1.0)/(Gamma+1.0)*Enthalpy_j); - - su2double ahatL = astarL*astarL/max(astarL, ProjVelocity_i); - su2double ahatR = astarR*astarR/max(astarR,-ProjVelocity_j); - - su2double aF = min(ahatL,ahatR); - - /*--- Left and right pressures and Mach numbers ---*/ - - su2double mLP, betaLP, mRM, betaRM; - - su2double mL = ProjVelocity_i/aF; - su2double mR = ProjVelocity_j/aF; - - su2double MFsq = 0.5*(mL*mL+mR*mR); - su2double param1 = max(MFsq, Minf*Minf); - su2double Mrefsq = min(1.0, param1); - - su2double fa = 2.0*sqrt(Mrefsq)-Mrefsq; - - su2double alpha = 3.0/16.0*(-4.0+5.0*fa*fa); - su2double beta = 1.0/8.0; - - if (fabs(mL) <= 1.0) { - su2double p1 = 0.25*(mL+1.0)*(mL+1.0); - su2double p2 = (mL*mL-1.0)*(mL*mL-1.0); - - mLP = p1 + beta*p2; - betaLP = p1*(2.0-mL) + alpha*mL*p2; - } - else { - mLP = 0.5*(mL+fabs(mL)); - betaLP = mLP/mL; - } - - if (fabs(mR) <= 1.0) { - su2double p1 = 0.25*(mR-1.0)*(mR-1.0); - su2double p2 = (mR*mR-1.0)*(mR*mR-1.0); - - mRM = -p1 - beta*p2; - betaRM = p1*(2.0+mR) - alpha*mR*p2; - } - else { - mRM = 0.5*(mR-fabs(mR)); - betaRM = mRM/mR; - } - - /*--- Pressure and velocity diffusion terms ---*/ - - su2double rhoF = 0.5*(Density_i+Density_j); - su2double Mp = -(Kp/fa)*max((1.0-sigma*MFsq),0.0)*(Pressure_j-Pressure_i)/(rhoF*aF*aF); - - su2double Pu = -Ku*fa*betaLP*betaRM*2.0*rhoF*aF*(ProjVelocity_j-ProjVelocity_i); - - /*--- Finally the fluxes ---*/ - - su2double mF = mLP + mRM + Mp; - mdot = aF * (max(mF,0.0)*Density_i + min(mF,0.0)*Density_j); - - pressure = betaLP*Pressure_i + betaRM*Pressure_j + Pu; - - if (!implicit || !UseAccurateJacobian) return; - - /*--- Analytical differentiation of the face mass flux and - pressure (in reverse mode, "?_b" denotes dmot_d?). ---*/ - - /*--- limited mean Mach number (used in division...) ---*/ - su2double MF = max(numeric_limits::epsilon(),sqrt(MFsq)); - - for (int outVar=0; outVar<2; ++outVar) { - - su2double aF_b = 0.0, mF_b = 0.0, MF_b = 0.0, rhoF_b = 0.0, fa_b = 0.0, alpha_b = 0.0, - rho_i_b = 0.0, rho_j_b = 0.0, p_i_b = 0.0, p_j_b = 0.0, Vn_i_b = 0.0, Vn_j_b = 0.0, - mR_b = 0.0, mL_b = 0.0, betaLP_b = 0.0, betaRM_b = 0.0, tmp = 0.0; - - if (outVar==0) { - /*--- mdot = ... ---*/ - if (mF > 0.0) { - aF_b += mF*Density_i; - mF_b += aF*Density_i; - rho_i_b += mF*aF; - } - else { - aF_b += mF*Density_j; - mF_b += aF*Density_j; - rho_j_b += mF*aF; - } - - /*--- Mp = ... ---*/ - if (sigma*MFsq < 1.0) { - rhoF_b -= Mp/rhoF * mF_b; - fa_b -= Mp/fa * mF_b; - aF_b -= 2.0*Mp/aF * mF_b; - MF_b += 2.0*sigma*MF*(Kp/fa)*(Pressure_j-Pressure_i)/(rhoF*aF*aF) * mF_b; - tmp = -(Kp/fa)*(1.0-sigma*MFsq)/(rhoF*aF*aF); - p_i_b -= tmp * mF_b; - p_j_b += tmp * mF_b; - } - - /*--- rhoF = ... ---*/ - rho_i_b += 0.5*rhoF_b; rho_j_b += 0.5*rhoF_b; - - /*--- mRM = ... ---*/ - if (fabs(mR) < 1.0) mR_b += (1.0-mR)*(0.5+4.0*beta*mR*(mR+1.0)) * mF_b; - else if (mR <=-1.0) mR_b += mF_b; - - /*--- mLP = ... ---*/ - if (fabs(mL) < 1.0) mL_b += (1.0+mL)*(0.5+4.0*beta*mL*(mL-1.0)) * mF_b; - else if (mL >= 1.0) mL_b += mF_b; - } - else { - /*--- pressure = ... ---*/ - p_i_b += betaLP; betaLP_b += Pressure_i; - p_j_b += betaRM; betaRM_b += Pressure_j; - - /*--- Pu = ... ---*/ - rhoF_b += Pu/rhoF; - fa_b += Pu/fa; - aF_b += Pu/aF; - tmp = -Ku*fa*2.0*rhoF*aF*(ProjVelocity_j-ProjVelocity_i); - betaLP_b += tmp*betaRM; - betaRM_b += tmp*betaLP; - tmp = -Ku*fa*betaLP*betaRM*2.0*rhoF*aF; - Vn_i_b -= tmp; - Vn_j_b += tmp; - - /*--- rhoF = ... ---*/ - rho_i_b += 0.5*rhoF_b; rho_j_b += 0.5*rhoF_b; - - /*--- betaRM = ... ---*/ - if (fabs(mR) < 1.0) { - tmp = mR*mR-1.0; - mR_b += tmp*(0.75-alpha*(5.0*tmp+4.0)) * betaRM_b; - alpha_b -= mR*tmp*tmp * betaRM_b; - } - - /*--- betaLP = ... ---*/ - if (fabs(mL) < 1.0) { - tmp = mL*mL-1.0; - mL_b -= tmp*(0.75-alpha*(5.0*tmp+4.0)) * betaLP_b; - alpha_b += mL*tmp*tmp * betaLP_b; - } - - /*--- alpha = ... ---*/ - fa_b += 1.875*fa * alpha_b; - } - - /*--- steps shared by both ---*/ - /*--- fa = ... ---*/ - su2double Mref_b = 2.0*(1.0-sqrt(Mrefsq)) * fa_b; - - /*--- Mrefsq = ... ---*/ - if (MF < 1.0 && MF > Minf) MF_b += Mref_b; - - /*--- MFsq = ... ---*/ - mL_b += 0.5*mL/MF * MF_b; mR_b += 0.5*mR/MF * MF_b; - - /*--- mL/R = ... ---*/ - Vn_i_b += mL_b/aF; Vn_j_b += mR_b/aF; - aF_b -= (mL*mL_b+mR*mR_b)/aF; - - /*--- aF,ahat,astar = f(H_i,H_j) ---*/ - su2double astar_b = aF_b, H_i_b, H_j_b; - - if (ahatL < ahatR) { - if (astarL <= ProjVelocity_i) { - tmp = astarL/ProjVelocity_i; - astar_b *= 2.0*tmp; - Vn_i_b -= tmp*tmp * aF_b; - } - H_i_b = sqrt(0.5*(Gamma-1.0)/((Gamma+1.0)*Enthalpy_i)) * astar_b; - H_j_b = 0.0; - } - else { - if (astarR <= -ProjVelocity_j) { - tmp = -astarR/ProjVelocity_j; - astar_b *= 2.0*tmp; - Vn_j_b += tmp*tmp * aF_b; - } - H_j_b = sqrt(0.5*(Gamma-1.0)/((Gamma+1.0)*Enthalpy_j)) * astar_b; - H_i_b = 0.0; - } - - /*--- store derivatives ---*/ - su2double *target_i = (outVar==0 ? dmdot_dVi : dpres_dVi), - *target_j = (outVar==0 ? dmdot_dVj : dpres_dVj); - target_i[5] = target_j[5] = 0.0; - - /*--- ProjVelocity = ... ---*/ - for (unsigned short iDim = 0; iDim < nDim; ++iDim) { - target_i[iDim] = UnitNormal[iDim] * Vn_i_b; - target_j[iDim] = UnitNormal[iDim] * Vn_j_b; - } - target_i[ nDim ] = p_i_b; target_j[ nDim ] = p_j_b; - target_i[nDim+1] = rho_i_b; target_j[nDim+1] = rho_j_b; - target_i[nDim+2] = H_i_b; target_j[nDim+2] = H_j_b; - } -} - -CUpwAUSMPLUSUP2_Flow::CUpwAUSMPLUSUP2_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : - CUpwAUSMPLUS_SLAU_Base_Flow(val_nDim, val_nVar, config) { - - Minf = config->GetMach(); - Kp = 0.25; - sigma = 1.0; - - if (Minf < EPS) - SU2_MPI::Error("AUSM+Up2 requires a reference Mach number (\"MACH_NUMBER\") greater than 0.", CURRENT_FUNCTION); -} - -CUpwAUSMPLUSUP2_Flow::~CUpwAUSMPLUSUP2_Flow(void) { - -} - -void CUpwAUSMPLUSUP2_Flow::ComputeMassAndPressureFluxes(CConfig *config, su2double &mdot, su2double &pressure) { - - /*--- Projected velocities and squared magnitude ---*/ - - su2double ProjVelocity_i = 0.0, ProjVelocity_j = 0.0, sq_vel = 0.0; - - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; - - sq_vel += 0.5*(Velocity_i[iDim]*Velocity_i[iDim] + Velocity_j[iDim]*Velocity_j[iDim]); - } - - /*--- Compute interface speed of sound (aF) ---*/ - - su2double astarL = sqrt(2.0*(Gamma-1.0)/(Gamma+1.0)*Enthalpy_i); - su2double astarR = sqrt(2.0*(Gamma-1.0)/(Gamma+1.0)*Enthalpy_j); - - su2double ahatL = astarL*astarL/max(astarL, ProjVelocity_i); - su2double ahatR = astarR*astarR/max(astarR,-ProjVelocity_j); - - su2double aF = min(ahatL,ahatR); - - /*--- Left and right pressure functions and Mach numbers ---*/ - - su2double mLP, pLP, mRM, pRM; - - su2double mL = ProjVelocity_i/aF; - su2double mR = ProjVelocity_j/aF; - - su2double MFsq = 0.5*(mL*mL+mR*mR); - su2double param1 = max(MFsq, Minf*Minf); - su2double Mrefsq = min(1.0, param1); - - su2double fa = 2.0*sqrt(Mrefsq)-Mrefsq; - - su2double alpha = 3.0/16.0*(-4.0+5.0*fa*fa); - su2double beta = 1.0/8.0; - - if (fabs(mL) <= 1.0) { - su2double p1 = 0.25*(mL+1.0)*(mL+1.0); - su2double p2 = (mL*mL-1.0)*(mL*mL-1.0); - - mLP = p1 + beta*p2; - pLP = p1*(2.0-mL) + alpha*mL*p2; - } - else { - mLP = 0.5*(mL+fabs(mL)); - pLP = mLP/mL; - } - - if (fabs(mR) <= 1.0) { - su2double p1 = 0.25*(mR-1.0)*(mR-1.0); - su2double p2 = (mR*mR-1.0)*(mR*mR-1.0); - - mRM = -p1 - beta*p2; - pRM = p1*(2.0+mR) - alpha*mR*p2; - } - else { - mRM = 0.5*(mR-fabs(mR)); - pRM = mRM/mR; - } - - /*--- Mass flux with pressure diffusion term ---*/ - - su2double rhoF = 0.5*(Density_i+Density_j); - su2double Mp = -(Kp/fa)*max((1.0-sigma*MFsq),0.0)*(Pressure_j-Pressure_i)/(rhoF*aF*aF); - - su2double mF = mLP + mRM + Mp; - mdot = aF * (max(mF,0.0)*Density_i + min(mF,0.0)*Density_j); - - /*--- Modified pressure flux ---*/ - - pressure = 0.5*(Pressure_j+Pressure_i) + 0.5*(pLP-pRM)*(Pressure_i-Pressure_j) + sqrt(sq_vel)*(pLP+pRM-1.0)*rhoF*aF; - -} - -CUpwSLAU_Flow::CUpwSLAU_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config, bool val_low_dissipation) : - CUpwAUSMPLUS_SLAU_Base_Flow(val_nDim, val_nVar, config) { - - slau_low_diss = val_low_dissipation; - slau2 = false; -} - -CUpwSLAU_Flow::~CUpwSLAU_Flow(void) { - -} - -void CUpwSLAU_Flow::ComputeMassAndPressureFluxes(CConfig *config, su2double &mdot, su2double &pressure) { - - /*--- Project velocities and speed of sound ---*/ - - su2double ProjVelocity_i = 0.0, ProjVelocity_j = 0.0, sq_veli = 0.0, sq_velj = 0.0; - - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; - - sq_veli += Velocity_i[iDim]*Velocity_i[iDim]; - sq_velj += Velocity_j[iDim]*Velocity_j[iDim]; - } - - su2double Energy_i = Enthalpy_i - Pressure_i/Density_i; - SoundSpeed_i = sqrt(fabs(Gamma*Gamma_Minus_One*(Energy_i-0.5*sq_veli))); - - su2double Energy_j = Enthalpy_j - Pressure_j/Density_j; - SoundSpeed_j = sqrt(fabs(Gamma*Gamma_Minus_One*(Energy_j-0.5*sq_velj))); - - /*--- Compute interface speed of sound (aF), and left/right Mach number ---*/ - - su2double aF = 0.5 * (SoundSpeed_i + SoundSpeed_j); - su2double mL = ProjVelocity_i/aF; - su2double mR = ProjVelocity_j/aF; - - /*--- Smooth function of the local Mach number---*/ - - su2double Mach_tilde = min(1.0, (1.0/aF) * sqrt(0.5*(sq_veli+sq_velj))); - su2double Chi = pow((1.0 - Mach_tilde),2.0); - su2double f_rho = -max(min(mL,0.0),-1.0) * min(max(mR,0.0),1.0); - - /*--- Mean normal velocity with density weighting ---*/ - - su2double Vn_Mag = (Density_i*fabs(ProjVelocity_i) + Density_j*fabs(ProjVelocity_j)) / (Density_i + Density_j); - su2double Vn_MagL= (1.0 - f_rho)*Vn_Mag + f_rho*fabs(ProjVelocity_i); - su2double Vn_MagR= (1.0 - f_rho)*Vn_Mag + f_rho*fabs(ProjVelocity_j); - - /*--- Mass flux function ---*/ - - mdot = 0.5 * (Density_i*(ProjVelocity_i+Vn_MagL) + Density_j*(ProjVelocity_j-Vn_MagR) - (Chi/aF)*(Pressure_j-Pressure_i)); - - /*--- Pressure function ---*/ - - su2double BetaL, BetaR, Dissipation_ij; - - if (fabs(mL) < 1.0) BetaL = 0.25*(2.0-mL)*pow((mL+1.0),2.0); - else if (mL >= 0) BetaL = 1.0; - else BetaL = 0.0; - - if (fabs(mR) < 1.0) BetaR = 0.25*(2.0+mR)*pow((mR-1.0),2.0); - else if (mR >= 0) BetaR = 0.0; - else BetaR = 1.0; - - if (slau_low_diss) - SetRoe_Dissipation(Dissipation_i, Dissipation_j, Sensor_i, Sensor_j, Dissipation_ij, config); - else - Dissipation_ij = 1.0; - - pressure = 0.5*(Pressure_i+Pressure_j) + 0.5*(BetaL-BetaR)*(Pressure_i-Pressure_j); - - if (!slau2) pressure += Dissipation_ij*(1.0-Chi)*(BetaL+BetaR-1.0)*0.5*(Pressure_i+Pressure_j); - else pressure += Dissipation_ij*sqrt(0.5*(sq_veli+sq_velj))*(BetaL+BetaR-1.0)*aF*0.5*(Density_i+Density_j); - -} - -CUpwSLAU2_Flow::CUpwSLAU2_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config, bool val_low_dissipation) : - CUpwSLAU_Flow(val_nDim, val_nVar, config, val_low_dissipation) { - - /*--- The difference between SLAU and SLAU2 is minimal, so we derive from SLAU and set this flag - so that the ComputeMassAndPressureFluxes function modifies the pressure according to SLAU2. - This is safe since this constructor is guaranteed to execute after SLAU's one. ---*/ - slau2 = true; -} - -CUpwSLAU2_Flow::~CUpwSLAU2_Flow(void) { - -} - -CUpwHLLC_Flow::CUpwHLLC_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - kappa = config->GetRoe_Kappa(); - /* 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(); - - Gamma = config->GetGamma(); - - Gamma_Minus_One = Gamma - 1.0; - - IntermediateState = new su2double [nVar]; - dSm_dU = new su2double [nVar]; - dPI_dU = new su2double [nVar]; - drhoStar_dU = new su2double [nVar]; - dpStar_dU = new su2double [nVar]; - dEStar_dU = new su2double [nVar]; - - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - RoeVelocity = new su2double [nDim]; - -} - -CUpwHLLC_Flow::~CUpwHLLC_Flow(void) { - - delete [] IntermediateState; - delete [] dSm_dU; - delete [] dPI_dU; - delete [] drhoStar_dU; - delete [] dpStar_dU; - delete [] dEStar_dU; - - delete [] Velocity_i; - delete [] Velocity_j; - delete [] RoeVelocity; - -} - -void CUpwHLLC_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - /*--- Face area (norm or the normal vector) ---*/ - - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim] * Normal[iDim]; - - Area = sqrt(Area); - - /*-- Unit Normal ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = Normal[iDim] / Area; - - /*-- Fluid velocity at node i,j ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity_j[iDim] = V_j[iDim+1]; - } - - /*--- Primitive variables at point i ---*/ - - Pressure_i = V_i[nDim+1]; - Density_i = V_i[nDim+2]; - Enthalpy_i = V_i[nDim+3]; - - /*--- Primitive variables at point j ---*/ - - Pressure_j = V_j[nDim+1]; - Density_j = V_j[nDim+2]; - Enthalpy_j = V_j[nDim+3]; - - - sq_vel_i = 0.0; - sq_vel_j = 0.0; - - for (iDim = 0; iDim < nDim; iDim++) { - sq_vel_i += Velocity_i[iDim] * Velocity_i[iDim]; - sq_vel_j += Velocity_j[iDim] * Velocity_j[iDim]; - } - - Energy_i = Enthalpy_i - Pressure_i / Density_i; - Energy_j = Enthalpy_j - Pressure_j / Density_j; - - SoundSpeed_i = sqrt( (Enthalpy_i - 0.5 * sq_vel_i) * Gamma_Minus_One ); - SoundSpeed_j = sqrt( (Enthalpy_j - 0.5 * sq_vel_j) * Gamma_Minus_One ); - - /*--- Projected velocities ---*/ - - ProjVelocity_i = 0; - ProjVelocity_j = 0; - - for (iDim = 0; iDim < nDim; iDim++) { - ProjVelocity_i += Velocity_i[iDim] * UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim] * UnitNormal[iDim]; - } - - /*--- Projected Grid Velocity ---*/ - - ProjInterfaceVel = 0; - - if (dynamic_grid) { - - for (iDim = 0; iDim < nDim; iDim++) - ProjInterfaceVel += 0.5 * ( GridVel_i[iDim] + GridVel_j[iDim] )*UnitNormal[iDim]; - - SoundSpeed_i -= ProjInterfaceVel; - SoundSpeed_j += ProjInterfaceVel; - - ProjVelocity_i -= ProjInterfaceVel; - ProjVelocity_j -= ProjInterfaceVel; - } - - /*--- Roe's averaging ---*/ - - Rrho = ( sqrt(Density_i) + sqrt(Density_j) ); - - sq_velRoe = 0.0; - RoeProjVelocity = - ProjInterfaceVel; - - for (iDim = 0; iDim < nDim; iDim++) { - RoeVelocity[iDim] = ( Velocity_i[iDim] * sqrt(Density_i) + Velocity_j[iDim] * sqrt(Density_j) ) / Rrho; - sq_velRoe += RoeVelocity[iDim] * RoeVelocity[iDim]; - RoeProjVelocity += RoeVelocity[iDim] * UnitNormal[iDim]; - } - - /*--- Mean Roe variables iPoint and jPoint ---*/ - - RoeDensity = sqrt( Density_i * Density_j ); - RoeEnthalpy = ( sqrt(Density_j) * Enthalpy_j + sqrt(Density_i) * Enthalpy_i) / Rrho; - - /*--- Roe-averaged speed of sound ---*/ - - //RoeSoundSpeed2 = Gamma_Minus_One * ( RoeEnthalpy - 0.5 * sq_velRoe ); - RoeSoundSpeed = sqrt( Gamma_Minus_One * ( RoeEnthalpy - 0.5 * sq_velRoe ) ) - ProjInterfaceVel; - - - /*--- Speed of sound at L and R ---*/ - - sL = min( RoeProjVelocity - RoeSoundSpeed, ProjVelocity_i - SoundSpeed_i); - sR = max( RoeProjVelocity + RoeSoundSpeed, ProjVelocity_j + SoundSpeed_j); - - /*--- speed of contact surface ---*/ - - RHO = Density_j * (sR - ProjVelocity_j) - Density_i * (sL - ProjVelocity_i); - sM = ( Pressure_i - Pressure_j - Density_i * ProjVelocity_i * ( sL - ProjVelocity_i ) + Density_j * ProjVelocity_j * ( sR - ProjVelocity_j ) ) / RHO; - - /*--- Pressure at right and left (Pressure_j=Pressure_i) side of contact surface ---*/ - - pStar = Density_j * ( ProjVelocity_j - sR ) * ( ProjVelocity_j - sM ) + Pressure_j; - - -if (sM > 0.0) { - - if (sL > 0.0) { - - /*--- Compute Left Flux ---*/ - - val_residual[0] = Density_i * ProjVelocity_i; - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = Density_i * Velocity_i[iDim] * ProjVelocity_i + Pressure_i * UnitNormal[iDim]; - val_residual[nVar-1] = Enthalpy_i * Density_i * ProjVelocity_i; - } - else { - - /*--- Compute Flux Left Star from Left Star State ---*/ - - rhoSL = ( sL - ProjVelocity_i ) / ( sL - sM ); - - IntermediateState[0] = rhoSL * Density_i; - for (iDim = 0; iDim < nDim; iDim++) - IntermediateState[iDim+1] = rhoSL * ( Density_i * Velocity_i[iDim] + ( pStar - Pressure_i ) / ( sL - ProjVelocity_i ) * UnitNormal[iDim] ) ; - IntermediateState[nVar-1] = rhoSL * ( Density_i * Energy_i - ( Pressure_i * ProjVelocity_i - pStar * sM) / ( sL - ProjVelocity_i ) ); - - - val_residual[0] = sM * IntermediateState[0]; - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = sM * IntermediateState[iDim+1] + pStar * UnitNormal[iDim]; - val_residual[nVar-1] = sM * ( IntermediateState[nVar-1] + pStar ) + pStar * ProjInterfaceVel; - } - } - else { - - if (sR < 0.0) { - - /*--- Compute Right Flux ---*/ - - val_residual[0] = Density_j * ProjVelocity_j; - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = Density_j * Velocity_j[iDim] * ProjVelocity_j + Pressure_j * UnitNormal[iDim]; - val_residual[nVar-1] = Enthalpy_j * Density_j * ProjVelocity_j; - } - else { - - /*--- Compute Flux Right Star from Right Star State ---*/ - - rhoSR = ( sR - ProjVelocity_j ) / ( sR - sM ); - - IntermediateState[0] = rhoSR * Density_j; - for (iDim = 0; iDim < nDim; iDim++) - IntermediateState[iDim+1] = rhoSR * ( Density_j * Velocity_j[iDim] + ( pStar - Pressure_j ) / ( sR - ProjVelocity_j ) * UnitNormal[iDim] ) ; - IntermediateState[nVar-1] = rhoSR * ( Density_j * Energy_j - ( Pressure_j * ProjVelocity_j - pStar * sM ) / ( sR - ProjVelocity_j ) ); - - - val_residual[0] = sM * IntermediateState[0]; - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = sM * IntermediateState[iDim+1] + pStar * UnitNormal[iDim]; - val_residual[nVar-1] = sM * (IntermediateState[nVar-1] + pStar ) + pStar * ProjInterfaceVel; - } - } - - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] *= Area; - - - if (implicit) { - - if (sM > 0.0) { - - if (sL > 0.0) { - - /*--- Compute Jacobian based on Left State ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_j[iVar][jVar] = 0; - - GetInviscidProjJac(Velocity_i, &Energy_i, UnitNormal, 1.0, val_Jacobian_i); - - } - else { - /*--- Compute Jacobian based on Left Star State ---*/ - - EStar = IntermediateState[nVar-1]; - Omega = 1/(sL-sM); - OmegaSM = Omega * sM; - - - /*--------- Left Jacobian ---------*/ - - - /*--- Computing pressure derivatives d/dU_L (PI) ---*/ - - dPI_dU[0] = 0.5 * Gamma_Minus_One * sq_vel_i; - for (iDim = 0; iDim < nDim; iDim++) - dPI_dU[iDim+1] = - Gamma_Minus_One * Velocity_i[iDim]; - dPI_dU[nVar-1] = Gamma_Minus_One; - - - /*--- Computing d/dU_L (Sm) ---*/ - - dSm_dU[0] = ( - ProjVelocity_i * ProjVelocity_i + sM * sL + dPI_dU[0] ) / RHO; - for (iDim = 0; iDim < nDim; iDim++) - dSm_dU[iDim+1] = ( UnitNormal[iDim] * ( 2 * ProjVelocity_i - sL - sM ) + dPI_dU[iDim+1] ) / RHO; - dSm_dU[nVar-1] = dPI_dU[nVar-1] / RHO; - - - /*--- Computing d/dU_L (rhoStar) ---*/ - - drhoStar_dU[0] = Omega * ( sL + IntermediateState[0] * dSm_dU[0] ); - for (iDim = 0; iDim < nDim; iDim++) - drhoStar_dU[iDim+1] = Omega * ( - UnitNormal[iDim] + IntermediateState[0] * dSm_dU[iDim+1] ); - drhoStar_dU[nVar-1] = Omega * IntermediateState[0] * dSm_dU[nVar-1]; - - - /*--- Computing d/dU_L (pStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dpStar_dU[iVar] = Density_i * (sR - ProjVelocity_j) * dSm_dU[iVar]; - - - /*--- Computing d/dU_L (EStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); - - dEStar_dU[0] += Omega * ProjVelocity_i * ( Enthalpy_i - dPI_dU[0] ); - for (iDim = 0; iDim < nDim; iDim++) - dEStar_dU[iDim+1] += Omega * ( - UnitNormal[iDim] * Enthalpy_i - ProjVelocity_i * dPI_dU[iDim+1] ); - dEStar_dU[nVar-1] += Omega * ( sL - ProjVelocity_i - ProjVelocity_i * dPI_dU[nVar-1] ); - - - - /*--- Jacobian First Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[0][iVar] = sM * drhoStar_dU[iVar] + IntermediateState[0] * dSm_dU[iVar]; - - /*--- Jacobian Middle Rows ---*/ - - for (jDim = 0; jDim < nDim; jDim++) { - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[jDim+1][iVar] = ( OmegaSM + 1 ) * ( UnitNormal[jDim] * dpStar_dU[iVar] + IntermediateState[jDim+1] * dSm_dU[iVar] ); - - val_Jacobian_i[jDim+1][0] += OmegaSM * Velocity_i[jDim] * ProjVelocity_i; - - val_Jacobian_i[jDim+1][jDim+1] += OmegaSM * (sL - ProjVelocity_i); - - for (iDim = 0; iDim < nDim; iDim++) - val_Jacobian_i[jDim+1][iDim+1] -= OmegaSM * Velocity_i[jDim] * UnitNormal[iDim]; - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[jDim+1][iVar] -= OmegaSM * dPI_dU[iVar] * UnitNormal[jDim]; - } - - /*--- Jacobian Last Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[nVar-1][iVar] = sM * ( dEStar_dU[iVar] + dpStar_dU[iVar] ) + ( EStar + pStar ) * dSm_dU[iVar]; - - - - - /*--------- Right Jacobian ---------*/ - - - /*--- Computing d/dU_R (Sm) ---*/ - - dSm_dU[0] = ( ProjVelocity_j * ProjVelocity_j - sM * sR - 0.5 * Gamma_Minus_One * sq_vel_j ) / RHO; - for (iDim = 0; iDim < nDim; iDim++) - dSm_dU[iDim+1] = - ( UnitNormal[iDim] * ( 2 * ProjVelocity_j - sR - sM) - Gamma_Minus_One * Velocity_j[iDim] ) / RHO; - dSm_dU[nVar-1] = - Gamma_Minus_One / RHO; - - - /*--- Computing d/dU_R (pStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dpStar_dU[iVar] = Density_j * (sL - ProjVelocity_i) * dSm_dU[iVar]; - - - /*--- Computing d/dU_R (EStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); - - - - /*--- Jacobian First Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[0][iVar] = IntermediateState[0] * ( OmegaSM + 1 ) * dSm_dU[iVar]; - - /*--- Jacobian Middle Rows ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[iDim+1][iVar] = ( OmegaSM + 1 ) * ( IntermediateState[iDim+1] * dSm_dU[iVar] + UnitNormal[iDim] * dpStar_dU[iVar] ); - } - - /*--- Jacobian Last Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[nVar-1][iVar] = sM * (dEStar_dU[iVar] + dpStar_dU[iVar]) + (EStar + pStar) * dSm_dU[iVar]; - } - } - else { - if (sR < 0.0) { - - /*--- Compute Jacobian based on Right State ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_i[iVar][jVar] = 0; - - GetInviscidProjJac(Velocity_j, &Energy_j, UnitNormal, 1.0, val_Jacobian_j); - - } - else { - /*--- Compute Jacobian based on Right Star State ---*/ - - EStar = IntermediateState[nVar-1]; - Omega = 1/(sR-sM); - OmegaSM = Omega * sM; - - - /*--------- Left Jacobian ---------*/ - - - /*--- Computing d/dU_L (Sm) ---*/ - - dSm_dU[0] = ( - ProjVelocity_i * ProjVelocity_i + sM * sL + 0.5 * Gamma_Minus_One * sq_vel_i ) / RHO; - for (iDim = 0; iDim < nDim; iDim++) - dSm_dU[iDim+1] = ( UnitNormal[iDim] * ( 2 * ProjVelocity_i - sL - sM ) - Gamma_Minus_One * Velocity_i[iDim] ) / RHO; - dSm_dU[nVar-1] = Gamma_Minus_One / RHO; - - - /*--- Computing d/dU_L (pStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dpStar_dU[iVar] = Density_i * (sR - ProjVelocity_j) * dSm_dU[iVar]; - - - /*--- Computing d/dU_L (EStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); - - - - /*--- Jacobian First Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[0][iVar] = IntermediateState[0] * ( OmegaSM + 1 ) * dSm_dU[iVar]; - - /*--- Jacobian Middle Rows ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[iDim+1][iVar] = (OmegaSM + 1) * ( IntermediateState[iDim+1] * dSm_dU[iVar] + UnitNormal[iDim] * dpStar_dU[iVar] ); - } - - /*--- Jacobian Last Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[nVar-1][iVar] = sM * (dEStar_dU[iVar] + dpStar_dU[iVar]) + (EStar + pStar) * dSm_dU[iVar]; - - - - /*--------- Right Jacobian ---------*/ - - - /*--- Computing pressure derivatives d/dU_R (PI) ---*/ - - dPI_dU[0] = 0.5 * Gamma_Minus_One * sq_vel_j; - for (iDim = 0; iDim < nDim; iDim++) - dPI_dU[iDim+1] = - Gamma_Minus_One * Velocity_j[iDim]; - dPI_dU[nVar-1] = Gamma_Minus_One; - - - - /*--- Computing d/dU_R (Sm) ---*/ - - dSm_dU[0] = - ( - ProjVelocity_j * ProjVelocity_j + sM * sR + dPI_dU[0] ) / RHO; - for (iDim = 0; iDim < nDim; iDim++) - dSm_dU[iDim+1] = - ( UnitNormal[iDim] * ( 2 * ProjVelocity_j - sR - sM) + dPI_dU[iDim+1] ) / RHO; - dSm_dU[nVar-1] = - dPI_dU[nVar-1] / RHO; - - - /*--- Computing d/dU_R (pStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dpStar_dU[iVar] = Density_j * (sL - ProjVelocity_i) * dSm_dU[iVar]; - - - /*--- Computing d/dU_R (rhoStar) ---*/ - - drhoStar_dU[0] = Omega * ( sR + IntermediateState[0] * dSm_dU[0] ); - for (iDim = 0; iDim < nDim; iDim++) - drhoStar_dU[iDim+1] = Omega * ( - UnitNormal[iDim] + IntermediateState[0] * dSm_dU[iDim+1] ); - drhoStar_dU[nVar-1] = Omega * IntermediateState[0] * dSm_dU[nVar-1]; - - - /*--- Computing d/dU_R (EStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); - - dEStar_dU[0] += Omega * ProjVelocity_j * ( Enthalpy_j - dPI_dU[0] ); - for (iDim = 0; iDim < nDim; iDim++) - dEStar_dU[iDim+1] += Omega * ( - UnitNormal[iDim] * Enthalpy_j - ProjVelocity_j * dPI_dU[iDim+1] ); - dEStar_dU[nVar-1] += Omega * ( sR - ProjVelocity_j - ProjVelocity_j * dPI_dU[nVar-1] ); - - - - /*--- Jacobian First Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[0][iVar] = sM * drhoStar_dU[iVar] + IntermediateState[0] * dSm_dU[iVar]; - - /*--- Jacobian Middle Rows ---*/ - - for (jDim = 0; jDim < nDim; jDim++) { - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[jDim+1][iVar] = ( OmegaSM + 1 ) * ( UnitNormal[jDim] * dpStar_dU[iVar] + IntermediateState[jDim+1] * dSm_dU[iVar] ); - - val_Jacobian_j[jDim+1][0] += OmegaSM * Velocity_j[jDim] * ProjVelocity_j; - - val_Jacobian_j[jDim+1][jDim+1] += OmegaSM * (sR - ProjVelocity_j); - - for (iDim = 0; iDim < nDim; iDim++) - val_Jacobian_j[jDim+1][iDim+1] -= OmegaSM * Velocity_j[jDim] * UnitNormal[iDim]; - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[jDim+1][iVar] -= OmegaSM * dPI_dU[iVar] * UnitNormal[jDim]; - } - - /*--- Jacobian Last Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[nVar-1][iVar] = sM * ( dEStar_dU[iVar] + dpStar_dU[iVar] ) + ( EStar + pStar ) * dSm_dU[iVar]; - - } - } - - - /*--- Jacobians of the inviscid flux, scale = k because val_residual ~ 0.5*(fc_i+fc_j)*Normal ---*/ - - Area *= kappa; - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_i[iVar][jVar] *= Area; - val_Jacobian_j[iVar][jVar] *= Area; - } - } -} - -} - -CUpwGeneralHLLC_Flow::CUpwGeneralHLLC_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - kappa = config->GetRoe_Kappa(); - /* 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(); - - Gamma = config->GetGamma(); - - IntermediateState = new su2double [nVar]; - dSm_dU = new su2double [nVar]; - dPI_dU = new su2double [nVar]; - drhoStar_dU = new su2double [nVar]; - dpStar_dU = new su2double [nVar]; - dEStar_dU = new su2double [nVar]; - - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - RoeVelocity = new su2double [nDim]; - -} - -CUpwGeneralHLLC_Flow::~CUpwGeneralHLLC_Flow(void) { - - delete [] IntermediateState; - delete [] dSm_dU; - delete [] dPI_dU; - delete [] drhoStar_dU; - delete [] dpStar_dU; - delete [] dEStar_dU; - - delete [] Velocity_i; - delete [] Velocity_j; - delete [] RoeVelocity; - -} - -void CUpwGeneralHLLC_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - /*--- Face area (norm or the normal vector) ---*/ - - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim] * Normal[iDim]; - - Area = sqrt(Area); - - /*-- Unit Normal ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = Normal[iDim] / Area; - - /*-- Fluid velocity at node i,j ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity_j[iDim] = V_j[iDim+1]; - } - - /*--- Primitive variables at point i ---*/ - - Pressure_i = V_i[nDim+1]; - Density_i = V_i[nDim+2]; - Enthalpy_i = V_i[nDim+3]; - - /*--- Primitive variables at point j ---*/ - - Pressure_j = V_j[nDim+1]; - Density_j = V_j[nDim+2]; - Enthalpy_j = V_j[nDim+3]; - - - sq_vel_i = 0.0; - sq_vel_j = 0.0; - - for (iDim = 0; iDim < nDim; iDim++) { - sq_vel_i += Velocity_i[iDim] * Velocity_i[iDim]; - sq_vel_j += Velocity_j[iDim] * Velocity_j[iDim]; - } - - Energy_i = Enthalpy_i - Pressure_i / Density_i; - StaticEnthalpy_i = Enthalpy_i - 0.5 * sq_vel_i; - StaticEnergy_i = Energy_i - 0.5 * sq_vel_i; - - Kappa_i = S_i[1] / Density_i; - Chi_i = S_i[0] - Kappa_i * StaticEnergy_i; - SoundSpeed_i = sqrt(Chi_i + StaticEnthalpy_i * Kappa_i); - - - Energy_j = Enthalpy_j - Pressure_j / Density_j; - StaticEnthalpy_j = Enthalpy_j - 0.5 * sq_vel_j; - StaticEnergy_j = Energy_j - 0.5 * sq_vel_j; - - Kappa_j = S_j[1] / Density_j; - Chi_j = S_j[0] - Kappa_j * StaticEnergy_j; - SoundSpeed_j = sqrt(Chi_j + StaticEnthalpy_j * Kappa_j); - - /*--- Projected velocities ---*/ - - ProjVelocity_i = 0.0; - ProjVelocity_j = 0.0; - - for (iDim = 0; iDim < nDim; iDim++) { - ProjVelocity_i += Velocity_i[iDim] * UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim] * UnitNormal[iDim]; - } - - - /*--- Projected Grid Velocity ---*/ - - ProjInterfaceVel = 0; - - if (dynamic_grid) { - - for (iDim = 0; iDim < nDim; iDim++) - ProjInterfaceVel += 0.5 * ( GridVel_i[iDim] + GridVel_j[iDim] )*UnitNormal[iDim]; - - SoundSpeed_i -= ProjInterfaceVel; - SoundSpeed_j += ProjInterfaceVel; - - ProjVelocity_i -= ProjInterfaceVel; - ProjVelocity_j -= ProjInterfaceVel; - } - - /*--- Roe's averaging ---*/ - - Rrho = ( sqrt(Density_i) + sqrt(Density_j) ); - - sq_velRoe = 0.0; - RoeProjVelocity = - ProjInterfaceVel; - - for (iDim = 0; iDim < nDim; iDim++) { - RoeVelocity[iDim] = ( Velocity_i[iDim] * sqrt(Density_i) + Velocity_j[iDim] * sqrt(Density_j) ) / Rrho; - sq_velRoe += RoeVelocity[iDim] * RoeVelocity[iDim]; - RoeProjVelocity += RoeVelocity[iDim] * UnitNormal[iDim]; - } - - /*--- Mean Roe variables iPoint and jPoint ---*/ - - RoeKappa = 0.5 * ( Kappa_i + Kappa_j ); - RoeChi = 0.5 * ( Chi_i + Chi_j ); - RoeDensity = sqrt( Density_i * Density_j ); - RoeEnthalpy = ( sqrt(Density_j) * Enthalpy_j + sqrt(Density_i) * Enthalpy_i) / Rrho; - - VinokurMontagne(); - - /*--- Roe-averaged speed of sound ---*/ - - //RoeSoundSpeed2 = RoeChi + RoeKappa * ( RoeEnthalpy - 0.5 * sq_velRoe ); - RoeSoundSpeed = sqrt( RoeChi + RoeKappa * ( RoeEnthalpy - 0.5 * sq_velRoe ) ) - ProjInterfaceVel; - - /*--- Speed of sound at L and R ---*/ - - sL = min( RoeProjVelocity - RoeSoundSpeed, ProjVelocity_i - SoundSpeed_i ); - sR = max( RoeProjVelocity + RoeSoundSpeed, ProjVelocity_j + SoundSpeed_j ); - - /*--- speed of contact surface ---*/ - - RHO = Density_j * (sR - ProjVelocity_j) - Density_i * (sL - ProjVelocity_i); - sM = ( Pressure_i - Pressure_j - Density_i * ProjVelocity_i * ( sL - ProjVelocity_i ) + Density_j * ProjVelocity_j * ( sR - ProjVelocity_j ) ) / RHO; - - /*--- Pressure at right and left (Pressure_j=Pressure_i) side of contact surface ---*/ - - pStar = Density_j * ( ProjVelocity_j - sR ) * ( ProjVelocity_j - sM ) + Pressure_j; - - -if (sM > 0.0) { - - if (sL > 0.0) { - - /*--- Compute Left Flux ---*/ - - val_residual[0] = Density_i * ProjVelocity_i; - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = Density_i * Velocity_i[iDim] * ProjVelocity_i + Pressure_i * UnitNormal[iDim]; - val_residual[nVar-1] = Enthalpy_i * Density_i * ProjVelocity_i; - } - else { - - /*--- Compute Flux Left Star from Left Star State ---*/ - - rhoSL = ( sL - ProjVelocity_i ) / ( sL - sM ); - - IntermediateState[0] = rhoSL * Density_i; - for (iDim = 0; iDim < nDim; iDim++) - IntermediateState[iDim+1] = rhoSL * ( Density_i * Velocity_i[iDim] + ( pStar - Pressure_i ) / ( sL - ProjVelocity_i ) * UnitNormal[iDim] ) ; - IntermediateState[nVar-1] = rhoSL * ( Density_i * Energy_i - ( Pressure_i * ProjVelocity_i - pStar * sM) / ( sL - ProjVelocity_i ) ); - - - val_residual[0] = sM * IntermediateState[0]; - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = sM * IntermediateState[iDim+1] + pStar * UnitNormal[iDim]; - val_residual[nVar-1] = sM * ( IntermediateState[nVar-1] + pStar ) + pStar * ProjInterfaceVel; - } - } - else { - - if (sR < 0.0) { - - /*--- Compute Right Flux ---*/ - - val_residual[0] = Density_j * ProjVelocity_j; - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = Density_j * Velocity_j[iDim] * ProjVelocity_j + Pressure_j * UnitNormal[iDim]; - val_residual[nVar-1] = Enthalpy_j * Density_j * ProjVelocity_j; - } - else { - - /*--- Compute Flux Right Star from Right Star State ---*/ - - rhoSR = ( sR - ProjVelocity_j ) / ( sR - sM ); - - IntermediateState[0] = rhoSR * Density_j; - for (iDim = 0; iDim < nDim; iDim++) - IntermediateState[iDim+1] = rhoSR * ( Density_j * Velocity_j[iDim] + ( pStar - Pressure_j ) / ( sR - ProjVelocity_j ) * UnitNormal[iDim] ) ; - IntermediateState[nVar-1] = rhoSR * ( Density_j * Energy_j - ( Pressure_j * ProjVelocity_j - pStar * sM ) / ( sR - ProjVelocity_j ) ); - - - val_residual[0] = sM * IntermediateState[0]; - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = sM * IntermediateState[iDim+1] + pStar * UnitNormal[iDim]; - val_residual[nVar-1] = sM * (IntermediateState[nVar-1] + pStar ) + pStar * ProjInterfaceVel; - } - } - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] *= Area; - - - if (implicit) { - - if (sM > 0.0) { - - if (sL > 0.0) { - - /*--- Compute Jacobian based on Left State ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_j[iVar][jVar] = 0; - - - GetInviscidProjJac(Velocity_i, &Enthalpy_i, &Chi_i, &Kappa_i, UnitNormal, 1.0, val_Jacobian_i); - - } - else { - /*--- Compute Jacobian based on Left Star State ---*/ - - EStar = IntermediateState[nVar-1]; - Omega = 1/(sL-sM); - OmegaSM = Omega * sM; - - - /*--------- Left Jacobian ---------*/ - - - /*--- Computing pressure derivatives d/dU_L (PI) ---*/ - - dPI_dU[0] = Chi_i - 0.5 * Kappa_i * sq_vel_i; - for (iDim = 0; iDim < nDim; iDim++) - dPI_dU[iDim+1] = - Kappa_i * Velocity_i[iDim]; - dPI_dU[nVar-1] = Kappa_i; - - - /*--- Computing d/dU_L (Sm) ---*/ - - dSm_dU[0] = ( - ProjVelocity_i * ProjVelocity_i + sM * sL + dPI_dU[0] ) / RHO; - for (iDim = 0; iDim < nDim; iDim++) - dSm_dU[iDim+1] = ( UnitNormal[iDim] * ( 2 * ProjVelocity_i - sL - sM ) + dPI_dU[iDim+1] ) / RHO; - dSm_dU[nVar-1] = dPI_dU[nVar-1] / RHO; - - - /*--- Computing d/dU_L (rhoStar) ---*/ - - drhoStar_dU[0] = Omega * ( sL + IntermediateState[0] * dSm_dU[0] ); - for (iDim = 0; iDim < nDim; iDim++) - drhoStar_dU[iDim+1] = Omega * ( - UnitNormal[iDim] + IntermediateState[0] * dSm_dU[iDim+1] ); - drhoStar_dU[nVar-1] = Omega * IntermediateState[0] * dSm_dU[nVar-1]; - - - /*--- Computing d/dU_L (pStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dpStar_dU[iVar] = Density_i * (sR - ProjVelocity_j) * dSm_dU[iVar]; - - - /*--- Computing d/dU_L (EStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); - - dEStar_dU[0] += Omega * ProjVelocity_i * ( Enthalpy_i - dPI_dU[0] ); - for (iDim = 0; iDim < nDim; iDim++) - dEStar_dU[iDim+1] += Omega * ( - UnitNormal[iDim] * Enthalpy_i - ProjVelocity_i * dPI_dU[iDim+1] ); - dEStar_dU[nVar-1] += Omega * ( sL - ProjVelocity_i - ProjVelocity_i * dPI_dU[nVar-1] ); - - - - /*--- Jacobian First Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[0][iVar] = sM * drhoStar_dU[iVar] + IntermediateState[0] * dSm_dU[iVar]; - - /*--- Jacobian Middle Rows ---*/ - - for (jDim = 0; jDim < nDim; jDim++) { - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[jDim+1][iVar] = ( OmegaSM + 1 ) * ( UnitNormal[jDim] * dpStar_dU[iVar] + IntermediateState[jDim+1] * dSm_dU[iVar] ); - - val_Jacobian_i[jDim+1][0] += OmegaSM * Velocity_i[jDim] * ProjVelocity_i; - - val_Jacobian_i[jDim+1][jDim+1] += OmegaSM * (sL - ProjVelocity_i); - - for (iDim = 0; iDim < nDim; iDim++) - val_Jacobian_i[jDim+1][iDim+1] -= OmegaSM * Velocity_i[jDim] * UnitNormal[iDim]; - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[jDim+1][iVar] -= OmegaSM * dPI_dU[iVar] * UnitNormal[jDim]; - } - - /*--- Jacobian Last Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[nVar-1][iVar] = sM * ( dEStar_dU[iVar] + dpStar_dU[iVar] ) + ( EStar + pStar ) * dSm_dU[iVar]; - - - - - /*--------- Right Jacobian ---------*/ - - - /*--- Computing pressure derivatives d/dU_R (PI) ---*/ - - dPI_dU[0] = Chi_j - 0.5 * Kappa_j * sq_vel_j; - for (iDim = 0; iDim < nDim; iDim++) - dPI_dU[iDim+1] = - Kappa_j * Velocity_j[iDim]; - dPI_dU[nVar-1] = Kappa_j; - - - /*--- Computing d/dU_R (Sm) ---*/ - - dSm_dU[0] = ( ProjVelocity_j * ProjVelocity_j - sM * sR - dPI_dU[0] ) / RHO; - for (iDim = 0; iDim < nDim; iDim++) - dSm_dU[iDim+1] = - ( UnitNormal[iDim] * ( 2 * ProjVelocity_j - sR - sM) + dPI_dU[iDim+1] ) / RHO; - dSm_dU[nVar-1] = - dPI_dU[nVar-1] / RHO; - - - /*--- Computing d/dU_R (pStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dpStar_dU[iVar] = Density_j * (sL - ProjVelocity_i) * dSm_dU[iVar]; - - - /*--- Computing d/dU_R (EStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); - - - - /*--- Jacobian First Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[0][iVar] = IntermediateState[0] * ( OmegaSM + 1 ) * dSm_dU[iVar]; - - /*--- Jacobian Middle Rows ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[iDim+1][iVar] = ( OmegaSM + 1 ) * ( IntermediateState[iDim+1] * dSm_dU[iVar] + UnitNormal[iDim] * dpStar_dU[iVar] ); - } - - /*--- Jacobian Last Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[nVar-1][iVar] = sM * (dEStar_dU[iVar] + dpStar_dU[iVar]) + (EStar + pStar) * dSm_dU[iVar]; - } - } - else { - if (sR < 0.0) { - - /*--- Compute Jacobian based on Right State ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_i[iVar][jVar] = 0; - - GetInviscidProjJac(Velocity_j, &Enthalpy_j, &Chi_j, &Kappa_j, UnitNormal, 1.0, val_Jacobian_j); - - } - else { - /*--- Compute Jacobian based on Right Star State ---*/ - - EStar = IntermediateState[nVar-1]; - Omega = 1/(sR-sM); - OmegaSM = Omega * sM; - - - /*--------- Left Jacobian ---------*/ - - - /*--- Computing pressure derivatives d/dU_L (PI) ---*/ - - dPI_dU[0] = Chi_i - 0.5 * Kappa_i * sq_vel_i; - for (iDim = 0; iDim < nDim; iDim++) - dPI_dU[iDim+1] = - Kappa_i * Velocity_i[iDim]; - dPI_dU[nVar-1] = Kappa_i; - - - /*--- Computing d/dU_L (Sm) ---*/ - - dSm_dU[0] = ( - ProjVelocity_i * ProjVelocity_i + sM * sL + dPI_dU[0] ) / RHO; - for (iDim = 0; iDim < nDim; iDim++) - dSm_dU[iDim+1] = ( UnitNormal[iDim] * ( 2 * ProjVelocity_i - sL - sM ) + dPI_dU[iDim+1] ) / RHO; - dSm_dU[nVar-1] = dPI_dU[nVar-1] / RHO; - - - /*--- Computing d/dU_L (pStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dpStar_dU[iVar] = Density_i * (sR - ProjVelocity_j) * dSm_dU[iVar]; - - - /*--- Computing d/dU_L (EStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); - - - - /*--- Jacobian First Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[0][iVar] = IntermediateState[0] * ( OmegaSM + 1 ) * dSm_dU[iVar]; - - /*--- Jacobian Middle Rows ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[iDim+1][iVar] = (OmegaSM + 1) * ( IntermediateState[iDim+1] * dSm_dU[iVar] + UnitNormal[iDim] * dpStar_dU[iVar] ); - } - - /*--- Jacobian Last Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_i[nVar-1][iVar] = sM * (dEStar_dU[iVar] + dpStar_dU[iVar]) + (EStar + pStar) * dSm_dU[iVar]; - - - - /*--------- Right Jacobian ---------*/ - - - /*--- Computing pressure derivatives d/dU_R (PI) ---*/ - - dPI_dU[0] = Chi_j - 0.5 * Kappa_j * sq_vel_j; - for (iDim = 0; iDim < nDim; iDim++) - dPI_dU[iDim+1] = - Kappa_j * Velocity_j[iDim]; - dPI_dU[nVar-1] = Kappa_j; - - - /*--- Computing d/dU_R (Sm) ---*/ - - dSm_dU[0] = - ( - ProjVelocity_j * ProjVelocity_j + sM * sR + dPI_dU[0] ) / RHO; - for (iDim = 0; iDim < nDim; iDim++) - dSm_dU[iDim+1] = - ( UnitNormal[iDim] * ( 2 * ProjVelocity_j - sR - sM) + dPI_dU[iDim+1] ) / RHO; - dSm_dU[nVar-1] = - dPI_dU[nVar-1] / RHO; - - - /*--- Computing d/dU_R (pStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dpStar_dU[iVar] = Density_j * (sL - ProjVelocity_i) * dSm_dU[iVar]; - - - /*--- Computing d/dU_R (rhoStar) ---*/ - - drhoStar_dU[0] = Omega * ( sR + IntermediateState[0] * dSm_dU[0] ); - for (iDim = 0; iDim < nDim; iDim++) - drhoStar_dU[iDim+1] = Omega * ( - UnitNormal[iDim] + IntermediateState[0] * dSm_dU[iDim+1] ); - drhoStar_dU[nVar-1] = Omega * IntermediateState[0] * dSm_dU[nVar-1]; - - - /*--- Computing d/dU_R (EStar) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - dEStar_dU[iVar] = Omega * ( sM * dpStar_dU[iVar] + ( EStar + pStar ) * dSm_dU[iVar] ); - - dEStar_dU[0] += Omega * ProjVelocity_j * ( Enthalpy_j - dPI_dU[0] ); - for (iDim = 0; iDim < nDim; iDim++) - dEStar_dU[iDim+1] += Omega * ( - UnitNormal[iDim] * Enthalpy_j - ProjVelocity_j * dPI_dU[iDim+1] ); - dEStar_dU[nVar-1] += Omega * ( sR - ProjVelocity_j - ProjVelocity_j * dPI_dU[nVar-1] ); - - - - /*--- Jacobian First Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[0][iVar] = sM * drhoStar_dU[iVar] + IntermediateState[0] * dSm_dU[iVar]; - - /*--- Jacobian Middle Rows ---*/ - - for (jDim = 0; jDim < nDim; jDim++) { - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[jDim+1][iVar] = ( OmegaSM + 1 ) * ( UnitNormal[jDim] * dpStar_dU[iVar] + IntermediateState[jDim+1] * dSm_dU[iVar] ); - - val_Jacobian_j[jDim+1][0] += OmegaSM * Velocity_j[jDim] * ProjVelocity_j; - - val_Jacobian_j[jDim+1][jDim+1] += OmegaSM * (sR - ProjVelocity_j); - - for (iDim = 0; iDim < nDim; iDim++) - val_Jacobian_j[jDim+1][iDim+1] -= OmegaSM * Velocity_j[jDim] * UnitNormal[iDim]; - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[jDim+1][iVar] -= OmegaSM * dPI_dU[iVar] * UnitNormal[jDim]; - } - - /*--- Jacobian Last Row ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_Jacobian_j[nVar-1][iVar] = sM * ( dEStar_dU[iVar] + dpStar_dU[iVar] ) + ( EStar + pStar ) * dSm_dU[iVar]; - } - } - - - /*--- Jacobians of the inviscid flux, scale = kappa because val_residual ~ 0.5*(fc_i+fc_j)*Normal ---*/ - - Area *= kappa; - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_i[iVar][jVar] *= Area; - val_Jacobian_j[iVar][jVar] *= Area; - } - } - - } - -} - -void CUpwGeneralHLLC_Flow::VinokurMontagne() { - - su2double delta_rhoStaticEnergy, delta_rho, delta_p, err_P, s, D; - - delta_rho = Density_j - Density_i; - delta_p = Pressure_j - Pressure_i; - - RoeKappaStaticEnthalpy = 0.5 * ( StaticEnthalpy_i * Kappa_i + StaticEnthalpy_j * Kappa_j ); - - s = RoeChi + RoeKappaStaticEnthalpy; - - D = s*s * delta_rho * delta_rho + delta_p * delta_p; - - delta_rhoStaticEnergy = Density_j * StaticEnergy_j - Density_i * StaticEnergy_i; - - err_P = delta_p - RoeChi * delta_rho - RoeKappa * delta_rhoStaticEnergy; - - if (abs((D - delta_p*err_P)/Density_i) > 1e-3 && abs(delta_rho/Density_i) > 1e-3 && s/Density_i > 1e-3) { - - RoeKappa = ( D * RoeKappa ) / ( D - delta_p * err_P ); - RoeChi = ( D * RoeChi+ s*s * delta_rho * err_P ) / ( D - delta_p * err_P ); - - } -} - -#ifdef CHECK - -int UgpWithCvCompFlow::calcEulerFluxMatrices_HLLC(su2double (*val_Jacobian_i)[5], su2double (*val_Jacobian_j)[5], su2double (*val_Jacobian_i_Scal)[6], su2double (*val_Jacobian_j_Scal)[6], - const su2double Density_i, const su2double *uL, const su2double pL, const su2double TL, const su2double h0, const su2double RL, const su2double gammaL, const su2double *scalL, const su2double kL, - const su2double Density_j, const su2double *uR, const su2double pR, const su2double TR, const su2double h1, const su2double RR, const su2double gammaR, const su2double *scalR, const su2double kR, - const su2double area, const su2double *nVec, const int nScal, const su2double surfVeloc) -{ - - su2double unL = vecDotVec3d(uL, nVec); - su2double uLuL = vecDotVec3d(uL, uL); - su2double cL = sqrt(gammaL*pL/Density_i); - su2double hL = gammaL/(gammaL-1.0)*pL/Density_i + 0.5*uLuL + kL; - // su2double hL = h0 + 0.5*uLuL + kL; - su2double eL = hL*Density_i-pL; - - su2double unR = vecDotVec3d(uR, nVec); - su2double uRuR = vecDotVec3d(uR, uR); - su2double cR = sqrt(gammaR*pR/Density_j); - su2double hR = gammaR/(gammaR-1.0)*pR/Density_j + 0.5*uRuR + kR; - // su2double hR = h1 + 0.5*uRuR + kR; - su2double eR = hR*Density_j-pR; - - - // Roe's aveaging - su2double Rrho = sqrt(Density_j/Density_i); - su2double tmp = 1.0/(1.0+Rrho); - su2double velRoe[3]; - for (int i=0; i<3; i++) - velRoe[i] = tmp*(uL[i] + uR[i]*Rrho); - su2double uRoe = vecDotVec3d(velRoe, nVec); - su2double hRoe = tmp*(hL + hR*Rrho); - - // su2double cRoe = sqrt((gammaL-1.0)*(hRoe- 0.5*vecDotVec3d(velRoe, velRoe))); - su2double gamPdivRho = tmp*((gammaL*pL/Density_i+0.5*(gammaL-1.0)*uLuL) + (gammaR*pR/Density_j+0.5*(gammaR-1.0)*uRuR)*Rrho); - su2double cRoe = sqrt(gamPdivRho - ((gammaL+gammaR)*0.5-1.0)*0.5*vecDotVec3d(velRoe, velRoe)); - - // speed of sound at L and R - su2double sL = min(uRoe-cRoe, unL-cL); - su2double sR = max(uRoe+cRoe, unR+cR); - - // speed of contact surface - su2double sM = (pL-pR-Density_i*unL*(sL-unL)+Density_j*unR*(sR-unR))/(Density_j*(sR-unR)-Density_i*(sL-unL)); - - // pressure at right and left (pR=pL) side of contact surface - su2double pStar = Density_j*(unR-sR)*(unR-sM)+pR; - - if (sM >= 0.0) { - - if (sL > 0.0) { - - su2double nVecArea[3]; - for (int i=0; i<3; i++) nVecArea[i] = nVec[i]*area; - - calcJacobianA(val_Jacobian_i, uL, pL, Density_i, nVecArea, 0.5*(gammaL+gammaR), 0.0); - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_j[i][j] = 0.0; - - } - else { - - su2double invSLmSs = 1.0/(sL-sM); - su2double sLmuL = sL-unL; - su2double rhoSL = Density_i*sLmuL*invSLmSs; - su2double rhouSL[3]; - - for (int i=0; i<3; i++) - rhouSL[i] = (Density_i*uL[i]*sLmuL+(pStar-pL)*nVec[i])*invSLmSs; - - su2double eSL = (sLmuL*eL-pL*unL+pStar*sM)*invSLmSs; - su2double gammaLM1 = (gammaL-1.0); - su2double gammaRM1 = (gammaR-1.0); - su2double invrhotld = 1.0/(Density_j*(sR-unR)-Density_i*(sL-unL)); - - su2double dSMdUL[5], dSMdUR[5]; - su2double dpsdUL[5], dpsdUR[5]; - - dSMdUL[0] = -unL*unL + uLuL*gammaLM1/2.0 + sM*sL; - dSMdUL[1] = nVec[0]*(2.0*unL-sL-sM) - gammaLM1*uL[0]; - dSMdUL[2] = nVec[1]*(2.0*unL-sL-sM) - gammaLM1*uL[1]; - dSMdUL[3] = nVec[2]*(2.0*unL-sL-sM) - gammaLM1*uL[2]; - dSMdUL[4] = gammaLM1; - - for (iVar = 0; iVar < nVar; iVar++) - { - dSMdUL[i] *= invrhotld; - dpsdUL[i] = Density_j*(sR-unR)*dSMdUL[i]; - } - - dSMdUR[0] = unR*unR - uRuR*gammaRM1/2.0 - sM*sR; - dSMdUR[1] = -nVec[0]*(2.0*unR-sR-sM) + gammaRM1*uR[0]; - dSMdUR[2] = -nVec[1]*(2.0*unR-sR-sM) + gammaRM1*uR[1]; - dSMdUR[3] = -nVec[2]*(2.0*unR-sR-sM) + gammaRM1*uR[2]; - dSMdUR[4] = -gammaRM1; - - for (iVar = 0; iVar < nVar; iVar++) - { - dSMdUR[i] *= invrhotld; - dpsdUR[i] = Density_i*(sL-unL)*dSMdUR[i]; - } - - calcSubSonicJacobeanHLLC(val_Jacobian_i, val_Jacobian_j, - Density_i, uL, pL, eL, unL, uLuL, sL, - rhoSL, rhouSL, eSL, dSMdUL, - dSMdUR, dpsdUL, dpsdUR, sM, pStar, 0.5*(gammaL+gammaR), nVec); - - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[0][i] = val_Jacobian_i[0][i]*sM + dSMdUL[i]*rhoSL; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[1][i] = val_Jacobian_i[1][i]*sM + dSMdUL[i]*rhouSL[0] + dpsdUL[i]*nVec[0]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[2][i] = val_Jacobian_i[2][i]*sM + dSMdUL[i]*rhouSL[1] + dpsdUL[i]*nVec[1]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[3][i] = val_Jacobian_i[3][i]*sM + dSMdUL[i]*rhouSL[2] + dpsdUL[i]*nVec[2]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[4][i] = (val_Jacobian_i[4][i]+dpsdUL[i])*sM + (eSL+pStar)*dSMdUL[i]; - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_i[i][j] *= area; - - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[0][i] = val_Jacobian_j[0][i]*sM + dSMdUR[i]*rhoSL; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[1][i] = val_Jacobian_j[1][i]*sM + dSMdUR[i]*rhouSL[0] + dpsdUR[i]*nVec[0]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[2][i] = val_Jacobian_j[2][i]*sM + dSMdUR[i]*rhouSL[1] + dpsdUR[i]*nVec[1]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[3][i] = val_Jacobian_j[3][i]*sM + dSMdUR[i]*rhouSL[2] + dpsdUR[i]*nVec[2]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[4][i] = (val_Jacobian_j[4][i]+dpsdUR[i])*sM + (eSL+pStar)*dSMdUR[i]; - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_j[i][j] *= area; - - } - } - - else { - - if (sR >= 0.0) { - - su2double invSRmSs = 1.0/(sR-sM); - su2double sRmuR = sR-unR; - su2double rhoSR = Density_j*sRmuR*invSRmSs; - su2double rhouSR[3]; - for (int i=0; i<3; i++) - rhouSR[i] = (Density_j*uR[i]*sRmuR+(pStar-pR)*nVec[i])*invSRmSs; - su2double eSR = (sRmuR*eR-pR*unR+pStar*sM)*invSRmSs; - su2double gammaLM1 = (gammaL-1.0); - su2double gammaRM1 = (gammaR-1.0); - su2double invrhotld = 1.0/(Density_j*(sR-unR)-Density_i*(sL-unL)); - - su2double dSMdUL[5], dSMdUR[5]; - su2double dpsdUL[5], dpsdUR[5]; - - dSMdUL[0] = -unL*unL + uLuL*gammaLM1/2.0 + sM*sL; - dSMdUL[1] = nVec[0]*(2.0*unL-sL-sM) - gammaLM1*uL[0]; - dSMdUL[2] = nVec[1]*(2.0*unL-sL-sM) - gammaLM1*uL[1]; - dSMdUL[3] = nVec[2]*(2.0*unL-sL-sM) - gammaLM1*uL[2]; - dSMdUL[4] = gammaLM1; - - for (iVar = 0; iVar < nVar; iVar++) { - dSMdUL[i] *= invrhotld; - dpsdUL[i] = Density_j*(sR-unR)*dSMdUL[i]; - } - - dSMdUR[0] = unR*unR - uRuR*gammaRM1/2.0 - sM*sR; - dSMdUR[1] = -nVec[0]*(2.0*unR-sR-sM) + gammaRM1*uR[0]; - dSMdUR[2] = -nVec[1]*(2.0*unR-sR-sM) + gammaRM1*uR[1]; - dSMdUR[3] = -nVec[2]*(2.0*unR-sR-sM) + gammaRM1*uR[2]; - dSMdUR[4] = -gammaRM1; - - for (iVar = 0; iVar < nVar; iVar++) { - dSMdUR[i] *= invrhotld; - dpsdUR[i] = Density_i*(sL-unL)*dSMdUR[i]; - } - - calcSubSonicJacobeanHLLC(val_Jacobian_j, val_Jacobian_i, - Density_j, uR, pR, eR, unR, uRuR, sR, - rhoSR, rhouSR, eSR, - dSMdUR, dSMdUL, dpsdUR, dpsdUL, sM, pStar, 0.5*(gammaL+gammaR), nVec); - - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[0][i] = val_Jacobian_i[0][i]*sM + dSMdUL[i]*rhoSR; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[1][i] = val_Jacobian_i[1][i]*sM + dSMdUL[i]*rhouSR[0] + dpsdUL[i]*nVec[0]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[2][i] = val_Jacobian_i[2][i]*sM + dSMdUL[i]*rhouSR[1] + dpsdUL[i]*nVec[1]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[3][i] = val_Jacobian_i[3][i]*sM + dSMdUL[i]*rhouSR[2] + dpsdUL[i]*nVec[2]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_i[4][i] = (val_Jacobian_i[4][i]+dpsdUL[i])*sM + (eSR+pStar)*dSMdUL[i]; - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_i[i][j] *= area; - - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[0][i] = val_Jacobian_j[0][i]*sM + dSMdUR[i]*rhoSR; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[1][i] = val_Jacobian_j[1][i]*sM + dSMdUR[i]*rhouSR[0] + dpsdUR[i]*nVec[0]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[2][i] = val_Jacobian_j[2][i]*sM + dSMdUR[i]*rhouSR[1] + dpsdUR[i]*nVec[1]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[3][i] = val_Jacobian_j[3][i]*sM + dSMdUR[i]*rhouSR[2] + dpsdUR[i]*nVec[2]; - for (iVar = 0; iVar < nVar; iVar++) val_Jacobian_j[4][i] = (val_Jacobian_j[4][i]+dpsdUR[i])*sM + (eSR+pStar)*dSMdUR[i]; - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_j[i][j] *= area; - - } - - else { - - su2double nVecArea[3]; - for (int i=0; i<3; i++) nVecArea[i] = nVec[i]*area; - calcJacobianA(val_Jacobian_j, uR, pR, Density_j, nVecArea, 0.5*(gammaL+gammaR), 0.0); - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_i[i][j] = 0.0; - - } - - } - -} - -void UgpWithCvCompFlow::calcSubSonicJacobeanHLLC(su2double (*AL)[5], su2double (*AR)[5], - su2double Density_i, const su2double *uL, su2double pL, su2double eL, su2double qL, su2double psiL, su2double SL, - su2double rhoSL, su2double *rhouSL, su2double eSL, - su2double *dSMdUL, su2double *dSMdUR, su2double *dpsdUL, su2double *dpsdUR, su2double SM, su2double pS, - su2double gamma, const su2double *nV) // nV is not normalized -{ - - su2double gammaMinus1 = (gamma-1.0); - su2double omL = 1.0/(SL-SM); - - AL[0][0] = SL + rhoSL*dSMdUL[0]; - AL[0][1] = -nV[0] + rhoSL*dSMdUL[1]; - AL[0][2] = -nV[1] + rhoSL*dSMdUL[2]; - AL[0][3] = -nV[2] + rhoSL*dSMdUL[3]; - AL[0][4] = + rhoSL*dSMdUL[4]; - - AL[1][0] = qL*uL[0] - nV[0]*psiL*gammaMinus1/2.0 + nV[0]*dpsdUL[0] + rhouSL[0]*dSMdUL[0]; - AL[1][1] = SL - qL + nV[0]*(gamma-2.0)*uL[0] + nV[0]*dpsdUL[1] + rhouSL[0]*dSMdUL[1]; - AL[1][2] = - uL[0]*nV[1] + nV[0]*gammaMinus1*uL[1] + nV[0]*dpsdUL[2] + rhouSL[0]*dSMdUL[2]; - AL[1][3] = - uL[0]*nV[2] + nV[0]*gammaMinus1*uL[2] + nV[0]*dpsdUL[3] + rhouSL[0]*dSMdUL[3]; - AL[1][4] = -gammaMinus1*nV[0] + nV[0]*dpsdUL[4] + rhouSL[0]*dSMdUL[4]; - - AL[2][0] = qL*uL[1] - nV[1]*psiL*gammaMinus1/2.0 + nV[1]*dpsdUL[0] + rhouSL[1]*dSMdUL[0]; - AL[2][1] = - uL[1]*nV[0] + nV[1]*gammaMinus1*uL[0] + nV[1]*dpsdUL[1] + rhouSL[1]*dSMdUL[1]; - AL[2][2] = SL - qL + nV[1]*(gamma-2.0)*uL[1] + nV[1]*dpsdUL[2] + rhouSL[1]*dSMdUL[2]; - AL[2][3] = - uL[1]*nV[2] + nV[1]*gammaMinus1*uL[2] + nV[1]*dpsdUL[3] + rhouSL[1]*dSMdUL[3]; - AL[2][4] = -gammaMinus1*nV[1] + nV[1]*dpsdUL[4] + rhouSL[1]*dSMdUL[4]; - - AL[3][0] = qL*uL[2] - nV[2]*psiL*gammaMinus1/2.0 + nV[2]*dpsdUL[0] + rhouSL[2]*dSMdUL[0]; - AL[3][1] = - uL[2]*nV[0] + nV[2]*gammaMinus1*uL[0] + nV[2]*dpsdUL[1] + rhouSL[2]*dSMdUL[1]; - AL[3][2] = - uL[2]*nV[1] + nV[2]*gammaMinus1*uL[1] + nV[2]*dpsdUL[2] + rhouSL[2]*dSMdUL[2]; - AL[3][3] = SL - qL + nV[2]*(gamma-2.0)*uL[2] + nV[2]*dpsdUL[3] + rhouSL[2]*dSMdUL[3]; - AL[3][4] = -gammaMinus1*nV[2] + nV[2]*dpsdUL[4] + rhouSL[2]*dSMdUL[4]; - - AL[4][0] = qL*(eL+pL)/Density_i - qL*psiL*(gamma-1.0)/2.0 + SM*dpsdUL[0] + (pS+eSL)*dSMdUL[0]; - AL[4][1] = - nV[0]*(eL+pL)/Density_i + gammaMinus1*uL[0]*qL + SM*dpsdUL[1] + (pS+eSL)*dSMdUL[1]; - AL[4][2] = - nV[1]*(eL+pL)/Density_i + gammaMinus1*uL[1]*qL + SM*dpsdUL[2] + (pS+eSL)*dSMdUL[2]; - AL[4][3] = - nV[2]*(eL+pL)/Density_i + gammaMinus1*uL[2]*qL + SM*dpsdUL[3] + (pS+eSL)*dSMdUL[3]; - AL[4][4] = SL-qL*gamma + SM*dpsdUL[4] + (pS+eSL)*dSMdUL[4]; - - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - AL[i][j] *= omL; - - for (iVar = 0; iVar < nVar; iVar++) AR[0][i] = omL*rhoSL*dSMdUR[i]; - for (iVar = 0; iVar < nVar; iVar++) AR[1][i] = omL*(nV[0]*dpsdUR[i]+rhouSL[0]*dSMdUR[i]); - for (iVar = 0; iVar < nVar; iVar++) AR[2][i] = omL*(nV[1]*dpsdUR[i]+rhouSL[1]*dSMdUR[i]); - for (iVar = 0; iVar < nVar; iVar++) AR[3][i] = omL*(nV[2]*dpsdUR[i]+rhouSL[2]*dSMdUR[i]); - for (iVar = 0; iVar < nVar; iVar++) AR[4][i] = omL*(dpsdUR[i]*SM+(pS+eSL)*dSMdUR[i]); - -} - -void UgpWithCvCompFlow::calcJacobianA(su2double (*A)[5], const su2double *vel, su2double pp, su2double rrho, const su2double *nV, su2double gamma, su2double surfVeloc) // nV is not normalized -{ - - su2double kapm1 = (gamma - 1.0); - - su2double nVel[3]; - nVel[0] = vel[0]*nV[0]; - nVel[1] = vel[1]*nV[1]; - nVel[2] = vel[2]*nV[2]; - su2double U_k = nVel[0]+nVel[1]+nVel[2]; - su2double vSquHlf = 0.5*vecDotVec3d(vel, vel); - su2double c = sqrt(gamma*pp/rrho); - su2double inv_kap_m1 = 1.0/kapm1; - - A[0][0] =-surfVeloc; - A[0][1] = nV[0]; - A[0][2] = nV[1]; - A[0][3] = nV[2]; - A[0][4] = 0.0; - - A[1][0] = -vel[0]*(nVel[1]+nVel[2])+nV[0]*(kapm1*vSquHlf-vel[0]*vel[0]); - A[1][1] = (2.-gamma)*nVel[0]+U_k-surfVeloc; - A[1][2] = vel[0]*nV[1]-kapm1*vel[1]*nV[0]; - A[1][3] = vel[0]*nV[2]-kapm1*vel[2]*nV[0]; - A[1][4] = kapm1*nV[0]; - - A[2][0] = -vel[1]*(nVel[0]+nVel[2])+nV[1]*(kapm1*vSquHlf-vel[1]*vel[1]); - A[2][1] = -kapm1*vel[0]*nV[1]+ vel[1]*nV[0]; - A[2][2] = (2.-gamma)*nVel[1]+U_k-surfVeloc; - A[2][3] = vel[1]*nV[2]-kapm1*vel[2]*nV[1]; - A[2][4] = kapm1*nV[1]; - - A[3][0] = -vel[2]*(nVel[0]+nVel[1])+nV[2]*(kapm1*vSquHlf-vel[2]*vel[2]); - A[3][1] = -kapm1*vel[0]*nV[2]+vel[2]*nV[0]; - A[3][2] = -kapm1*vel[1]*nV[2]+vel[2]*nV[1]; - A[3][3] = (2.-gamma)*nVel[2]+U_k-surfVeloc; - A[3][4] = kapm1*nV[2]; - - A[4][0] = U_k*((gamma-2.)*vSquHlf-c*c*inv_kap_m1); - A[4][1] = c*c*inv_kap_m1*nV[0]-kapm1*vel[0]*(nVel[1]+nVel[2])-(kapm1*vel[0]*vel[0]-vSquHlf)*nV[0]; - A[4][2] = c*c*inv_kap_m1*nV[1]-kapm1*vel[1]*(nVel[0]+nVel[2])-(kapm1*vel[1]*vel[1]-vSquHlf)*nV[1]; - A[4][3] = c*c*inv_kap_m1*nV[2]-kapm1*vel[2]*(nVel[0]+nVel[1])-(kapm1*vel[2]*vel[2]-vSquHlf)*nV[2]; - A[4][4] = gamma*U_k-surfVeloc; - -} - - -#endif - - -CUpwRoeBase_Flow::CUpwRoeBase_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config, - bool val_low_dissipation) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - /* 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(); - kappa = config->GetRoe_Kappa(); // 1 is unstable - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - roe_low_dissipation = val_low_dissipation; - - Diff_U = new su2double [nVar]; - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - RoeVelocity = new su2double [nDim]; - ProjFlux_i = new su2double [nVar]; - ProjFlux_j = new su2double [nVar]; - Conservatives_i = new su2double [nVar]; - Conservatives_j = new su2double [nVar]; - Lambda = new su2double [nVar]; - P_Tensor = new su2double* [nVar]; - invP_Tensor = new su2double* [nVar]; - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - P_Tensor[iVar] = new su2double [nVar]; - invP_Tensor[iVar] = new su2double [nVar]; - } -} - -CUpwRoeBase_Flow::~CUpwRoeBase_Flow(void) { - - delete [] Diff_U; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] RoeVelocity; - delete [] ProjFlux_i; - delete [] ProjFlux_j; - delete [] Conservatives_i; - delete [] Conservatives_j; - delete [] Lambda; - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - delete [] P_Tensor[iVar]; - delete [] invP_Tensor[iVar]; - } - delete [] P_Tensor; - delete [] invP_Tensor; - -} - -void CUpwRoeBase_Flow::FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { -/*--- - CUpwRoeBase_Flow::ComputeResidual initializes the residual (flux) and its Jacobians with the standard Roe averaging - fc_{1/2} = kappa*(fc_i+fc_j)*Normal. It then calls this method, which derived classes specialize, to account for - the dissipation part. ----*/ -} - -void CUpwRoeBase_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - unsigned short iVar, jVar, iDim; - su2double ProjGridVel = 0.0, Energy_i, Energy_j; - - AD::StartPreacc(); - AD::SetPreaccIn(V_i, nDim+4); AD::SetPreaccIn(V_j, nDim+4); AD::SetPreaccIn(Normal, nDim); - if (dynamic_grid) { - AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); - } - if (roe_low_dissipation){ - AD::SetPreaccIn(Sensor_i); AD::SetPreaccIn(Sensor_j); - AD::SetPreaccIn(Dissipation_i); AD::SetPreaccIn(Dissipation_j); - } - - /*--- Face area (norm or the normal vector) and unit normal ---*/ - - 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; - - /*--- Primitive variables at point i ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - Velocity_i[iDim] = V_i[iDim+1]; - Pressure_i = V_i[nDim+1]; - Density_i = V_i[nDim+2]; - Enthalpy_i = V_i[nDim+3]; - Energy_i = Enthalpy_i - Pressure_i/Density_i; - - /*--- Primitive variables at point j ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - Velocity_j[iDim] = V_j[iDim+1]; - Pressure_j = V_j[nDim+1]; - Density_j = V_j[nDim+2]; - Enthalpy_j = V_j[nDim+3]; - Energy_j = Enthalpy_j - Pressure_j/Density_j; - - /*--- Compute variables that are common to the derived schemes ---*/ - - /*--- Roe-averaged variables at interface between i & j ---*/ - - su2double R = sqrt(fabs(Density_j/Density_i)); - RoeDensity = R*Density_i; - su2double sq_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); - sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; - } - RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); - RoeSoundSpeed2 = (Gamma-1)*(RoeEnthalpy-0.5*sq_vel); - - /*--- Negative RoeSoundSpeed^2, the jump variables is too large, clear fluxes and exit. ---*/ - - if (RoeSoundSpeed2 <= 0.0) { - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = 0.0; - if (implicit){ - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_i[iVar][jVar] = 0.0; - val_Jacobian_j[iVar][jVar] = 0.0; - } - } - } - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - return; - } - - RoeSoundSpeed = sqrt(RoeSoundSpeed2); - - /*--- P tensor ---*/ - - GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, P_Tensor); - - /*--- Projected velocity adjusted for mesh motion ---*/ - - ProjVelocity = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; - - if (dynamic_grid) { - for (iDim = 0; iDim < nDim; iDim++) - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*UnitNormal[iDim]; - ProjVelocity -= ProjGridVel; - } - - /*--- Flow eigenvalues ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - Lambda[iDim] = ProjVelocity; - - Lambda[nVar-2] = ProjVelocity + RoeSoundSpeed; - Lambda[nVar-1] = ProjVelocity - RoeSoundSpeed; - - /*--- Apply Mavriplis' entropy correction to eigenvalues ---*/ - - su2double MaxLambda = fabs(ProjVelocity) + RoeSoundSpeed; - - for (iVar = 0; iVar < nVar; iVar++) - Lambda[iVar] = max(fabs(Lambda[iVar]), config->GetEntropyFix_Coeff()*MaxLambda); - - /*--- Reconstruct conservative variables ---*/ - - Conservatives_i[0] = Density_i; - Conservatives_j[0] = Density_j; - - for (iDim = 0; iDim < nDim; iDim++) { - Conservatives_i[iDim+1] = Density_i*Velocity_i[iDim]; - Conservatives_j[iDim+1] = Density_j*Velocity_j[iDim]; - } - Conservatives_i[nDim+1] = Density_i*Energy_i; - Conservatives_j[nDim+1] = Density_j*Energy_j; - - /*--- Compute left and right fluxes ---*/ - - GetInviscidProjFlux(&Density_i, Velocity_i, &Pressure_i, &Enthalpy_i, Normal, ProjFlux_i); - GetInviscidProjFlux(&Density_j, Velocity_j, &Pressure_j, &Enthalpy_j, Normal, ProjFlux_j); - - /*--- Initialize residual (flux) and Jacobians ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] = kappa*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); - - if (implicit) { - GetInviscidProjJac(Velocity_i, &Energy_i, Normal, kappa, val_Jacobian_i); - GetInviscidProjJac(Velocity_j, &Energy_j, Normal, kappa, val_Jacobian_j); - } - - /*--- Finalize in children class ---*/ - - FinalizeResidual(val_residual, val_Jacobian_i, val_Jacobian_j, config); - - /*--- Correct for grid motion ---*/ - - if (dynamic_grid) { - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] -= ProjGridVel*Area * 0.5*(Conservatives_i[iVar]+Conservatives_j[iVar]); - - if (implicit) { - val_Jacobian_i[iVar][iVar] -= 0.5*ProjGridVel*Area; - val_Jacobian_j[iVar][iVar] -= 0.5*ProjGridVel*Area; - } - } - } - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - -} - -CUpwRoe_Flow::CUpwRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config, - bool val_low_dissipation) : CUpwRoeBase_Flow(val_nDim, val_nVar, config, val_low_dissipation) {} - -CUpwRoe_Flow::~CUpwRoe_Flow() {} - -void CUpwRoe_Flow::FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, - su2double **val_Jacobian_j, CConfig *config) { - - unsigned short iVar, jVar, kVar; - - /*--- Compute inverse P tensor ---*/ - GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); - - /*--- Diference between conservative variables at jPoint and iPoint ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Diff_U[iVar] = Conservatives_j[iVar]-Conservatives_i[iVar]; - - /*--- Low dissipation formulation ---*/ - if (roe_low_dissipation) - SetRoe_Dissipation(Dissipation_i, Dissipation_j, Sensor_i, Sensor_j, Dissipation_ij, config); - else - Dissipation_ij = 1.0; - - /*--- Standard Roe "dissipation" ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ - su2double Proj_ModJac_Tensor_ij = 0.0; - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; - - /*--- Update residual and Jacobians ---*/ - val_residual[iVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Diff_U[jVar]*Area*Dissipation_ij; - - if(implicit){ - val_Jacobian_i[iVar][jVar] += (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; - val_Jacobian_j[iVar][jVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; - } - } - } - -} - -CUpwL2Roe_Flow::CUpwL2Roe_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : - CUpwRoeBase_Flow(val_nDim, val_nVar, config, false) {} - -CUpwL2Roe_Flow::~CUpwL2Roe_Flow() {} - -void CUpwL2Roe_Flow::FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, - su2double **val_Jacobian_j, CConfig *config) { - - /*--- L2Roe: a low dissipation version of Roe's approximate Riemann solver for low Mach numbers. IJNMF 2015 ---*/ - - unsigned short iVar, jVar, kVar, iDim; - - /*--- Clamped Mach number ---*/ - - su2double M_i = 0.0, M_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - M_i += Velocity_i[iDim]*Velocity_i[iDim]; - M_j += Velocity_j[iDim]*Velocity_j[iDim]; - } - M_i = sqrt(M_i / fabs(Pressure_i*Gamma/Density_i)); - M_j = sqrt(M_j / fabs(Pressure_j*Gamma/Density_j)); - - su2double zeta = max(0.05,min(max(M_i,M_j),1.0)); - - /*--- Compute wave amplitudes (characteristics) ---*/ - - su2double proj_delta_vel = 0.0, delta_vel[3]; - for (iDim = 0; iDim < nDim; iDim++) { - delta_vel[iDim] = Velocity_j[iDim] - Velocity_i[iDim]; - proj_delta_vel += delta_vel[iDim]*UnitNormal[iDim]; - } - proj_delta_vel *= zeta; - su2double delta_p = Pressure_j - Pressure_i; - su2double delta_rho = Density_j - Density_i; - - su2double delta_wave[5] = {0.0, 0.0, 0.0, 0.0, 0.0}; - if (nDim == 2) { - delta_wave[0] = delta_rho - delta_p/RoeSoundSpeed2; - delta_wave[1] = (UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1])*zeta; - delta_wave[2] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - delta_wave[3] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - } else { - delta_wave[0] = delta_rho - delta_p/RoeSoundSpeed2; - delta_wave[1] = (UnitNormal[0]*delta_vel[2]-UnitNormal[2]*delta_vel[0])*zeta; - delta_wave[2] = (UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1])*zeta; - delta_wave[3] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - delta_wave[4] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - } - - /*--- Update residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - for (kVar = 0; kVar < nVar; kVar++) - val_residual[iVar] -= (1.0-kappa)*Lambda[kVar]*delta_wave[kVar]*P_Tensor[iVar][kVar]*Area; - - if (!implicit) return; - - /*--- If implicit use the Jacobians of the standard Roe scheme as an approximation ---*/ - - GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ - su2double Proj_ModJac_Tensor_ij = 0.0; - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; - - val_Jacobian_i[iVar][jVar] += (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; - val_Jacobian_j[iVar][jVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; - } - } - -} - -CUpwLMRoe_Flow::CUpwLMRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : - CUpwRoeBase_Flow(val_nDim, val_nVar, config, false) {} - -CUpwLMRoe_Flow::~CUpwLMRoe_Flow() {} - -void CUpwLMRoe_Flow::FinalizeResidual(su2double *val_residual, su2double **val_Jacobian_i, - su2double **val_Jacobian_j, CConfig *config) { - - /*--- Rieper, A low-Mach number fix for Roe's approximate Riemman Solver, JCP 2011 ---*/ - - unsigned short iVar, jVar, kVar, iDim; - - /*--- Clamped Mach number ---*/ - - su2double M_i = 0.0, M_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - M_i += Velocity_i[iDim]*Velocity_i[iDim]; - M_j += Velocity_j[iDim]*Velocity_j[iDim]; - } - M_i = sqrt(M_i / fabs(Pressure_i*Gamma/Density_i)); - M_j = sqrt(M_j / fabs(Pressure_j*Gamma/Density_j)); - - su2double zeta = max(0.05,min(max(M_i,M_j),1.0)); - - /*--- Compute wave amplitudes (characteristics) ---*/ - - su2double proj_delta_vel = 0.0, delta_vel[3]; - for (iDim = 0; iDim < nDim; iDim++) { - delta_vel[iDim] = Velocity_j[iDim] - Velocity_i[iDim]; - proj_delta_vel += delta_vel[iDim]*UnitNormal[iDim]; - } - proj_delta_vel *= zeta; - su2double delta_p = Pressure_j - Pressure_i; - su2double delta_rho = Density_j - Density_i; - - su2double delta_wave[5] = {0.0, 0.0, 0.0, 0.0, 0.0}; - if (nDim == 2) { - delta_wave[0] = delta_rho - delta_p/RoeSoundSpeed2; - delta_wave[1] = (UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]); - delta_wave[2] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - delta_wave[3] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - } else { - delta_wave[0] = delta_rho - delta_p/RoeSoundSpeed2; - delta_wave[1] = (UnitNormal[0]*delta_vel[2]-UnitNormal[2]*delta_vel[0]); - delta_wave[2] = (UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]); - delta_wave[3] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - delta_wave[4] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - } - - /*--- Update residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - for (kVar = 0; kVar < nVar; kVar++) - val_residual[iVar] -= (1.0-kappa)*Lambda[kVar]*delta_wave[kVar]*P_Tensor[iVar][kVar]*Area; - - if (!implicit) return; - - /*--- If implicit use the Jacobians of the standard Roe scheme as an approximation ---*/ - - GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ - su2double Proj_ModJac_Tensor_ij = 0.0; - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; - - val_Jacobian_i[iVar][jVar] += (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; - val_Jacobian_j[iVar][jVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; - } - } - -} - -CUpwGeneralRoe_Flow::CUpwGeneralRoe_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - /* 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(); - kappa = config->GetRoe_Kappa(); // 1 is unstable - - - Diff_U = new su2double [nVar]; - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - RoeVelocity = new su2double [nDim]; - delta_vel = new su2double [nDim]; - delta_wave = new su2double [nVar]; - ProjFlux_i = new su2double [nVar]; - ProjFlux_j = new su2double [nVar]; - Lambda = new su2double [nVar]; - Epsilon = new su2double [nVar]; - P_Tensor = new su2double* [nVar]; - invP_Tensor = new su2double* [nVar]; - - for (iVar = 0; iVar < nVar; iVar++) { - P_Tensor[iVar] = new su2double [nVar]; - invP_Tensor[iVar] = new su2double [nVar]; - } -} - -CUpwGeneralRoe_Flow::~CUpwGeneralRoe_Flow(void) { - - delete [] Diff_U; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] RoeVelocity; - delete [] delta_vel; - delete [] delta_wave; - delete [] ProjFlux_i; - delete [] ProjFlux_j; - delete [] Lambda; - delete [] Epsilon; - for (iVar = 0; iVar < nVar; iVar++) { - delete [] P_Tensor[iVar]; - delete [] invP_Tensor[iVar]; - } - delete [] P_Tensor; - delete [] invP_Tensor; - -} - -void CUpwGeneralRoe_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - AD::StartPreacc(); - AD::SetPreaccIn(V_i, nDim+4); AD::SetPreaccIn(V_j, nDim+4); AD::SetPreaccIn(Normal, nDim); - AD::SetPreaccIn(S_i, 2); AD::SetPreaccIn(S_j, 2); - if (dynamic_grid) { - AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); - } - su2double U_i[5] = {0.0,0.0,0.0,0.0,0.0}, U_j[5] = {0.0,0.0,0.0,0.0,0.0}; - - /*--- Face area (norm or the normal vector) ---*/ - - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim]*Normal[iDim]; - Area = sqrt(Area); - - /*-- Unit Normal ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = Normal[iDim]/Area; - - /*--- Primitive variables at point i ---*/ - - Velocity2_i = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity2_i += Velocity_i[iDim]*Velocity_i[iDim]; - } - - Pressure_i = V_i[nDim+1]; - Density_i = V_i[nDim+2]; - Enthalpy_i = V_i[nDim+3]; - Energy_i = Enthalpy_i - Pressure_i/Density_i; - StaticEnthalpy_i = Enthalpy_i - 0.5*Velocity2_i; - StaticEnergy_i = StaticEnthalpy_i - Pressure_i/Density_i; - - Kappa_i = S_i[1]/Density_i; - Chi_i = S_i[0] - Kappa_i*StaticEnergy_i; - SoundSpeed_i = sqrt(Chi_i + StaticEnthalpy_i*Kappa_i); - - /*--- Primitive variables at point j ---*/ - - - Velocity2_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_j[iDim] = V_j[iDim+1]; - Velocity2_j += Velocity_j[iDim]*Velocity_j[iDim]; - } - - Pressure_j = V_j[nDim+1]; - Density_j = V_j[nDim+2]; - Enthalpy_j = V_j[nDim+3]; - Energy_j = Enthalpy_j - Pressure_j/Density_j; - - StaticEnthalpy_j = Enthalpy_j - 0.5*Velocity2_j; - StaticEnergy_j = StaticEnthalpy_j - Pressure_j/Density_j; - - Kappa_j = S_j[1]/Density_j; - Chi_j = S_j[0] - Kappa_j*StaticEnergy_j; - SoundSpeed_j = sqrt(Chi_j + StaticEnthalpy_j*Kappa_j); - - /*--- Recompute conservative variables ---*/ - - U_i[0] = Density_i; U_j[0] = Density_j; - for (iDim = 0; iDim < nDim; iDim++) { - U_i[iDim+1] = Density_i*Velocity_i[iDim]; U_j[iDim+1] = Density_j*Velocity_j[iDim]; - } - U_i[nDim+1] = Density_i*Energy_i; U_j[nDim+1] = Density_j*Energy_j; - -// /*--- Roe-averaged variables at interface between i & j ---*/ - - ComputeRoeAverage(); - - if (RoeSoundSpeed2 <= 0.0) { - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = 0.0; - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_i[iVar][iVar] = 0.0; - val_Jacobian_j[iVar][iVar] = 0.0; - } - } - return; - } - - RoeSoundSpeed = sqrt(RoeSoundSpeed2); - - /*--- Compute ProjFlux_i ---*/ - GetInviscidProjFlux(&Density_i, Velocity_i, &Pressure_i, &Enthalpy_i, Normal, ProjFlux_i); - - /*--- Compute ProjFlux_j ---*/ - GetInviscidProjFlux(&Density_j, Velocity_j, &Pressure_j, &Enthalpy_j, Normal, ProjFlux_j); - - /*--- Compute P and Lambda (do it with the Normal) ---*/ - - GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, &RoeEnthalpy, &RoeChi, &RoeKappa, UnitNormal, P_Tensor); - - ProjVelocity = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; - ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; - } - - /*--- Projected velocity adjustment due to mesh motion ---*/ - if (dynamic_grid) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*UnitNormal[iDim]; - } - ProjVelocity -= ProjGridVel; - ProjVelocity_i -= ProjGridVel; - ProjVelocity_j -= ProjGridVel; - } - - /*--- Flow eigenvalues and entropy correctors ---*/ - for (iDim = 0; iDim < nDim; iDim++) - Lambda[iDim] = ProjVelocity; - - Lambda[nVar-2] = ProjVelocity + RoeSoundSpeed; - Lambda[nVar-1] = ProjVelocity - RoeSoundSpeed; - - /*--- Compute absolute value with Mavriplis' entropy correction ---*/ - - MaxLambda = fabs(ProjVelocity) + RoeSoundSpeed; - Delta = config->GetEntropyFix_Coeff(); - - for (iVar = 0; iVar < nVar; iVar++) { - Lambda[iVar] = max(fabs(Lambda[iVar]), Delta*MaxLambda); - } - -// /*--- Harten and Hyman (1983) entropy correction ---*/ -// for (iDim = 0; iDim < nDim; iDim++) -// Epsilon[iDim] = 4.0*max(0.0, max(Lambda[iDim]-ProjVelocity_i, ProjVelocity_j-Lambda[iDim])); -// -// Epsilon[nVar-2] = 4.0*max(0.0, max(Lambda[nVar-2]-(ProjVelocity_i+SoundSpeed_i),(ProjVelocity_j+SoundSpeed_j)-Lambda[nVar-2])); -// Epsilon[nVar-1] = 4.0*max(0.0, max(Lambda[nVar-1]-(ProjVelocity_i-SoundSpeed_i),(ProjVelocity_j-SoundSpeed_j)-Lambda[nVar-1])); -// -// for (iVar = 0; iVar < nVar; iVar++) -// if ( fabs(Lambda[iVar]) < Epsilon[iVar] ) -// Lambda[iVar] = (Lambda[iVar]*Lambda[iVar] + Epsilon[iVar]*Epsilon[iVar])/(2.0*Epsilon[iVar]); -// else -// Lambda[iVar] = fabs(Lambda[iVar]); - -// for (iVar = 0; iVar < nVar; iVar++) -// Lambda[iVar] = fabs(Lambda[iVar]); - - if (!implicit) { - - /*--- Compute wave amplitudes (characteristics) ---*/ - proj_delta_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - delta_vel[iDim] = Velocity_j[iDim] - Velocity_i[iDim]; - proj_delta_vel += delta_vel[iDim]*Normal[iDim]; - } - delta_p = Pressure_j - Pressure_i; - delta_rho = Density_j - Density_i; - proj_delta_vel = proj_delta_vel/Area; - - if (nDim == 2) { - delta_wave[0] = delta_rho - delta_p/(RoeSoundSpeed*RoeSoundSpeed); - delta_wave[1] = UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]; - delta_wave[2] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - delta_wave[3] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - } else { - delta_wave[0] = delta_rho - delta_p/(RoeSoundSpeed*RoeSoundSpeed); - delta_wave[1] = UnitNormal[0]*delta_vel[2]-UnitNormal[2]*delta_vel[0]; - delta_wave[2] = UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]; - delta_wave[3] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - delta_wave[4] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - } - - /*--- Roe's Flux approximation ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = 0.5*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); - for (jVar = 0; jVar < nVar; jVar++) - val_residual[iVar] -= 0.5*Lambda[jVar]*delta_wave[jVar]*P_Tensor[iVar][jVar]*Area; - } - - /*--- Flux contribution due to grid motion ---*/ - if (dynamic_grid) { - ProjVelocity = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); - } - } - } - else { - - /*--- Compute inverse P ---*/ - - GetPMatrix_inv(invP_Tensor, &RoeDensity, RoeVelocity, &RoeSoundSpeed, &RoeChi , &RoeKappa, UnitNormal); - - /*--- Jacobians of the inviscid flux, scaled by - kappa because val_resconv ~ kappa*(fc_i+fc_j)*Normal ---*/ - - GetInviscidProjJac(Velocity_i, &Enthalpy_i, &Chi_i, &Kappa_i, Normal, kappa, val_Jacobian_i); - - GetInviscidProjJac(Velocity_j, &Enthalpy_j, &Chi_j, &Kappa_j, Normal, kappa, val_Jacobian_j); - - - /*--- Diference variables iPoint and jPoint ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Diff_U[iVar] = U_j[iVar]-U_i[iVar]; - - /*--- Roe's Flux approximation ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = kappa*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); - for (jVar = 0; jVar < nVar; jVar++) { - Proj_ModJac_Tensor_ij = 0.0; - - /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ - - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; - - val_residual[iVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Diff_U[jVar]*Area; - val_Jacobian_i[iVar][jVar] += (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; - val_Jacobian_j[iVar][jVar] -= (1.0-kappa)*Proj_ModJac_Tensor_ij*Area; - } - } - - /*--- Jacobian contributions due to grid motion ---*/ - if (dynamic_grid) { - ProjVelocity = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); - /*--- Implicit terms ---*/ - val_Jacobian_i[iVar][iVar] -= 0.5*ProjVelocity; - val_Jacobian_j[iVar][iVar] -= 0.5*ProjVelocity; - } - } - - } - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); -} - - -void CUpwGeneralRoe_Flow::ComputeRoeAverage() { - - //su2double delta_rhoStaticEnergy, err_P, s, D; - // su2double tol = 10-6; - - R = sqrt(fabs(Density_j/Density_i)); - RoeDensity = R*Density_i; - sq_vel = 0; for (iDim = 0; iDim < nDim; iDim++) { - RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); - sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; - } - - RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); - delta_rho = Density_j - Density_i; - delta_p = Pressure_j - Pressure_i; - RoeKappa = 0.5*(Kappa_i + Kappa_j); - RoeKappa = (Kappa_i + Kappa_j + 4*RoeKappa)/6; - RoeChi = 0.5*(Chi_i + Chi_j); - RoeChi = (Chi_i + Chi_j + 4*RoeChi)/6; - - -// RoeKappaStaticEnthalpy = 0.5*(StaticEnthalpy_i*Kappa_i + StaticEnthalpy_j*Kappa_j); -// RoeKappaStaticEnthalpy = (StaticEnthalpy_i*Kappa_i + StaticEnthalpy_j*Kappa_j + 4*RoeKappaStaticEnthalpy)/6; -// s = RoeChi + RoeKappaStaticEnthalpy; -// D = s*s*delta_rho*delta_rho + delta_p*delta_p; -// delta_rhoStaticEnergy = Density_j*StaticEnergy_j - Density_i*StaticEnergy_i; -// err_P = delta_p - RoeChi*delta_rho - RoeKappa*delta_rhoStaticEnergy; -// -// -// if (abs((D - delta_p*err_P)/Density_i)>1e-3 && abs(delta_rho/Density_i)>1e-3 && s/Density_i > 1e-3) { -// -// RoeKappa = (D*RoeKappa)/(D - delta_p*err_P); -// RoeChi = (D*RoeChi+ s*s*delta_rho*err_P)/(D - delta_p*err_P); -// -// } - - RoeSoundSpeed2 = RoeChi + RoeKappa*(RoeEnthalpy-0.5*sq_vel); - -} - -CUpwMSW_Flow::CUpwMSW_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - if (config->GetDynamic_Grid() && (SU2_MPI::GetRank() == MASTER_NODE)) - cout << "WARNING: Grid velocities are NOT yet considered in the MSW scheme." << endl; - - /*--- Set booleans from CConfig settings ---*/ - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - /*--- Allocate arrays ---*/ - Diff_U = new su2double [nVar]; - Fc_i = new su2double [nVar]; - Fc_j = new su2double [nVar]; - Lambda_i = new su2double [nVar]; - Lambda_j = new su2double [nVar]; - - u_i = new su2double [nDim]; - u_j = new su2double [nDim]; - ust_i = new su2double [nDim]; - ust_j = new su2double [nDim]; - Vst_i = new su2double [nPrimVar]; - Vst_j = new su2double [nPrimVar]; - Ust_i = new su2double [nVar]; - Ust_j = new su2double [nVar]; - - Velst_i = new su2double [nDim]; - Velst_j = new su2double [nDim]; - - P_Tensor = new su2double* [nVar]; - invP_Tensor = new su2double* [nVar]; - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - P_Tensor[iVar] = new su2double [nVar]; - invP_Tensor[iVar] = new su2double [nVar]; - } - -} - -CUpwMSW_Flow::~CUpwMSW_Flow(void) { - - delete [] Diff_U; - delete [] Fc_i; - delete [] Fc_j; - delete [] Lambda_i; - delete [] Lambda_j; - - delete [] u_i; - delete [] u_j; - delete [] ust_i; - delete [] ust_j; - delete [] Ust_i; - delete [] Vst_i; - delete [] Ust_j; - delete [] Vst_j; - delete [] Velst_i; - delete [] Velst_j; - - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - delete [] P_Tensor[iVar]; - delete [] invP_Tensor[iVar]; - } - delete [] P_Tensor; - delete [] invP_Tensor; - -} - -void CUpwMSW_Flow::ComputeResidual(su2double *val_residual, - su2double **val_Jacobian_i, - su2double **val_Jacobian_j, CConfig *config) { - - unsigned short iDim, iVar, jVar, kVar; - su2double P_i, P_j; - su2double ProjVel_i, ProjVel_j, ProjVelst_i, ProjVelst_j; - su2double sqvel_i, sqvel_j; - su2double alpha, w, dp, onemw; - su2double Proj_ModJac_Tensor_i, Proj_ModJac_Tensor_j; - - /*--- Set parameters in the numerical method ---*/ - alpha = 6.0; - - /*--- Calculate supporting geometry parameters ---*/ - - Area = 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; - - /*--- Initialize flux & Jacobian vectors ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Fc_i[iVar] = 0.0; - Fc_j[iVar] = 0.0; - } - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_i[iVar][jVar] = 0.0; - val_Jacobian_j[iVar][jVar] = 0.0; - } - } - } - - /*--- Load variables from nodes i & j ---*/ - - rhos_i = V_i[0]; - rhos_j = V_j[0]; - for (iDim = 0; iDim < nDim; iDim++) { - u_i[iDim] = V_i[iDim+1]; - u_j[iDim] = V_j[iDim+1]; - } - P_i = V_i[nDim+1]; - P_j = V_j[nDim+1]; - - /*--- Calculate supporting quantities ---*/ - - sqvel_i = 0.0; sqvel_j = 0.0; - ProjVel_i = 0.0; ProjVel_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - sqvel_i += u_i[iDim]*u_i[iDim]; - sqvel_j += u_j[iDim]*u_j[iDim]; - ProjVel_i += u_i[iDim]*UnitNormal[iDim]; - ProjVel_j += u_j[iDim]*UnitNormal[iDim]; - } - - /*--- Calculate the state weighting function ---*/ - - dp = fabs(P_j-P_i) / min(P_j, P_i); - w = 0.5 * (1.0/(pow(alpha*dp,2.0) +1.0)); - onemw = 1.0 - w; - - /*--- Calculate weighted state vector (*) for i & j ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Ust_i[iVar] = onemw*U_i[iVar] + w*U_j[iVar]; - Ust_j[iVar] = onemw*U_j[iVar] + w*U_i[iVar]; - } - for (iVar = 0; iVar < nDim+5; iVar++) { - Vst_i[iVar] = onemw*V_i[iVar] + w*V_j[iVar]; - Vst_j[iVar] = onemw*V_j[iVar] + w*V_i[iVar]; - } - ProjVelst_i = onemw*ProjVel_i + w*ProjVel_j; - ProjVelst_j = onemw*ProjVel_j + w*ProjVel_i; - - for (iDim = 0; iDim < nDim; iDim++) { - Velst_i[iDim] = Vst_i[iDim+1]; - Velst_j[iDim] = Vst_j[iDim+1]; - } - - /*--- Flow eigenvalues at i (Lambda+) ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - Lambda_i[iDim] = 0.5*(ProjVelst_i + fabs(ProjVelst_i)); - } - - Lambda_i[nDim] = 0.5*( ProjVelst_i + Vst_i[nDim+4] + fabs(ProjVelst_i + Vst_i[nDim+4]) ); - Lambda_i[nDim+1] = 0.5*( ProjVelst_i - Vst_i[nDim+4] + fabs(ProjVelst_i - Vst_i[nDim+4]) ); - - /*--- Compute projected P, invP, and Lambda ---*/ - - GetPMatrix(&Vst_i[nDim+2], Velst_i, &Vst_i[nDim+4], UnitNormal, P_Tensor); - GetPMatrix_inv(&Vst_i[nDim+2], Velst_i, &Vst_i[nDim+4], UnitNormal, invP_Tensor); - - /*--- Projected flux (f+) at i ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - Proj_ModJac_Tensor_i = 0.0; - - /*--- Compute Proj_ModJac_Tensor = P x Lambda+ x inverse P ---*/ - - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_i += P_Tensor[iVar][kVar]*Lambda_i[kVar]*invP_Tensor[kVar][jVar]; - Fc_i[iVar] += Proj_ModJac_Tensor_i*U_i[jVar]*Area; - if (implicit) - val_Jacobian_i[iVar][jVar] += Proj_ModJac_Tensor_i*Area; - } - } - - /*--- Flow eigenvalues at j (Lambda-) ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - Lambda_j[iDim] = 0.5*(ProjVelst_j - fabs(ProjVelst_j)); - } - Lambda_j[nDim] = 0.5*( ProjVelst_j + Vst_j[nDim+4] - - fabs(ProjVelst_j + Vst_j[nDim+4]) ); - Lambda_j[nDim+1] = 0.5*( ProjVelst_j - Vst_j[nDim+4] - - fabs(ProjVelst_j - Vst_j[nDim+4]) ); - - /*--- Compute projected P, invP, and Lambda ---*/ - - GetPMatrix(&Vst_j[nDim+2], Velst_j, &Vst_j[nDim+4], UnitNormal, P_Tensor); - GetPMatrix_inv(&Vst_j[nDim+2], Velst_j, &Vst_j[nDim+4], UnitNormal, invP_Tensor); - - /*--- Projected flux (f-) ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - Proj_ModJac_Tensor_j = 0.0; - /*--- Compute Proj_ModJac_Tensor = P x Lambda- x inverse P ---*/ - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_j += P_Tensor[iVar][kVar]*Lambda_j[kVar]*invP_Tensor[kVar][jVar]; - Fc_j[iVar] += Proj_ModJac_Tensor_j*U_j[jVar]*Area; - if (implicit) - val_Jacobian_j[iVar][jVar] += Proj_ModJac_Tensor_j*Area; - } - } - - /*--- Flux splitting ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = Fc_i[iVar]+Fc_j[iVar]; - } - -} - -CUpwTurkel_Flow::CUpwTurkel_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - /* 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(); - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Beta_min = config->GetminTurkelBeta(); - Beta_max = config->GetmaxTurkelBeta(); - - Diff_U = new su2double [nVar]; - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - RoeVelocity = new su2double [nDim]; - ProjFlux_i = new su2double [nVar]; - ProjFlux_j = new su2double [nVar]; - Lambda = new su2double [nVar]; - Epsilon = new su2double [nVar]; - absPeJac = new su2double* [nVar]; - invRinvPe = new su2double* [nVar]; - R_Tensor = new su2double* [nVar]; - Matrix = new su2double* [nVar]; - Art_Visc = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - absPeJac[iVar] = new su2double [nVar]; - invRinvPe[iVar] = new su2double [nVar]; - Matrix[iVar] = new su2double [nVar]; - Art_Visc[iVar] = new su2double [nVar]; - R_Tensor[iVar] = new su2double [nVar]; - } -} - -CUpwTurkel_Flow::~CUpwTurkel_Flow(void) { - - delete [] Diff_U; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] RoeVelocity; - delete [] ProjFlux_i; - delete [] ProjFlux_j; - delete [] Lambda; - delete [] Epsilon; - for (iVar = 0; iVar < nVar; iVar++) { - delete [] absPeJac[iVar]; - delete [] invRinvPe[iVar]; - delete [] Matrix[iVar]; - delete [] Art_Visc[iVar]; - delete [] R_Tensor[iVar]; - } - delete [] Matrix; - delete [] Art_Visc; - delete [] absPeJac; - delete [] invRinvPe; - delete [] R_Tensor; - -} - -void CUpwTurkel_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - su2double U_i[5] = {0.0,0.0,0.0,0.0,0.0}, U_j[5] = {0.0,0.0,0.0,0.0,0.0}; - - /*--- Face area (norm or the normal vector) ---*/ - - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim]*Normal[iDim]; - Area = sqrt(Area); - - /*-- Unit Normal ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = Normal[iDim]/Area; - - /*--- Primitive variables at point i ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - Velocity_i[iDim] = V_i[iDim+1]; - Pressure_i = V_i[nDim+1]; - Density_i = V_i[nDim+2]; - Enthalpy_i = V_i[nDim+3]; - Energy_i = Enthalpy_i - Pressure_i/Density_i; - SoundSpeed_i = sqrt(fabs(Pressure_i*Gamma/Density_i)); - - /*--- Primitive variables at point j ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - Velocity_j[iDim] = V_j[iDim+1]; - Pressure_j = V_j[nDim+1]; - Density_j = V_j[nDim+2]; - Enthalpy_j = V_j[nDim+3]; - Energy_j = Enthalpy_j - Pressure_j/Density_j; - SoundSpeed_j = sqrt(fabs(Pressure_j*Gamma/Density_j)); - - /*--- Recompute conservative variables ---*/ - - U_i[0] = Density_i; U_j[0] = Density_j; - for (iDim = 0; iDim < nDim; iDim++) { - U_i[iDim+1] = Density_i*Velocity_i[iDim]; U_j[iDim+1] = Density_j*Velocity_j[iDim]; - } - U_i[nDim+1] = Density_i*Energy_i; U_j[nDim+1] = Density_j*Energy_j; - - /*--- Roe-averaged variables at interface between i & j ---*/ - - R = sqrt(fabs(Density_j/Density_i)); - RoeDensity = R*Density_i; - sq_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); - sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; - } - RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); - RoeSoundSpeed = sqrt(fabs((Gamma-1)*(RoeEnthalpy-0.5*sq_vel))); - RoePressure = RoeDensity/Gamma*RoeSoundSpeed*RoeSoundSpeed; - - /*--- Compute ProjFlux_i ---*/ - GetInviscidProjFlux(&Density_i, Velocity_i, &Pressure_i, &Enthalpy_i, Normal, ProjFlux_i); - - /*--- Compute ProjFlux_j ---*/ - GetInviscidProjFlux(&Density_j, Velocity_j, &Pressure_j, &Enthalpy_j, Normal, ProjFlux_j); - - ProjVelocity = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; - ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; - } - - /*--- Projected velocity adjustment due to mesh motion ---*/ - if (dynamic_grid) { - su2double ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*UnitNormal[iDim]; - } - ProjVelocity -= ProjGridVel; - ProjVelocity_i -= ProjGridVel; - ProjVelocity_j -= ProjGridVel; - } - - /*--- First few flow eigenvalues of A.Normal with the normal---*/ - for (iDim = 0; iDim < nDim; iDim++) - Lambda[iDim] = ProjVelocity; - - local_Mach = sqrt(sq_vel)/RoeSoundSpeed; - Beta = max(Beta_min, min(local_Mach, Beta_max)); - Beta2 = Beta*Beta; - - one_m_Betasqr = 1.0 - Beta2; // 1-Beta*Beta - one_p_Betasqr = 1.0 + Beta2; // 1+Beta*Beta - sqr_one_m_Betasqr_Lam1 = pow((one_m_Betasqr*Lambda[0]),2); // [(1-Beta^2)*Lambda[0]]^2 - sqr_two_Beta_c_Area = pow(2.0*Beta*RoeSoundSpeed*Area,2); // [2*Beta*c*Area]^2 - - /*--- The rest of the flow eigenvalues of preconditioned matrix---*/ - Lambda[nVar-2] = 0.5 * ( one_p_Betasqr*Lambda[0] + sqrt( sqr_one_m_Betasqr_Lam1 + sqr_two_Beta_c_Area)); - Lambda[nVar-1] = 0.5 * ( one_p_Betasqr*Lambda[0] - sqrt( sqr_one_m_Betasqr_Lam1 + sqr_two_Beta_c_Area)); - - s_hat = 1.0/Area * (Lambda[nVar-1] - Lambda[0]*Beta2); - r_hat = 1.0/Area * (Lambda[nVar-2] - Lambda[0]*Beta2); - t_hat = 0.5/Area * (Lambda[nVar-1] - Lambda[nVar-2]); - rhoB2a2 = RoeDensity*Beta2*RoeSoundSpeed*RoeSoundSpeed; - - /*--- Diference variables iPoint and jPoint and absolute value of the eigen values---*/ - for (iVar = 0; iVar < nVar; iVar++) { - Diff_U[iVar] = U_j[iVar]-U_i[iVar]; - Lambda[iVar] = fabs(Lambda[iVar]); - } - - /*--- Compute the absolute Preconditioned Jacobian in entropic Variables (do it with the Unitary Normal) ---*/ - GetPrecondJacobian(Beta2, r_hat, s_hat, t_hat, rhoB2a2, Lambda, UnitNormal, absPeJac); - - /*--- Compute the matrix from entropic variables to conserved variables ---*/ - GetinvRinvPe(Beta2, RoeEnthalpy, RoeSoundSpeed, RoeDensity, RoeVelocity, invRinvPe); - - /*--- Compute the matrix from entropic variables to conserved variables ---*/ - GetRMatrix(RoePressure, RoeSoundSpeed, RoeDensity, RoeVelocity, R_Tensor); - - if (implicit) { - /*--- Jacobians of the inviscid flux, scaled by - 0.5 because val_residual ~ 0.5*(fc_i+fc_j)*Normal ---*/ - GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5, val_Jacobian_i); - GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5, val_Jacobian_j); - } - - for (iVar = 0; iVar < nVar; iVar ++) { - for (jVar = 0; jVar < nVar; jVar ++) { - Matrix[iVar][jVar] = 0.0; - for (kVar = 0; kVar < nVar; kVar++) - Matrix[iVar][jVar] += absPeJac[iVar][kVar]*R_Tensor[kVar][jVar]; - } - } - - for (iVar = 0; iVar < nVar; iVar ++) { - for (jVar = 0; jVar < nVar; jVar ++) { - Art_Visc[iVar][jVar] = 0.0; - for (kVar = 0; kVar < nVar; kVar++) - Art_Visc[iVar][jVar] += invRinvPe[iVar][kVar]*Matrix[kVar][jVar]; - } - } - - /*--- Roe's Flux approximation ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = 0.5*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); - for (jVar = 0; jVar < nVar; jVar++) { - val_residual[iVar] -= 0.5*Art_Visc[iVar][jVar]*Diff_U[jVar]; - if (implicit) { - val_Jacobian_i[iVar][jVar] += 0.5*Art_Visc[iVar][jVar]; - val_Jacobian_j[iVar][jVar] -= 0.5*Art_Visc[iVar][jVar]; - } - } - } - - /*--- Contributions due to mesh motion---*/ - if (dynamic_grid) { - ProjVelocity = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*UnitNormal[iDim]; - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); - /*--- Implicit terms ---*/ - if (implicit) { - val_Jacobian_i[iVar][iVar] -= 0.5*ProjVelocity; - val_Jacobian_j[iVar][iVar] -= 0.5*ProjVelocity; - } - } - } - -} - -CAvgGrad_Base::CAvgGrad_Base(unsigned short val_nDim, - unsigned short val_nVar, - unsigned short val_nPrimVar, - bool val_correct_grad, - CConfig *config) - : CNumerics(val_nDim, val_nVar, config), - nPrimVar(val_nPrimVar), - correct_gradient(val_correct_grad) { - - unsigned short iVar, iDim; - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - TauWall_i = 0; TauWall_j = 0; - - PrimVar_i = new su2double [nPrimVar]; - PrimVar_j = new su2double [nPrimVar]; - Mean_PrimVar = new su2double [nPrimVar]; - - Mean_GradPrimVar = new su2double* [nPrimVar]; - for (iVar = 0; iVar < nPrimVar; iVar++) - Mean_GradPrimVar[iVar] = new su2double [nDim]; - - Edge_Vector = new su2double[nDim]; - - if (correct_gradient) { - Proj_Mean_GradPrimVar_Edge = new su2double[val_nPrimVar]; - } else { - Proj_Mean_GradPrimVar_Edge = NULL; - } - - tau_jacobian_i = new su2double* [nDim]; - for (iDim = 0; iDim < nDim; iDim++) { - tau_jacobian_i[iDim] = new su2double [nVar]; - } - heat_flux_vector = new su2double[nDim]; - heat_flux_jac_i = new su2double[nVar]; - -} - -CAvgGrad_Base::~CAvgGrad_Base() { - - delete [] PrimVar_i; - delete [] PrimVar_j; - delete [] Mean_PrimVar; - for (unsigned short iVar = 0; iVar < nPrimVar; iVar++) - delete [] Mean_GradPrimVar[iVar]; - delete [] Mean_GradPrimVar; - - if (tau_jacobian_i != NULL) { - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - delete [] tau_jacobian_i[iDim]; - } - delete [] tau_jacobian_i; - } - if (heat_flux_vector != NULL) { - delete [] heat_flux_vector; - } - if (heat_flux_jac_i != NULL) { - delete [] heat_flux_jac_i; - } - - delete [] Edge_Vector; - if (Proj_Mean_GradPrimVar_Edge != NULL) - delete [] Proj_Mean_GradPrimVar_Edge; -} - -void CAvgGrad_Base::CorrectGradient(su2double** GradPrimVar, - const su2double* val_PrimVar_i, - const su2double* val_PrimVar_j, - const su2double* val_edge_vector, - const su2double val_dist_ij_2, - const unsigned short val_nPrimVar) { - for (unsigned short iVar = 0; iVar < val_nPrimVar; iVar++) { - Proj_Mean_GradPrimVar_Edge[iVar] = 0.0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - Proj_Mean_GradPrimVar_Edge[iVar] += GradPrimVar[iVar][iDim]*val_edge_vector[iDim]; - } - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - GradPrimVar[iVar][iDim] -= (Proj_Mean_GradPrimVar_Edge[iVar] - - (val_PrimVar_j[iVar]-val_PrimVar_i[iVar]))*val_edge_vector[iDim] / val_dist_ij_2; - } - } -} - -void CAvgGrad_Base::SetStressTensor(const su2double *val_primvar, - const su2double* const *val_gradprimvar, - const su2double val_turb_ke, - const su2double val_laminar_viscosity, - const su2double val_eddy_viscosity) { - - unsigned short iDim, jDim; - const su2double Density = val_primvar[nDim+2]; - const su2double total_viscosity = val_laminar_viscosity + val_eddy_viscosity; - - su2double div_vel = 0.0; - for (iDim = 0 ; iDim < nDim; iDim++) - div_vel += val_gradprimvar[iDim+1][iDim]; - - /* --- If UQ methodology is used, calculate tau using the perturbed reynolds stress tensor --- */ - - if (using_uq){ - for (iDim = 0 ; iDim < nDim; iDim++) - for (jDim = 0 ; jDim < nDim; jDim++) - tau[iDim][jDim] = val_laminar_viscosity*( val_gradprimvar[jDim+1][iDim] + val_gradprimvar[iDim+1][jDim] ) - - TWO3*val_laminar_viscosity*div_vel*delta[iDim][jDim] - Density * MeanPerturbedRSM[iDim][jDim]; - - } else { - - for (iDim = 0 ; iDim < nDim; iDim++) - for (jDim = 0 ; jDim < nDim; jDim++) - tau[iDim][jDim] = total_viscosity*( val_gradprimvar[jDim+1][iDim] + val_gradprimvar[iDim+1][jDim] ) - - TWO3*total_viscosity*div_vel*delta[iDim][jDim]; - } -} - -void CAvgGrad_Base::AddQCR(const su2double* const *val_gradprimvar) { - - su2double den_aux, c_cr1= 0.3, O_ik, O_jk; - unsigned short iDim, jDim, kDim; - - /*--- Denominator Antisymmetric normalized rotation tensor ---*/ - - den_aux = 0.0; - for (iDim = 0 ; iDim < nDim; iDim++) - for (jDim = 0 ; jDim < nDim; jDim++) - den_aux += val_gradprimvar[iDim+1][jDim] * val_gradprimvar[iDim+1][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 = (val_gradprimvar[iDim+1][kDim] - val_gradprimvar[kDim+1][iDim])/ den_aux; - O_jk = (val_gradprimvar[jDim+1][kDim] - val_gradprimvar[kDim+1][jDim])/ den_aux; - tau[iDim][jDim] -= c_cr1 * ((O_ik * tau[jDim][kDim]) + (O_jk * tau[iDim][kDim])); - } - } - } -} - -void CAvgGrad_Base::AddTauWall(const su2double *val_normal, - const su2double val_tau_wall) { - - unsigned short iDim, jDim; - su2double TauNormal, TauElem[3], TauTangent[3], WallShearStress, Area, UnitNormal[3]; - - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += val_normal[iDim]*val_normal[iDim]; - Area = sqrt(Area); - - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = val_normal[iDim]/Area; - - /*--- First, compute wall shear stress as the magnitude of the wall-tangential - component of the shear stress tensor---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - TauElem[iDim] = 0.0; - for (jDim = 0; jDim < nDim; jDim++) - TauElem[iDim] += tau[iDim][jDim]*UnitNormal[jDim]; - } - - TauNormal = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - TauNormal += TauElem[iDim] * UnitNormal[iDim]; - - for (iDim = 0; iDim < nDim; iDim++) - TauTangent[iDim] = TauElem[iDim] - TauNormal * UnitNormal[iDim]; - - WallShearStress = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - WallShearStress += TauTangent[iDim]*TauTangent[iDim]; - WallShearStress = sqrt(WallShearStress); - - /*--- Scale the stress tensor by the ratio of the wall shear stress - to the computed representation of the shear stress ---*/ - - for (iDim = 0 ; iDim < nDim; iDim++) - for (jDim = 0 ; jDim < nDim; jDim++) - tau[iDim][jDim] = tau[iDim][jDim]*(val_tau_wall/WallShearStress); -} - -void CAvgGrad_Base::GetMeanRateOfStrainMatrix(su2double **S_ij) const -{ - /* --- Calculate the rate of strain tensor, using mean velocity gradients --- */ - - if (nDim == 3){ - S_ij[0][0] = Mean_GradPrimVar[1][0]; - S_ij[1][1] = Mean_GradPrimVar[2][1]; - S_ij[2][2] = Mean_GradPrimVar[3][2]; - S_ij[0][1] = 0.5 * (Mean_GradPrimVar[1][1] + Mean_GradPrimVar[2][0]); - S_ij[0][2] = 0.5 * (Mean_GradPrimVar[1][2] + Mean_GradPrimVar[3][0]); - S_ij[1][2] = 0.5 * (Mean_GradPrimVar[2][2] + Mean_GradPrimVar[3][1]); - S_ij[1][0] = S_ij[0][1]; - S_ij[2][1] = S_ij[1][2]; - S_ij[2][0] = S_ij[0][2]; - } - else { - S_ij[0][0] = Mean_GradPrimVar[1][0]; - S_ij[1][1] = Mean_GradPrimVar[2][1]; - S_ij[2][2] = 0.0; - S_ij[0][1] = 0.5 * (Mean_GradPrimVar[1][1] + Mean_GradPrimVar[2][0]); - S_ij[0][2] = 0.0; - S_ij[1][2] = 0.0; - S_ij[1][0] = S_ij[0][1]; - S_ij[2][1] = S_ij[1][2]; - S_ij[2][0] = S_ij[0][2]; - - } -} - -void CAvgGrad_Base::SetReynoldsStressMatrix(su2double turb_ke){ - unsigned short iDim, jDim; - su2double **S_ij = new su2double* [3]; - su2double muT = Mean_Eddy_Viscosity; - su2double divVel = 0; - su2double density; - su2double TWO3 = 2.0/3.0; - density = Mean_PrimVar[nDim+2]; - - for (iDim = 0; iDim < 3; iDim++){ - S_ij[iDim] = new su2double [3]; - } - - - GetMeanRateOfStrainMatrix(S_ij); - - /* --- Using rate of strain matrix, calculate Reynolds stress tensor --- */ - - for (iDim = 0; iDim < 3; iDim++){ - divVel += S_ij[iDim][iDim]; - } - - for (iDim = 0; iDim < 3; iDim++){ - for (jDim = 0; jDim < 3; jDim++){ - MeanReynoldsStress[iDim][jDim] = TWO3 * turb_ke * delta3[iDim][jDim] - - muT / density * (2 * S_ij[iDim][jDim] - TWO3 * divVel * delta3[iDim][jDim]); - } - } - - for (iDim = 0; iDim < 3; iDim++) - delete [] S_ij[iDim]; - delete [] S_ij; -} - -void CAvgGrad_Base::SetPerturbedRSM(su2double turb_ke, CConfig *config){ - - unsigned short iDim,jDim; - - /* --- Calculate anisotropic part of Reynolds Stress tensor --- */ - - for (iDim = 0; iDim< 3; iDim++){ - for (jDim = 0; jDim < 3; jDim++){ - A_ij[iDim][jDim] = .5 * MeanReynoldsStress[iDim][jDim] / turb_ke - delta3[iDim][jDim] / 3.0; - Eig_Vec[iDim][jDim] = A_ij[iDim][jDim]; - } - } - - /* --- Get ordered eigenvectors and eigenvalues of A_ij --- */ - - EigenDecomposition(A_ij, Eig_Vec, Eig_Val, 3); - - /* compute convex combination coefficients */ - su2double c1c = Eig_Val[2] - Eig_Val[1]; - su2double c2c = 2.0 * (Eig_Val[1] - Eig_Val[0]); - su2double c3c = 3.0 * Eig_Val[0] + 1.0; - - /* define barycentric traingle corner points */ - Corners[0][0] = 1.0; - Corners[0][1] = 0.0; - Corners[1][0] = 0.0; - Corners[1][1] = 0.0; - Corners[2][0] = 0.5; - Corners[2][1] = 0.866025; - - /* define barycentric coordinates */ - Barycentric_Coord[0] = Corners[0][0] * c1c + Corners[1][0] * c2c + Corners[2][0] * c3c; - Barycentric_Coord[1] = Corners[0][1] * c1c + Corners[1][1] * c2c + Corners[2][1] * c3c; - - if (Eig_Val_Comp == 1) { - /* 1C turbulence */ - New_Coord[0] = Corners[0][0]; - New_Coord[1] = Corners[0][1]; - } - else if (Eig_Val_Comp== 2) { - /* 2C turbulence */ - New_Coord[0] = Corners[1][0]; - New_Coord[1] = Corners[1][1]; - } - else if (Eig_Val_Comp == 3) { - /* 3C turbulence */ - New_Coord[0] = Corners[2][0]; - New_Coord[1] = Corners[2][1]; - } - else { - /* 2C turbulence */ - New_Coord[0] = Corners[1][0]; - New_Coord[1] = Corners[1][1]; - } - - /* calculate perturbed barycentric coordinates */ - Barycentric_Coord[0] = Barycentric_Coord[0] + (uq_delta_b) * (New_Coord[0] - Barycentric_Coord[0]); - Barycentric_Coord[1] = Barycentric_Coord[1] + (uq_delta_b) * (New_Coord[1] - Barycentric_Coord[1]); - - /* rebuild c1c,c2c,c3c based on perturbed barycentric coordinates */ - c3c = Barycentric_Coord[1] / Corners[2][1]; - c1c = Barycentric_Coord[0] - Corners[2][0] * c3c; - c2c = 1 - c1c - c3c; - - /* build new anisotropy eigenvalues */ - Eig_Val[0] = (c3c - 1) / 3.0; - Eig_Val[1] = 0.5 *c2c + Eig_Val[0]; - Eig_Val[2] = c1c + Eig_Val[1]; - - /* permute eigenvectors if required */ - if (uq_permute) { - for (iDim=0; iDim<3; iDim++) { - for (jDim=0; jDim<3; jDim++) { - New_Eig_Vec[iDim][jDim] = Eig_Vec[2-iDim][jDim]; - } - } - } - - else { - for (iDim=0; iDim<3; iDim++) { - for (jDim=0; jDim<3; jDim++) { - New_Eig_Vec[iDim][jDim] = Eig_Vec[iDim][jDim]; - } - } - } - - EigenRecomposition(newA_ij, New_Eig_Vec, Eig_Val, 3); - - /* compute perturbed Reynolds stress matrix; use under-relaxation factor (uq_urlx)*/ - for (iDim = 0; iDim< 3; iDim++){ - for (jDim = 0; jDim < 3; jDim++){ - MeanPerturbedRSM[iDim][jDim] = 2.0 * turb_ke * (newA_ij[iDim][jDim] + 1.0/3.0 * delta3[iDim][jDim]); - MeanPerturbedRSM[iDim][jDim] = MeanReynoldsStress[iDim][jDim] + - uq_urlx*(MeanPerturbedRSM[iDim][jDim] - MeanReynoldsStress[iDim][jDim]); - } - } - -} - - -void CAvgGrad_Base::SetTauJacobian(const su2double *val_Mean_PrimVar, - const su2double val_laminar_viscosity, - const su2double val_eddy_viscosity, - const su2double val_dist_ij, - const su2double *val_normal) { - - /*--- QCR and wall functions are **not** accounted for here ---*/ - - const su2double Density = val_Mean_PrimVar[nDim+2]; - const su2double total_viscosity = val_laminar_viscosity + val_eddy_viscosity; - const su2double xi = total_viscosity/(Density*val_dist_ij); - - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - for (unsigned short jDim = 0; jDim < nDim; jDim++) { - // Jacobian w.r.t. momentum - tau_jacobian_i[iDim][jDim+1] = -xi*(delta[iDim][jDim] + val_normal[iDim]*val_normal[jDim]/3.0); - } - // Jacobian w.r.t. density - tau_jacobian_i[iDim][0] = 0; - for (unsigned short jDim = 0; jDim < nDim; jDim++) { - tau_jacobian_i[iDim][0] -= tau_jacobian_i[iDim][jDim+1]*val_Mean_PrimVar[jDim+1]; - } - // Jacobian w.r.t. energy - tau_jacobian_i[iDim][nDim+1] = 0; - } -} - -void CAvgGrad_Base::SetIncTauJacobian(const su2double val_laminar_viscosity, - const su2double val_eddy_viscosity, - const su2double val_dist_ij, - const su2double *val_normal) { - - const su2double total_viscosity = val_laminar_viscosity + val_eddy_viscosity; - const su2double xi = total_viscosity/val_dist_ij; - - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - tau_jacobian_i[iDim][0] = 0; - for (unsigned short jDim = 0; jDim < nDim; jDim++) { - tau_jacobian_i[iDim][jDim+1] = -xi*(delta[iDim][jDim] + val_normal[iDim]*val_normal[jDim]/3.0); - } - tau_jacobian_i[iDim][nDim+1] = 0; - } -} - -void CAvgGrad_Base::GetViscousProjFlux(const su2double *val_primvar, - const su2double *val_normal) { - - /*--- Primitive variables -> [Temp vel_x vel_y vel_z Pressure] ---*/ - - if (nDim == 2) { - Flux_Tensor[0][0] = 0.0; - Flux_Tensor[1][0] = tau[0][0]; - Flux_Tensor[2][0] = tau[0][1]; - Flux_Tensor[3][0] = tau[0][0]*val_primvar[1] + tau[0][1]*val_primvar[2]+ - heat_flux_vector[0]; - Flux_Tensor[0][1] = 0.0; - Flux_Tensor[1][1] = tau[1][0]; - Flux_Tensor[2][1] = tau[1][1]; - Flux_Tensor[3][1] = tau[1][0]*val_primvar[1] + tau[1][1]*val_primvar[2]+ - heat_flux_vector[1]; - } else { - Flux_Tensor[0][0] = 0.0; - Flux_Tensor[1][0] = tau[0][0]; - Flux_Tensor[2][0] = tau[0][1]; - Flux_Tensor[3][0] = tau[0][2]; - Flux_Tensor[4][0] = tau[0][0]*val_primvar[1] + tau[0][1]*val_primvar[2] + tau[0][2]*val_primvar[3] + - heat_flux_vector[0]; - Flux_Tensor[0][1] = 0.0; - Flux_Tensor[1][1] = tau[1][0]; - Flux_Tensor[2][1] = tau[1][1]; - Flux_Tensor[3][1] = tau[1][2]; - Flux_Tensor[4][1] = tau[1][0]*val_primvar[1] + tau[1][1]*val_primvar[2] + tau[1][2]*val_primvar[3] + - heat_flux_vector[1]; - Flux_Tensor[0][2] = 0.0; - Flux_Tensor[1][2] = tau[2][0]; - Flux_Tensor[2][2] = tau[2][1]; - Flux_Tensor[3][2] = tau[2][2]; - Flux_Tensor[4][2] = tau[2][0]*val_primvar[1] + tau[2][1]*val_primvar[2] + tau[2][2]*val_primvar[3] + - heat_flux_vector[2]; - } - - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - Proj_Flux_Tensor[iVar] = 0.0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Proj_Flux_Tensor[iVar] += Flux_Tensor[iVar][iDim] * val_normal[iDim]; - } - -} - -void CAvgGrad_Base::GetViscousProjJacs(const su2double *val_Mean_PrimVar, - const su2double val_dS, - const su2double *val_Proj_Visc_Flux, - su2double **val_Proj_Jac_Tensor_i, - su2double **val_Proj_Jac_Tensor_j) { - - const su2double Density = val_Mean_PrimVar[nDim+2]; - const su2double factor = 0.5/Density; - - if (nDim == 2) { - - val_Proj_Jac_Tensor_i[0][0] = 0.0; - val_Proj_Jac_Tensor_i[0][1] = 0.0; - val_Proj_Jac_Tensor_i[0][2] = 0.0; - val_Proj_Jac_Tensor_i[0][3] = 0.0; - val_Proj_Jac_Tensor_i[1][0] = val_dS*tau_jacobian_i[0][0]; - val_Proj_Jac_Tensor_i[1][1] = val_dS*tau_jacobian_i[0][1]; - val_Proj_Jac_Tensor_i[1][2] = val_dS*tau_jacobian_i[0][2]; - val_Proj_Jac_Tensor_i[1][3] = val_dS*tau_jacobian_i[0][3]; - val_Proj_Jac_Tensor_i[2][0] = val_dS*tau_jacobian_i[1][0]; - val_Proj_Jac_Tensor_i[2][1] = val_dS*tau_jacobian_i[1][1]; - val_Proj_Jac_Tensor_i[2][2] = val_dS*tau_jacobian_i[1][2]; - val_Proj_Jac_Tensor_i[2][3] = val_dS*tau_jacobian_i[1][3]; - const su2double contraction = tau_jacobian_i[0][0]*val_Mean_PrimVar[1] + - tau_jacobian_i[1][0]*val_Mean_PrimVar[2]; - val_Proj_Jac_Tensor_i[3][0] = val_dS*(contraction - heat_flux_jac_i[0]); - val_Proj_Jac_Tensor_i[3][1] = -val_dS*(tau_jacobian_i[0][0] + heat_flux_jac_i[1]); - val_Proj_Jac_Tensor_i[3][2] = -val_dS*(tau_jacobian_i[1][0] + heat_flux_jac_i[2]); - val_Proj_Jac_Tensor_i[3][3] = -val_dS*heat_flux_jac_i[3]; - - for (unsigned short iVar = 0; iVar < nVar; iVar++) - for (unsigned short jVar = 0; jVar < nVar; jVar++) - val_Proj_Jac_Tensor_j[iVar][jVar] = -val_Proj_Jac_Tensor_i[iVar][jVar]; - - const su2double proj_viscousflux_vel= val_Proj_Visc_Flux[1]*val_Mean_PrimVar[1] + - val_Proj_Visc_Flux[2]*val_Mean_PrimVar[2]; - val_Proj_Jac_Tensor_i[3][0] -= factor*proj_viscousflux_vel; - val_Proj_Jac_Tensor_j[3][0] -= factor*proj_viscousflux_vel; - val_Proj_Jac_Tensor_i[3][1] += factor*val_Proj_Visc_Flux[1]; - val_Proj_Jac_Tensor_j[3][1] += factor*val_Proj_Visc_Flux[1]; - val_Proj_Jac_Tensor_i[3][2] += factor*val_Proj_Visc_Flux[2]; - val_Proj_Jac_Tensor_j[3][2] += factor*val_Proj_Visc_Flux[2]; - - - } else { - - val_Proj_Jac_Tensor_i[0][0] = 0.0; - val_Proj_Jac_Tensor_i[0][1] = 0.0; - val_Proj_Jac_Tensor_i[0][2] = 0.0; - val_Proj_Jac_Tensor_i[0][3] = 0.0; - val_Proj_Jac_Tensor_i[0][4] = 0.0; - val_Proj_Jac_Tensor_i[1][0] = val_dS*tau_jacobian_i[0][0]; - val_Proj_Jac_Tensor_i[1][1] = val_dS*tau_jacobian_i[0][1]; - val_Proj_Jac_Tensor_i[1][2] = val_dS*tau_jacobian_i[0][2]; - val_Proj_Jac_Tensor_i[1][3] = val_dS*tau_jacobian_i[0][3]; - val_Proj_Jac_Tensor_i[1][4] = val_dS*tau_jacobian_i[0][4]; - val_Proj_Jac_Tensor_i[2][0] = val_dS*tau_jacobian_i[1][0]; - val_Proj_Jac_Tensor_i[2][1] = val_dS*tau_jacobian_i[1][1]; - val_Proj_Jac_Tensor_i[2][2] = val_dS*tau_jacobian_i[1][2]; - val_Proj_Jac_Tensor_i[2][3] = val_dS*tau_jacobian_i[1][3]; - val_Proj_Jac_Tensor_i[2][4] = val_dS*tau_jacobian_i[1][4]; - val_Proj_Jac_Tensor_i[3][0] = val_dS*tau_jacobian_i[2][0]; - val_Proj_Jac_Tensor_i[3][1] = val_dS*tau_jacobian_i[2][1]; - val_Proj_Jac_Tensor_i[3][2] = val_dS*tau_jacobian_i[2][2]; - val_Proj_Jac_Tensor_i[3][3] = val_dS*tau_jacobian_i[2][3]; - val_Proj_Jac_Tensor_i[3][4] = val_dS*tau_jacobian_i[2][4]; - const su2double contraction = tau_jacobian_i[0][0]*val_Mean_PrimVar[1] + - tau_jacobian_i[1][0]*val_Mean_PrimVar[2] + - tau_jacobian_i[2][0]*val_Mean_PrimVar[3]; - val_Proj_Jac_Tensor_i[4][0] = val_dS*(contraction - heat_flux_jac_i[0]); - val_Proj_Jac_Tensor_i[4][1] = -val_dS*(tau_jacobian_i[0][0] + heat_flux_jac_i[1]); - val_Proj_Jac_Tensor_i[4][2] = -val_dS*(tau_jacobian_i[1][0] + heat_flux_jac_i[2]); - val_Proj_Jac_Tensor_i[4][3] = -val_dS*(tau_jacobian_i[2][0] + heat_flux_jac_i[3]); - val_Proj_Jac_Tensor_i[4][4] = -val_dS*heat_flux_jac_i[4]; - - for (unsigned short iVar = 0; iVar < nVar; iVar++) - for (unsigned short jVar = 0; jVar < nVar; jVar++) - val_Proj_Jac_Tensor_j[iVar][jVar] = -val_Proj_Jac_Tensor_i[iVar][jVar]; - - const su2double proj_viscousflux_vel= val_Proj_Visc_Flux[1]*val_Mean_PrimVar[1] + - val_Proj_Visc_Flux[2]*val_Mean_PrimVar[2] + - val_Proj_Visc_Flux[3]*val_Mean_PrimVar[3]; - val_Proj_Jac_Tensor_i[4][0] -= factor*proj_viscousflux_vel; - val_Proj_Jac_Tensor_j[4][0] -= factor*proj_viscousflux_vel; - val_Proj_Jac_Tensor_i[4][1] += factor*val_Proj_Visc_Flux[1]; - val_Proj_Jac_Tensor_j[4][1] += factor*val_Proj_Visc_Flux[1]; - val_Proj_Jac_Tensor_i[4][2] += factor*val_Proj_Visc_Flux[2]; - val_Proj_Jac_Tensor_j[4][2] += factor*val_Proj_Visc_Flux[2]; - val_Proj_Jac_Tensor_i[4][3] += factor*val_Proj_Visc_Flux[3]; - val_Proj_Jac_Tensor_j[4][3] += factor*val_Proj_Visc_Flux[3]; - - } - -} - -CAvgGrad_Flow::CAvgGrad_Flow(unsigned short val_nDim, - unsigned short val_nVar, - bool val_correct_grad, - CConfig *config) - : CAvgGrad_Base(val_nDim, val_nVar, val_nDim+3, val_correct_grad, config) { - -} - -CAvgGrad_Flow::~CAvgGrad_Flow(void) { - -} - -void CAvgGrad_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - AD::StartPreacc(); - AD::SetPreaccIn(V_i, nDim+9); AD::SetPreaccIn(V_j, nDim+9); - AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); - AD::SetPreaccIn(PrimVar_Grad_i, nDim+1, nDim); - AD::SetPreaccIn(PrimVar_Grad_j, nDim+1, nDim); - AD::SetPreaccIn(turb_ke_i); AD::SetPreaccIn(turb_ke_j); - AD::SetPreaccIn(Normal, nDim); - - unsigned short iVar, jVar, iDim; - - /*--- Normalized normal vector ---*/ - - 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; - - for (iVar = 0; iVar < nPrimVar; iVar++) { - PrimVar_i[iVar] = V_i[iVar]; - PrimVar_j[iVar] = V_j[iVar]; - Mean_PrimVar[iVar] = 0.5*(PrimVar_i[iVar]+PrimVar_j[iVar]); - } - - - /*--- Compute vector going from iPoint to jPoint ---*/ - - dist_ij_2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; - dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; - } - - /*--- Laminar and Eddy viscosity ---*/ - - Laminar_Viscosity_i = V_i[nDim+5]; Laminar_Viscosity_j = V_j[nDim+5]; - Eddy_Viscosity_i = V_i[nDim+6]; Eddy_Viscosity_j = V_j[nDim+6]; - - /*--- Mean Viscosities and turbulent kinetic energy---*/ - - Mean_Laminar_Viscosity = 0.5*(Laminar_Viscosity_i + Laminar_Viscosity_j); - Mean_Eddy_Viscosity = 0.5*(Eddy_Viscosity_i + Eddy_Viscosity_j); - Mean_turb_ke = 0.5*(turb_ke_i + turb_ke_j); - - /*--- Mean gradient approximation ---*/ - - for (iVar = 0; iVar < nDim+1; iVar++) { - for (iDim = 0; iDim < nDim; iDim++) { - Mean_GradPrimVar[iVar][iDim] = 0.5*(PrimVar_Grad_i[iVar][iDim] + PrimVar_Grad_j[iVar][iDim]); - } - } - - /*--- Projection of the mean gradient in the direction of the edge ---*/ - - if (correct_gradient && dist_ij_2 != 0.0) { - CorrectGradient(Mean_GradPrimVar, PrimVar_i, PrimVar_j, Edge_Vector, - dist_ij_2, nDim+1); - } - - /*--- Wall shear stress values (wall functions) ---*/ - - if (TauWall_i > 0.0 && TauWall_j > 0.0) Mean_TauWall = 0.5*(TauWall_i + TauWall_j); - else if (TauWall_i > 0.0) Mean_TauWall = TauWall_i; - else if (TauWall_j > 0.0) Mean_TauWall = TauWall_j; - else Mean_TauWall = -1.0; - - /* --- If using UQ methodology, set Reynolds Stress tensor and perform perturbation--- */ - - if (using_uq){ - SetReynoldsStressMatrix(Mean_turb_ke); - SetPerturbedRSM(Mean_turb_ke, config); - } - - /*--- Get projected flux tensor ---*/ - - SetStressTensor(Mean_PrimVar, Mean_GradPrimVar, Mean_turb_ke, - Mean_Laminar_Viscosity, Mean_Eddy_Viscosity); - if (config->GetQCR()) AddQCR(Mean_GradPrimVar); - if (Mean_TauWall > 0) AddTauWall(Normal, Mean_TauWall); - - SetHeatFluxVector(Mean_GradPrimVar, Mean_Laminar_Viscosity, - Mean_Eddy_Viscosity); - - GetViscousProjFlux(Mean_PrimVar, Normal); - - /*--- Update viscous residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] = Proj_Flux_Tensor[iVar]; - - /*--- Compute the implicit part ---*/ - - if (implicit) { - - if (dist_ij_2 == 0.0) { - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_i[iVar][jVar] = 0.0; - val_Jacobian_j[iVar][jVar] = 0.0; - } - } - } else { - const su2double dist_ij = sqrt(dist_ij_2); - SetTauJacobian(Mean_PrimVar, Mean_Laminar_Viscosity, Mean_Eddy_Viscosity, - dist_ij, UnitNormal); - SetHeatFluxJacobian(Mean_PrimVar, Mean_Laminar_Viscosity, - Mean_Eddy_Viscosity, dist_ij, UnitNormal); - GetViscousProjJacs(Mean_PrimVar, Area, Proj_Flux_Tensor, - val_Jacobian_i, val_Jacobian_j); - } - - } - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - -} - - - -void CAvgGrad_Flow::SetHeatFluxVector(const su2double* const *val_gradprimvar, - const su2double val_laminar_viscosity, - const su2double val_eddy_viscosity) { - - const su2double Cp = (Gamma / Gamma_Minus_One) * Gas_Constant; - const su2double heat_flux_factor = Cp * (val_laminar_viscosity/Prandtl_Lam + val_eddy_viscosity/Prandtl_Turb); - - /*--- Gradient of primitive variables -> [Temp vel_x vel_y vel_z Pressure] ---*/ - - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - heat_flux_vector[iDim] = heat_flux_factor*val_gradprimvar[0][iDim]; - } -} - -void CAvgGrad_Flow::SetHeatFluxJacobian(const su2double *val_Mean_PrimVar, - const su2double val_laminar_viscosity, - const su2double val_eddy_viscosity, - const su2double val_dist_ij, - const su2double *val_normal) { - su2double sqvel = 0.0; - - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - sqvel += val_Mean_PrimVar[iDim+1]*val_Mean_PrimVar[iDim+1]; - } - - const su2double Density = val_Mean_PrimVar[nDim+2]; - const su2double Pressure = val_Mean_PrimVar[nDim+1]; - const su2double phi = Gamma_Minus_One/Density; - - /*--- R times partial derivatives of temp. ---*/ - - const su2double R_dTdu0 = -Pressure/(Density*Density) + 0.5*sqvel*phi; - const su2double R_dTdu1 = -phi*val_Mean_PrimVar[1]; - const su2double R_dTdu2 = -phi*val_Mean_PrimVar[2]; - - const su2double heat_flux_factor = val_laminar_viscosity/Prandtl_Lam + val_eddy_viscosity/Prandtl_Turb; - const su2double cpoR = Gamma/Gamma_Minus_One; // cp over R - const su2double conductivity_over_Rd = cpoR*heat_flux_factor/val_dist_ij; - - heat_flux_jac_i[0] = conductivity_over_Rd * R_dTdu0; - heat_flux_jac_i[1] = conductivity_over_Rd * R_dTdu1; - heat_flux_jac_i[2] = conductivity_over_Rd * R_dTdu2; - - if (nDim == 2) { - - const su2double R_dTdu3 = phi; - heat_flux_jac_i[3] = conductivity_over_Rd * R_dTdu3; - - } else { - - const su2double R_dTdu3 = -phi*val_Mean_PrimVar[3]; - const su2double R_dTdu4 = phi; - heat_flux_jac_i[3] = conductivity_over_Rd * R_dTdu3; - heat_flux_jac_i[4] = conductivity_over_Rd * R_dTdu4; - - } -} - - -CGeneralAvgGrad_Flow::CGeneralAvgGrad_Flow(unsigned short val_nDim, - unsigned short val_nVar, - bool val_correct_grad, - CConfig *config) - : CAvgGrad_Base(val_nDim, val_nVar, val_nDim+4, val_correct_grad, config) { - - Mean_SecVar = new su2double [2]; - -} - -CGeneralAvgGrad_Flow::~CGeneralAvgGrad_Flow(void) { - - delete [] Mean_SecVar; - -} - -void CGeneralAvgGrad_Flow::SetHeatFluxVector(const su2double* const *val_gradprimvar, - const su2double val_laminar_viscosity, - const su2double val_eddy_viscosity, - const su2double val_thermal_conductivity, - const su2double val_heat_capacity_cp) { - - const su2double heat_flux_factor = val_thermal_conductivity + val_heat_capacity_cp*val_eddy_viscosity/Prandtl_Turb; - - /*--- Gradient of primitive variables -> [Temp vel_x vel_y vel_z Pressure] ---*/ - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - heat_flux_vector[iDim] = heat_flux_factor*val_gradprimvar[0][iDim]; - } -} - -void CGeneralAvgGrad_Flow::SetHeatFluxJacobian(const su2double *val_Mean_PrimVar, - const su2double *val_Mean_SecVar, - const su2double val_eddy_viscosity, - const su2double val_thermal_conductivity, - const su2double val_heat_capacity_cp, - const su2double val_dist_ij) { - /* Viscous flux Jacobians for arbitrary equations of state */ - - //order of val_mean_primitives: T, vx, vy, vz, P, rho, ht - //order of secondary:dTdrho_e, dTde_rho - - su2double sqvel = 0.0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) { - sqvel += val_Mean_PrimVar[iDim+1]*val_Mean_PrimVar[iDim+1]; - } - - su2double rho = val_Mean_PrimVar[nDim+2]; - su2double P= val_Mean_PrimVar[nDim+1]; - su2double h= val_Mean_PrimVar[nDim+3]; - su2double dTdrho_e= val_Mean_SecVar[0]; - su2double dTde_rho= val_Mean_SecVar[1]; - - su2double dTdu0= dTdrho_e + dTde_rho*(-(h-P/rho) + sqvel)*(1/rho); - su2double dTdu1= dTde_rho*(-val_Mean_PrimVar[1])*(1/rho); - su2double dTdu2= dTde_rho*(-val_Mean_PrimVar[2])*(1/rho); - - su2double total_conductivity = val_thermal_conductivity + val_heat_capacity_cp*val_eddy_viscosity/Prandtl_Turb; - su2double factor2 = total_conductivity/val_dist_ij; - - heat_flux_jac_i[0] = factor2*dTdu0; - heat_flux_jac_i[1] = factor2*dTdu1; - heat_flux_jac_i[2] = factor2*dTdu2; - - if (nDim == 2) { - - su2double dTdu3= dTde_rho*(1/rho); - heat_flux_jac_i[3] = factor2*dTdu3; - - } else { - - su2double dTdu3= dTde_rho*(-val_Mean_PrimVar[3])*(1/rho); - su2double dTdu4= dTde_rho*(1/rho); - heat_flux_jac_i[3] = factor2*dTdu3; - heat_flux_jac_i[4] = factor2*dTdu4; - - } - -} - -void CGeneralAvgGrad_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - AD::StartPreacc(); - AD::SetPreaccIn(V_i, nDim+9); AD::SetPreaccIn(V_j, nDim+9); - AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); - AD::SetPreaccIn(S_i, 4); AD::SetPreaccIn(S_j, 4); - AD::SetPreaccIn(PrimVar_Grad_i, nDim+1, nDim); - AD::SetPreaccIn(PrimVar_Grad_j, nDim+1, nDim); - AD::SetPreaccIn(turb_ke_i); AD::SetPreaccIn(turb_ke_j); - AD::SetPreaccIn(Normal, nDim); - - unsigned short iVar, jVar, iDim; - - /*--- Normalized normal vector ---*/ - - 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; - - /*--- Mean primitive variables ---*/ - - for (iVar = 0; iVar < nPrimVar; iVar++) { - PrimVar_i[iVar] = V_i[iVar]; - PrimVar_j[iVar] = V_j[iVar]; - Mean_PrimVar[iVar] = 0.5*(PrimVar_i[iVar]+PrimVar_j[iVar]); - } - - /*--- Compute vector going from iPoint to jPoint ---*/ - - dist_ij_2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; - dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; - } - - /*--- Laminar and Eddy viscosity ---*/ - - Laminar_Viscosity_i = V_i[nDim+5]; Laminar_Viscosity_j = V_j[nDim+5]; - Eddy_Viscosity_i = V_i[nDim+6]; Eddy_Viscosity_j = V_j[nDim+6]; - Thermal_Conductivity_i = V_i[nDim+7]; Thermal_Conductivity_j = V_j[nDim+7]; - Cp_i = V_i[nDim+8]; Cp_j = V_j[nDim+8]; - - /*--- Mean secondary variables ---*/ - - for (iVar = 0; iVar < 2; iVar++) { - Mean_SecVar[iVar] = 0.5*(S_i[iVar+2]+S_j[iVar+2]); - } - - /*--- Mean Viscosities and turbulent kinetic energy---*/ - - Mean_Laminar_Viscosity = 0.5*(Laminar_Viscosity_i + Laminar_Viscosity_j); - Mean_Eddy_Viscosity = 0.5*(Eddy_Viscosity_i + Eddy_Viscosity_j); - Mean_turb_ke = 0.5*(turb_ke_i + turb_ke_j); - Mean_Thermal_Conductivity = 0.5*(Thermal_Conductivity_i + Thermal_Conductivity_j); - Mean_Cp = 0.5*(Cp_i + Cp_j); - - /*--- Mean gradient approximation ---*/ - - for (iVar = 0; iVar < nDim+1; iVar++) { - for (iDim = 0; iDim < nDim; iDim++) { - Mean_GradPrimVar[iVar][iDim] = 0.5*(PrimVar_Grad_i[iVar][iDim] + PrimVar_Grad_j[iVar][iDim]); - } - } - - /*--- Projection of the mean gradient in the direction of the edge ---*/ - - if (correct_gradient && dist_ij_2 != 0.0) { - CorrectGradient(Mean_GradPrimVar, PrimVar_i, PrimVar_j, Edge_Vector, - dist_ij_2, nDim+1); - } - - /* --- If using UQ methodology, set Reynolds Stress tensor and perform perturbation--- */ - - if (using_uq){ - SetReynoldsStressMatrix(Mean_turb_ke); - SetPerturbedRSM(Mean_turb_ke, config); - } - - /*--- Get projected flux tensor ---*/ - - SetStressTensor(Mean_PrimVar, Mean_GradPrimVar, Mean_turb_ke, - Mean_Laminar_Viscosity, Mean_Eddy_Viscosity); - - SetHeatFluxVector(Mean_GradPrimVar, Mean_Laminar_Viscosity, - Mean_Eddy_Viscosity, Mean_Thermal_Conductivity, Mean_Cp); - - GetViscousProjFlux(Mean_PrimVar, Normal); - - /*--- Update viscous residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] = Proj_Flux_Tensor[iVar]; - - /*--- Compute the implicit part ---*/ - - if (implicit) { - - if (dist_ij_2 == 0.0) { - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_i[iVar][jVar] = 0.0; - val_Jacobian_j[iVar][jVar] = 0.0; - } - } - } else { - const su2double dist_ij = sqrt(dist_ij_2); - SetTauJacobian(Mean_PrimVar, Mean_Laminar_Viscosity, Mean_Eddy_Viscosity, - dist_ij, UnitNormal); - SetHeatFluxJacobian(Mean_PrimVar, Mean_SecVar, Mean_Eddy_Viscosity, - Mean_Thermal_Conductivity, Mean_Cp, dist_ij); - GetViscousProjJacs(Mean_PrimVar, Area, Proj_Flux_Tensor, - val_Jacobian_i, val_Jacobian_j); - } - - } - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - -} - -CSourceGravity::CSourceGravity(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - -} - -CSourceGravity::~CSourceGravity(void) { } - -void CSourceGravity::ComputeResidual(su2double *val_residual, CConfig *config) { - unsigned short iVar; - - for (iVar = 0; iVar < nVar; iVar++) - val_residual[iVar] = 0.0; - - /*--- Evaluate the source term ---*/ - val_residual[nDim] = Volume * U_i[0] * STANDARD_GRAVITY; - -} - -CSourceBodyForce::CSourceBodyForce(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - /*--- Store the pointer to the constant body force vector. ---*/ - - Body_Force_Vector = new su2double[nDim]; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Body_Force_Vector[iDim] = config->GetBody_Force_Vector()[iDim]; - -} - -CSourceBodyForce::~CSourceBodyForce(void) { - - if (Body_Force_Vector != NULL) delete [] Body_Force_Vector; - -} - -void CSourceBodyForce::ComputeResidual(su2double *val_residual, CConfig *config) { - - unsigned short iDim; - su2double Force_Ref = config->GetForce_Ref(); - - /*--- Zero the continuity contribution ---*/ - - val_residual[0] = 0.0; - - /*--- Momentum contribution ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = -Volume * U_i[0] * Body_Force_Vector[iDim] / Force_Ref; - - /*--- Energy contribution ---*/ - - val_residual[nDim+1] = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - val_residual[nDim+1] += -Volume * U_i[iDim+1] * Body_Force_Vector[iDim] / Force_Ref; - -} - -CSourceRotatingFrame_Flow::CSourceRotatingFrame_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - -} - -CSourceRotatingFrame_Flow::~CSourceRotatingFrame_Flow(void) { } - -void CSourceRotatingFrame_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) { - - unsigned short iDim, iVar, jVar; - su2double Omega[3] = {0,0,0}, Momentum[3] = {0,0,0}; - - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - /*--- Retrieve the angular velocity vector from config. ---*/ - - for (iDim = 0; iDim < 3; iDim++){ - Omega[iDim] = config->GetRotation_Rate(iDim)/config->GetOmega_Ref(); - } - - /*--- Get the momentum vector at the current node. ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - Momentum[iDim] = U_i[iDim+1]; - - /*--- Calculate rotating frame source term as ( Omega X Rho-U ) ---*/ - - if (nDim == 2) { - val_residual[0] = 0.0; - val_residual[1] = (Omega[1]*Momentum[2] - Omega[2]*Momentum[1])*Volume; - val_residual[2] = (Omega[2]*Momentum[0] - Omega[0]*Momentum[2])*Volume; - val_residual[3] = 0.0; - } else { - val_residual[0] = 0.0; - val_residual[1] = (Omega[1]*Momentum[2] - Omega[2]*Momentum[1])*Volume; - val_residual[2] = (Omega[2]*Momentum[0] - Omega[0]*Momentum[2])*Volume; - val_residual[3] = (Omega[0]*Momentum[1] - Omega[1]*Momentum[0])*Volume; - val_residual[4] = 0.0; - } - - /*--- Calculate the source term Jacobian ---*/ - - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_i[iVar][jVar] = 0.0; - if (nDim == 2) { - val_Jacobian_i[1][2] = -Omega[2]*Volume; - val_Jacobian_i[2][1] = Omega[2]*Volume; - } else { - val_Jacobian_i[1][2] = -Omega[2]*Volume; - val_Jacobian_i[1][3] = Omega[1]*Volume; - val_Jacobian_i[2][1] = Omega[2]*Volume; - val_Jacobian_i[2][3] = -Omega[0]*Volume; - val_Jacobian_i[3][1] = -Omega[1]*Volume; - val_Jacobian_i[3][2] = Omega[0]*Volume; - } - } - -} - -CSourceAxisymmetric_Flow::CSourceAxisymmetric_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - -} - -CSourceAxisymmetric_Flow::~CSourceAxisymmetric_Flow(void) { } - -void CSourceAxisymmetric_Flow::ComputeResidual(su2double *val_residual, su2double **Jacobian_i, CConfig *config) { - - su2double yinv, Pressure_i, Enthalpy_i, Velocity_i, sq_vel; - unsigned short iDim, iVar, jVar; - - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - if (Coord_i[1] > EPS) { - - yinv = 1.0/Coord_i[1]; - - sq_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i = U_i[iDim+1] / U_i[0]; - sq_vel += Velocity_i *Velocity_i; - } - - Pressure_i = (Gamma-1.0)*U_i[0]*(U_i[nDim+1]/U_i[0]-0.5*sq_vel); - Enthalpy_i = (U_i[nDim+1] + Pressure_i) / U_i[0]; - - val_residual[0] = yinv*Volume*U_i[2]; - val_residual[1] = yinv*Volume*U_i[1]*U_i[2]/U_i[0]; - val_residual[2] = yinv*Volume*(U_i[2]*U_i[2]/U_i[0]); - val_residual[3] = yinv*Volume*Enthalpy_i*U_i[2]; - - if (implicit) { - Jacobian_i[0][0] = 0.0; - Jacobian_i[0][1] = 0.0; - Jacobian_i[0][2] = 1.0; - Jacobian_i[0][3] = 0.0; - - Jacobian_i[1][0] = -U_i[1]*U_i[2]/(U_i[0]*U_i[0]); - Jacobian_i[1][1] = U_i[2]/U_i[0]; - Jacobian_i[1][2] = U_i[1]/U_i[0]; - Jacobian_i[1][3] = 0.0; - - Jacobian_i[2][0] = -U_i[2]*U_i[2]/(U_i[0]*U_i[0]); - Jacobian_i[2][1] = 0.0; - Jacobian_i[2][2] = 2*U_i[2]/U_i[0]; - Jacobian_i[2][3] = 0.0; - - Jacobian_i[3][0] = -Gamma*U_i[2]*U_i[3]/(U_i[0]*U_i[0]) + (Gamma-1)*U_i[2]*(U_i[1]*U_i[1]+U_i[2]*U_i[2])/(U_i[0]*U_i[0]*U_i[0]); - Jacobian_i[3][1] = -(Gamma-1)*U_i[2]*U_i[1]/(U_i[0]*U_i[0]); - Jacobian_i[3][2] = Gamma*U_i[3]/U_i[0] - 1/2*(Gamma-1)*( (U_i[1]*U_i[1]+U_i[2]*U_i[2])/(U_i[0]*U_i[0]) + 2*U_i[2]*U_i[2]/(U_i[0]*U_i[0]) ); - Jacobian_i[3][3] = Gamma*U_i[2]/U_i[0]; - - for (iVar=0; iVar < nVar; iVar++) - for (jVar=0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] *= yinv*Volume; - - } - - } - - else { - - for (iVar=0; iVar < nVar; iVar++) - val_residual[iVar] = 0.0; - - if (implicit) { - for (iVar=0; iVar < nVar; iVar++) { - for (jVar=0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] = 0.0; - } - } - - } - -} - -CSourceWindGust::CSourceWindGust(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - -} - -CSourceWindGust::~CSourceWindGust(void) { } - -void CSourceWindGust::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) { - - su2double u_gust, v_gust, du_gust_dx, du_gust_dy, du_gust_dt, dv_gust_dx, dv_gust_dy, dv_gust_dt, smx, smy, se, rho, u, v, p; - unsigned short GustDir = config->GetGust_Dir(); //Gust direction - - u_gust = WindGust_i[0]; - v_gust = WindGust_i[1]; - - if (GustDir == X_DIR) { - du_gust_dx = WindGustDer_i[0]; - du_gust_dy = WindGustDer_i[1]; - du_gust_dt = WindGustDer_i[2]; - dv_gust_dx = 0.0; - dv_gust_dy = 0.0; - dv_gust_dt = 0.0; - } else { - du_gust_dx = 0.0; - du_gust_dy = 0.0; - du_gust_dt = 0.0; - dv_gust_dx = WindGustDer_i[0]; - dv_gust_dy = WindGustDer_i[1]; - dv_gust_dt = WindGustDer_i[2]; - - } - - /*--- Primitive variables at point i ---*/ - u = V_i[1]; - v = V_i[2]; - p = V_i[nDim+1]; - rho = V_i[nDim+2]; - - /*--- Source terms ---*/ - smx = rho*(du_gust_dt + (u+u_gust)*du_gust_dx + (v+v_gust)*du_gust_dy); - smy = rho*(dv_gust_dt + (u+u_gust)*dv_gust_dx + (v+v_gust)*dv_gust_dy); - se = u*smx + v*smy + p*(du_gust_dx + dv_gust_dy); - - if (nDim == 2) { - val_residual[0] = 0.0; - val_residual[1] = smx*Volume; - val_residual[2] = smy*Volume; - val_residual[3] = se*Volume; - } else { - SU2_MPI::Error("You should only be in the gust source term in two dimensions", CURRENT_FUNCTION); - } - - /*--- For now the source term Jacobian is just set to zero ---*/ - - unsigned short iVar, jVar; - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - /*--- Calculate the source term Jacobian ---*/ - - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_i[iVar][jVar] = 0.0; - } - -} diff --git a/SU2_CFD/src/numerics_direct_mean_inc.cpp b/SU2_CFD/src/numerics_direct_mean_inc.cpp deleted file mode 100644 index 6e8a58f985db..000000000000 --- a/SU2_CFD/src/numerics_direct_mean_inc.cpp +++ /dev/null @@ -1,1219 +0,0 @@ -/*! - * \file numerics_direct_mean_inc.cpp - * \brief This file contains the numerical methods for incompressible flow. - * \author F. Palacios, T. Economon - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - - -#include "../include/numerics_structure.hpp" -#include - -CUpwFDSInc_Flow::CUpwFDSInc_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - variable_density = (config->GetKind_DensityModel() == VARIABLE); - energy = config->GetEnergy_Equation(); - /* 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(); - - Diff_V = new su2double[nVar]; - Velocity_i = new su2double[nDim]; - Velocity_j = new su2double[nDim]; - MeanVelocity = new su2double[nDim]; - ProjFlux_i = new su2double[nVar]; - ProjFlux_j = new su2double[nVar]; - Lambda = new su2double[nVar]; - Epsilon = new su2double[nVar]; - Precon = new su2double*[nVar]; - invPrecon_A = new su2double*[nVar]; - - for (iVar = 0; iVar < nVar; iVar++) { - Precon[iVar] = new su2double[nVar]; - invPrecon_A[iVar] = new su2double[nVar]; - } - -} - -CUpwFDSInc_Flow::~CUpwFDSInc_Flow(void) { - - delete [] Diff_V; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] MeanVelocity; - delete [] ProjFlux_i; - delete [] ProjFlux_j; - delete [] Lambda; - delete [] Epsilon; - - for (iVar = 0; iVar < nVar; iVar++) { - delete [] Precon[iVar]; - delete [] invPrecon_A[iVar]; - } - delete [] Precon; - delete [] invPrecon_A; - -} - -void CUpwFDSInc_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - su2double U_i[5] = {0.0,0.0,0.0,0.0,0.0}, U_j[5] = {0.0,0.0,0.0,0.0,0.0}; - su2double ProjGridVel = 0.0; - - AD::StartPreacc(); - AD::SetPreaccIn(V_i, nDim+9); AD::SetPreaccIn(V_j, nDim+9); AD::SetPreaccIn(Normal, nDim); - if (dynamic_grid) { - AD::SetPreaccIn(GridVel_i, nDim); - AD::SetPreaccIn(GridVel_j, nDim); - } - - /*--- Face area (norm or the normal vector) ---*/ - - Area = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Area += Normal[iDim]*Normal[iDim]; - Area = sqrt(Area); - - /*--- Compute and unitary normal vector ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - UnitNormal[iDim] = Normal[iDim]/Area; - if (fabs(UnitNormal[iDim]) < EPS) UnitNormal[iDim] = EPS; - } - - /*--- Set primitive variables at points iPoint and jPoint ---*/ - - Pressure_i = V_i[0]; Pressure_j = V_j[0]; - Temperature_i = V_i[nDim+1]; Temperature_j = V_j[nDim+1]; - DensityInc_i = V_i[nDim+2]; DensityInc_j = V_j[nDim+2]; - BetaInc2_i = V_i[nDim+3]; BetaInc2_j = V_j[nDim+3]; - Cp_i = V_i[nDim+7]; Cp_j = V_j[nDim+7]; - Enthalpy_i = Cp_i*Temperature_i; Enthalpy_j = Cp_j*Temperature_j; - - ProjVelocity = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity_j[iDim] = V_j[iDim+1]; - MeanVelocity[iDim] = 0.5*(Velocity_i[iDim] + Velocity_j[iDim]); - ProjVelocity += MeanVelocity[iDim]*Normal[iDim]; - } - - /*--- Projected velocity adjustment due to mesh motion ---*/ - - if (dynamic_grid) { - ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - } - ProjVelocity -= ProjGridVel; - } - - /*--- Mean variables at points iPoint and jPoint ---*/ - - MeanDensity = 0.5*(DensityInc_i + DensityInc_j); - MeanPressure = 0.5*(Pressure_i + Pressure_j); - MeanBetaInc2 = 0.5*(BetaInc2_i + BetaInc2_j); - MeanEnthalpy = 0.5*(Enthalpy_i + Enthalpy_j); - MeanCp = 0.5*(Cp_i + Cp_j); - MeanTemperature = 0.5*(Temperature_i + Temperature_j); - - /*--- Artificial sound speed based on eigs of preconditioned system ---*/ - - MeanSoundSpeed = sqrt(MeanBetaInc2*Area*Area); - - /*--- We need the derivative of the equation of state to build the - preconditioning matrix. For now, the only option is the ideal gas - law, but in the future, dRhodT should be in the fluid model. ---*/ - - MeandRhodT = 0.0; dRhodT_i = 0.0; dRhodT_j = 0.0; - if (variable_density) { - MeandRhodT = -MeanDensity/MeanTemperature; - dRhodT_i = -DensityInc_i/Temperature_i; - dRhodT_j = -DensityInc_j/Temperature_j; - } - - /*--- Compute ProjFlux_i ---*/ - - GetInviscidIncProjFlux(&DensityInc_i, Velocity_i, &Pressure_i, &BetaInc2_i, &Enthalpy_i, Normal, ProjFlux_i); - - /*--- Compute ProjFlux_j ---*/ - - GetInviscidIncProjFlux(&DensityInc_j, Velocity_j, &Pressure_j, &BetaInc2_j, &Enthalpy_j, Normal, ProjFlux_j); - - /*--- Eigenvalues of the preconditioned system ---*/ - - if (nDim == 2) { - Lambda[0] = ProjVelocity; - Lambda[1] = ProjVelocity; - Lambda[2] = ProjVelocity - MeanSoundSpeed; - Lambda[3] = ProjVelocity + MeanSoundSpeed; - } - if (nDim == 3) { - Lambda[0] = ProjVelocity; - Lambda[1] = ProjVelocity; - Lambda[2] = ProjVelocity; - Lambda[3] = ProjVelocity - MeanSoundSpeed; - Lambda[4] = ProjVelocity + MeanSoundSpeed; - } - - /*--- Absolute value of the eigenvalues ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - Lambda[iVar] = fabs(Lambda[iVar]); - - /*--- Build the preconditioning matrix using mean values ---*/ - - GetPreconditioner(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Precon); - - /*--- Build the absolute value of the preconditioned Jacobian, i.e., - |A_precon| = P x |Lambda| x inv(P), where P diagonalizes the matrix - inv(Precon) x dF/dV and Lambda is the diag. matrix of its eigenvalues. ---*/ - - GetPreconditionedProjJac(&MeanDensity, Lambda, &MeanBetaInc2, UnitNormal, invPrecon_A); - - /*--- Difference of primitive variables at iPoint and jPoint ---*/ - - Diff_V[0] = Pressure_j - Pressure_i; - for (iDim = 0; iDim < nDim; iDim++) - Diff_V[iDim+1] = Velocity_j[iDim] - Velocity_i[iDim]; - Diff_V[nDim+1] = Temperature_j - Temperature_i; - - /*--- Build the inviscid Jacobian w.r.t. the primitive variables ---*/ - - if (implicit) { - GetInviscidIncProjJac(&DensityInc_i, Velocity_i, &BetaInc2_i, &Cp_i, &Temperature_i, &dRhodT_i, Normal, 0.5, val_Jacobian_i); - GetInviscidIncProjJac(&DensityInc_j, Velocity_j, &BetaInc2_j, &Cp_j, &Temperature_j, &dRhodT_j, Normal, 0.5, val_Jacobian_j); - } - - /*--- Compute dissipation as Precon x |A_precon| x dV. If implicit, - store Precon x |A_precon| from dissipation term. ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = 0.5*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); - for (jVar = 0; jVar < nVar; jVar++) { - Proj_ModJac_Tensor_ij = 0.0; - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_ij += Precon[iVar][kVar]*invPrecon_A[kVar][jVar]; - val_residual[iVar] -= 0.5*Proj_ModJac_Tensor_ij*Diff_V[jVar]; - if (implicit) { - val_Jacobian_i[iVar][jVar] += 0.5*Proj_ModJac_Tensor_ij; - val_Jacobian_j[iVar][jVar] -= 0.5*Proj_ModJac_Tensor_ij; - } - } - } - - /*--- Corrections due to grid motion ---*/ - if (dynamic_grid) { - - /*--- Recompute conservative variables ---*/ - - U_i[0] = DensityInc_i; U_j[0] = DensityInc_j; - for (iDim = 0; iDim < nDim; iDim++) { - U_i[iDim+1] = DensityInc_i*Velocity_i[iDim]; U_j[iDim+1] = DensityInc_j*Velocity_j[iDim]; - } - U_i[nDim+1] = DensityInc_i*Enthalpy_i; U_j[nDim+1] = DensityInc_j*Enthalpy_j; - - ProjVelocity = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - - /*--- Residual contributions ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); - - /*--- Jacobian contributions ---*/ - /*--- Implicit terms ---*/ - if (implicit) { - for (iDim = 0; iDim < nDim; iDim++){ - val_Jacobian_i[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_i; - val_Jacobian_j[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_j; - } - val_Jacobian_i[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_i*Cp_i; - val_Jacobian_j[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_j*Cp_j; - } - } - } - - if (!energy) { - val_residual[nDim+1] = 0.0; - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - val_Jacobian_i[iVar][nDim+1] = 0.0; - val_Jacobian_j[iVar][nDim+1] = 0.0; - - val_Jacobian_i[nDim+1][iVar] = 0.0; - val_Jacobian_j[nDim+1][iVar] = 0.0; - } - } - } - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); -} - -CCentJSTInc_Flow::CCentJSTInc_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - variable_density = (config->GetKind_DensityModel() == VARIABLE); - energy = config->GetEnergy_Equation(); - /* 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(); - - /*--- Artifical dissipation part ---*/ - - Param_p = 0.3; - Param_Kappa_2 = config->GetKappa_2nd_Flow(); - Param_Kappa_4 = config->GetKappa_4th_Flow(); - - /*--- Allocate some structures ---*/ - - Diff_V = new su2double [nVar]; - Diff_Lapl = new su2double [nVar]; - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - MeanVelocity = new su2double [nDim]; - ProjFlux = new su2double [nVar]; - Precon = new su2double*[nVar]; - - for (iVar = 0; iVar < nVar; iVar++) - Precon[iVar] = new su2double[nVar]; - -} - -CCentJSTInc_Flow::~CCentJSTInc_Flow(void) { - - delete [] Diff_V; - delete [] Diff_Lapl; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] MeanVelocity; - delete [] ProjFlux; - - for (iVar = 0; iVar < nVar; iVar++) - delete [] Precon[iVar]; - delete [] Precon; - -} - -void CCentJSTInc_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - su2double U_i[5] = {0.0,0.0,0.0,0.0,0.0}, U_j[5] = {0.0,0.0,0.0,0.0,0.0}; - su2double ProjGridVel = 0.0; - - /*--- Primitive variables at point i and j ---*/ - - Pressure_i = V_i[0]; Pressure_j = V_j[0]; - Temperature_i = V_i[nDim+1]; Temperature_j = V_j[nDim+1]; - DensityInc_i = V_i[nDim+2]; DensityInc_j = V_j[nDim+2]; - BetaInc2_i = V_i[nDim+3]; BetaInc2_j = V_j[nDim+3]; - Cp_i = V_i[nDim+7]; Cp_j = V_j[nDim+7]; - Enthalpy_i = Cp_i*Temperature_i; Enthalpy_j = Cp_j*Temperature_j; - - Area = 0.0; - sq_vel_i = 0.0; sq_vel_j = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity_j[iDim] = V_j[iDim+1]; - MeanVelocity[iDim] = 0.5*(Velocity_i[iDim]+Velocity_j[iDim]); - sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; - sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; - ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; - Area += Normal[iDim]*Normal[iDim]; - } - Area = sqrt(Area); - - /*--- Compute mean values of the variables ---*/ - - MeanDensity = 0.5*(DensityInc_i + DensityInc_j); - MeanPressure = 0.5*(Pressure_i + Pressure_j); - MeanBetaInc2 = 0.5*(BetaInc2_i + BetaInc2_j); - MeanEnthalpy = 0.5*(Enthalpy_i + Enthalpy_j); - MeanCp = 0.5*(Cp_i + Cp_j); - MeanTemperature = 0.5*(Temperature_i + Temperature_j); - - /*--- We need the derivative of the equation of state to build the - preconditioning matrix. For now, the only option is the ideal gas - law, but in the future, dRhodT should be in the fluid model. ---*/ - - MeandRhodT = 0.0; - if (variable_density) { - MeandRhodT = -MeanDensity/MeanTemperature; - } - - /*--- Get projected flux tensor ---*/ - - GetInviscidIncProjFlux(&MeanDensity, MeanVelocity, &MeanPressure, &MeanBetaInc2, &MeanEnthalpy, Normal, ProjFlux); - - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = ProjFlux[iVar]; - } - - /*--- Jacobians of the inviscid flux ---*/ - - if (implicit) { - GetInviscidIncProjJac(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Normal, 0.5, val_Jacobian_i); - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_j[iVar][jVar] = val_Jacobian_i[iVar][jVar]; - } - } - } - - /*--- Corrections due to grid motion ---*/ - if (dynamic_grid) { - - /*--- Recompute conservative variables ---*/ - - U_i[0] = DensityInc_i; U_j[0] = DensityInc_j; - for (iDim = 0; iDim < nDim; iDim++) { - U_i[iDim+1] = DensityInc_i*Velocity_i[iDim]; U_j[iDim+1] = DensityInc_j*Velocity_j[iDim]; - } - U_i[nDim+1] = DensityInc_i*Enthalpy_i; U_j[nDim+1] = DensityInc_j*Enthalpy_j; - - su2double ProjVelocity = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - - /*--- Residual contributions ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); - - /*--- Jacobian contributions ---*/ - /*--- Implicit terms ---*/ - if (implicit) { - for (iDim = 0; iDim < nDim; iDim++){ - val_Jacobian_i[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_i; - val_Jacobian_j[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_j; - } - val_Jacobian_i[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_i*Cp_i; - val_Jacobian_j[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_j*Cp_j; - } - } - } - - /*--- Computes differences between Laplacians and conservative variables ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - Diff_Lapl[iVar] = Und_Lapl_i[iVar]-Und_Lapl_j[iVar]; - Diff_V[iVar] = V_i[iVar]-V_j[iVar]; - } - - /*--- Build the preconditioning matrix using mean values ---*/ - - GetPreconditioner(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Precon); - - /*--- Compute the local spectral radius of the preconditioned system - and the stretching factor. ---*/ - - /*--- Projected velocity adjustment due to mesh motion ---*/ - - if (dynamic_grid) { - ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - } - ProjVelocity_i -= ProjGridVel; - ProjVelocity_j -= ProjGridVel; - } - - SoundSpeed_i = sqrt(BetaInc2_i*Area*Area); - SoundSpeed_j = sqrt(BetaInc2_j*Area*Area); - - Local_Lambda_i = fabs(ProjVelocity_i)+SoundSpeed_i; - Local_Lambda_j = fabs(ProjVelocity_j)+SoundSpeed_j; - - MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); - - Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); - Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); - - StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); - - sc2 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); - sc4 = sc2*sc2/4.0; - - Epsilon_2 = Param_Kappa_2*0.5*(Sensor_i+Sensor_j)*sc2; - Epsilon_4 = max(0.0, Param_Kappa_4-Epsilon_2)*sc4; - - /*--- Compute viscous part of the residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_residual[iVar] += Precon[iVar][jVar]*(Epsilon_2*Diff_V[jVar] - Epsilon_4*Diff_Lapl[jVar])*StretchingFactor*MeanLambda; - if (implicit) { - val_Jacobian_i[iVar][jVar] += Precon[iVar][jVar]*(Epsilon_2 + Epsilon_4*su2double(Neighbor_i+1))*StretchingFactor*MeanLambda; - val_Jacobian_j[iVar][jVar] -= Precon[iVar][jVar]*(Epsilon_2 + Epsilon_4*su2double(Neighbor_j+1))*StretchingFactor*MeanLambda; - } - } - } - - /*--- Remove energy contributions if not solving the energy equation. ---*/ - - if (!energy) { - val_residual[nDim+1] = 0.0; - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - val_Jacobian_i[iVar][nDim+1] = 0.0; - val_Jacobian_j[iVar][nDim+1] = 0.0; - - val_Jacobian_i[nDim+1][iVar] = 0.0; - val_Jacobian_j[nDim+1][iVar] = 0.0; - } - } - } -} - -CCentLaxInc_Flow::CCentLaxInc_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - variable_density = (config->GetKind_DensityModel() == VARIABLE); - /* 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(); - energy = config->GetEnergy_Equation(); - - /*--- Artificial dissipation part ---*/ - - Param_p = 0.3; - Param_Kappa_0 = config->GetKappa_1st_Flow(); - - /*--- Allocate some structures ---*/ - - Diff_V = new su2double[nVar]; - Velocity_i = new su2double[nDim]; - Velocity_j = new su2double[nDim]; - MeanVelocity = new su2double[nDim]; - ProjFlux = new su2double[nVar]; - Precon = new su2double*[nVar]; - - for (iVar = 0; iVar < nVar; iVar++) - Precon[iVar] = new su2double[nVar]; - -} - -CCentLaxInc_Flow::~CCentLaxInc_Flow(void) { - - delete [] Diff_V; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] MeanVelocity; - delete [] ProjFlux; - - for (iVar = 0; iVar < nVar; iVar++) - delete [] Precon[iVar]; - delete [] Precon; - -} - -void CCentLaxInc_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - su2double U_i[5] = {0.0,0.0,0.0,0.0,0.0}, U_j[5] = {0.0,0.0,0.0,0.0,0.0}; - su2double ProjGridVel = 0.0, ProjVelocity = 0.0; - - /*--- Primitive variables at point i and j ---*/ - - Pressure_i = V_i[0]; Pressure_j = V_j[0]; - Temperature_i = V_i[nDim+1]; Temperature_j = V_j[nDim+1]; - DensityInc_i = V_i[nDim+2]; DensityInc_j = V_j[nDim+2]; - BetaInc2_i = V_i[nDim+3]; BetaInc2_j = V_j[nDim+3]; - Cp_i = V_i[nDim+7]; Cp_j = V_j[nDim+7]; - Enthalpy_i = Cp_i*Temperature_i; Enthalpy_j = Cp_j*Temperature_j; - - Area = 0.0; - sq_vel_i = 0.0; sq_vel_j = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity_j[iDim] = V_j[iDim+1]; - MeanVelocity[iDim] = 0.5*(Velocity_i[iDim]+Velocity_j[iDim]); - sq_vel_i += 0.5*Velocity_i[iDim]*Velocity_i[iDim]; - sq_vel_j += 0.5*Velocity_j[iDim]*Velocity_j[iDim]; - ProjVelocity_i += Velocity_i[iDim]*Normal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*Normal[iDim]; - Area += Normal[iDim]*Normal[iDim]; - } - Area = sqrt(Area); - - /*--- Compute mean values of the variables ---*/ - - MeanDensity = 0.5*(DensityInc_i + DensityInc_j); - MeanPressure = 0.5*(Pressure_i + Pressure_j); - MeanBetaInc2 = 0.5*(BetaInc2_i + BetaInc2_j); - MeanEnthalpy = 0.5*(Enthalpy_i + Enthalpy_j); - MeanCp = 0.5*(Cp_i + Cp_j); - MeanTemperature = 0.5*(Temperature_i + Temperature_j); - - /*--- We need the derivative of the equation of state to build the - preconditioning matrix. For now, the only option is the ideal gas - law, but in the future, dRhodT should be in the fluid model. ---*/ - - MeandRhodT = 0.0; - if (variable_density) { - MeandRhodT = -MeanDensity/MeanTemperature; - } - - /*--- Get projected flux tensor ---*/ - - GetInviscidIncProjFlux(&MeanDensity, MeanVelocity, &MeanPressure, &MeanBetaInc2, &MeanEnthalpy, Normal, ProjFlux); - - /*--- Compute inviscid residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = ProjFlux[iVar]; - } - - /*--- Jacobians of the inviscid flux ---*/ - - if (implicit) { - GetInviscidIncProjJac(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Normal, 0.5, val_Jacobian_i); - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_j[iVar][jVar] = val_Jacobian_i[iVar][jVar]; - } - } - } - - /*--- Corrections due to grid motion ---*/ - if (dynamic_grid) { - - /*--- Recompute conservative variables ---*/ - - U_i[0] = DensityInc_i; U_j[0] = DensityInc_j; - for (iDim = 0; iDim < nDim; iDim++) { - U_i[iDim+1] = DensityInc_i*Velocity_i[iDim]; U_j[iDim+1] = DensityInc_j*Velocity_j[iDim]; - } - U_i[nDim+1] = DensityInc_i*Enthalpy_i; U_j[nDim+1] = DensityInc_j*Enthalpy_j; - - for (iDim = 0; iDim < nDim; iDim++) - ProjVelocity += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - - /*--- Residual contributions ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] -= ProjVelocity * 0.5*(U_i[iVar]+U_j[iVar]); - - /*--- Jacobian contributions ---*/ - /*--- Implicit terms ---*/ - if (implicit) { - for (iDim = 0; iDim < nDim; iDim++){ - val_Jacobian_i[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_i; - val_Jacobian_j[iDim+1][iDim+1] -= 0.5*ProjVelocity*DensityInc_j; - } - val_Jacobian_i[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_i*Cp_i; - val_Jacobian_j[nDim+1][nDim+1] -= 0.5*ProjVelocity*DensityInc_j*Cp_j; - } - } - } - - /*--- Computes differences btw. conservative variables ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - Diff_V[iVar] = V_i[iVar]-V_j[iVar]; - - /*--- Build the preconditioning matrix using mean values ---*/ - - GetPreconditioner(&MeanDensity, MeanVelocity, &MeanBetaInc2, &MeanCp, &MeanTemperature, &MeandRhodT, Precon); - - /*--- Compute the local espectral radius of the preconditioned system - and the stretching factor. ---*/ - - SoundSpeed_i = sqrt(BetaInc2_i*Area*Area); - SoundSpeed_j = sqrt(BetaInc2_j*Area*Area); - - /*--- Projected velocity adjustment due to mesh motion ---*/ - - if (dynamic_grid) { - ProjGridVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjGridVel += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; - } - ProjVelocity_i -= ProjGridVel; - ProjVelocity_j -= ProjGridVel; - } - - Local_Lambda_i = fabs(ProjVelocity_i)+SoundSpeed_i; - Local_Lambda_j = fabs(ProjVelocity_j)+SoundSpeed_j; - - MeanLambda = 0.5*(Local_Lambda_i+Local_Lambda_j); - - Phi_i = pow(Lambda_i/(4.0*MeanLambda), Param_p); - Phi_j = pow(Lambda_j/(4.0*MeanLambda), Param_p); - - StretchingFactor = 4.0*Phi_i*Phi_j/(Phi_i+Phi_j); - - sc0 = 3.0*(su2double(Neighbor_i)+su2double(Neighbor_j))/(su2double(Neighbor_i)*su2double(Neighbor_j)); - Epsilon_0 = Param_Kappa_0*sc0*su2double(nDim)/3.0; - - /*--- Compute viscous part of the residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_residual[iVar] += Precon[iVar][jVar]*Epsilon_0*Diff_V[jVar]*StretchingFactor*MeanLambda; - if (implicit) { - val_Jacobian_i[iVar][jVar] += Precon[iVar][jVar]*Epsilon_0*StretchingFactor*MeanLambda; - val_Jacobian_j[iVar][jVar] -= Precon[iVar][jVar]*Epsilon_0*StretchingFactor*MeanLambda; - } - } - } - - /*--- Remove energy contributions if we aren't solving the energy equation. ---*/ - - if (!energy) { - val_residual[nDim+1] = 0.0; - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - val_Jacobian_i[iVar][nDim+1] = 0.0; - val_Jacobian_j[iVar][nDim+1] = 0.0; - - val_Jacobian_i[nDim+1][iVar] = 0.0; - val_Jacobian_j[nDim+1][iVar] = 0.0; - } - } - } -} - -CAvgGradInc_Flow::CAvgGradInc_Flow(unsigned short val_nDim, - unsigned short val_nVar, - bool val_correct_grad, CConfig *config) - : CAvgGrad_Base(val_nDim, val_nVar, val_nDim+3, val_correct_grad, config) { - - energy = config->GetEnergy_Equation(); - -} - -CAvgGradInc_Flow::~CAvgGradInc_Flow(void) { -} - -void CAvgGradInc_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - AD::StartPreacc(); - AD::SetPreaccIn(V_i, nDim+9); AD::SetPreaccIn(V_j, nDim+9); - AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); - AD::SetPreaccIn(PrimVar_Grad_i, nVar, nDim); - AD::SetPreaccIn(PrimVar_Grad_j, nVar, nDim); - AD::SetPreaccIn(turb_ke_i); AD::SetPreaccIn(turb_ke_j); - AD::SetPreaccIn(Normal, nDim); - - unsigned short iVar, jVar, iDim; - - /*--- Normalized normal vector ---*/ - - 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; - - for (iVar = 0; iVar < nPrimVar; iVar++) { - PrimVar_i[iVar] = V_i[iVar]; - PrimVar_j[iVar] = V_j[iVar]; - Mean_PrimVar[iVar] = 0.5*(PrimVar_i[iVar]+PrimVar_j[iVar]); - } - - /*--- Compute vector going from iPoint to jPoint ---*/ - - dist_ij_2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; - dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; - } - - /*--- Density and transport properties ---*/ - - Laminar_Viscosity_i = V_i[nDim+4]; Laminar_Viscosity_j = V_j[nDim+4]; - Eddy_Viscosity_i = V_i[nDim+5]; Eddy_Viscosity_j = V_j[nDim+5]; - Thermal_Conductivity_i = V_i[nDim+6]; Thermal_Conductivity_j = V_j[nDim+6]; - - /*--- Mean transport properties ---*/ - - Mean_Laminar_Viscosity = 0.5*(Laminar_Viscosity_i + Laminar_Viscosity_j); - Mean_Eddy_Viscosity = 0.5*(Eddy_Viscosity_i + Eddy_Viscosity_j); - Mean_turb_ke = 0.5*(turb_ke_i + turb_ke_j); - Mean_Thermal_Conductivity = 0.5*(Thermal_Conductivity_i + Thermal_Conductivity_j); - - /*--- Mean gradient approximation ---*/ - - for (iVar = 0; iVar < nVar; iVar++) - for (iDim = 0; iDim < nDim; iDim++) - Mean_GradPrimVar[iVar][iDim] = 0.5*(PrimVar_Grad_i[iVar][iDim] + PrimVar_Grad_j[iVar][iDim]); - - /*--- Projection of the mean gradient in the direction of the edge ---*/ - - if (correct_gradient && dist_ij_2 != 0.0) { - CorrectGradient(Mean_GradPrimVar, PrimVar_i, PrimVar_j, Edge_Vector, - dist_ij_2, nVar); - } - - /*--- Get projected flux tensor ---*/ - SetStressTensor(Mean_PrimVar, Mean_GradPrimVar, Mean_turb_ke, - Mean_Laminar_Viscosity, Mean_Eddy_Viscosity); - GetViscousIncProjFlux(Mean_GradPrimVar, Normal, Mean_Thermal_Conductivity); - - /*--- Update viscous residual ---*/ - - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = Proj_Flux_Tensor[iVar]; - } - - /*--- Implicit part ---*/ - - if (implicit) { - - if (dist_ij_2 == 0.0) { - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) { - val_Jacobian_i[iVar][jVar] = 0.0; - val_Jacobian_j[iVar][jVar] = 0.0; - } - } - } else { - - const su2double dist_ij = sqrt(dist_ij_2); - SetIncTauJacobian(Mean_Laminar_Viscosity, Mean_Eddy_Viscosity, - dist_ij, UnitNormal); - GetViscousIncProjJacs(Area, val_Jacobian_i, val_Jacobian_j); - - /*--- Include the temperature equation Jacobian. ---*/ - su2double proj_vector_ij = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - proj_vector_ij += (Coord_j[iDim]-Coord_i[iDim])*Normal[iDim]; - } - proj_vector_ij = proj_vector_ij/dist_ij_2; - val_Jacobian_i[nDim+1][nDim+1] = -Mean_Thermal_Conductivity*proj_vector_ij; - val_Jacobian_j[nDim+1][nDim+1] = Mean_Thermal_Conductivity*proj_vector_ij; - } - - } - - if (!energy) { - val_residual[nDim+1] = 0.0; - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - val_Jacobian_i[iVar][nDim+1] = 0.0; - val_Jacobian_j[iVar][nDim+1] = 0.0; - - val_Jacobian_i[nDim+1][iVar] = 0.0; - val_Jacobian_j[nDim+1][iVar] = 0.0; - } - } - } - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - -} - -void CAvgGradInc_Flow::GetViscousIncProjFlux(const su2double* const *val_gradprimvar, - const su2double *val_normal, - su2double val_thermal_conductivity) { - - /*--- Gradient of primitive variables -> [Pressure vel_x vel_y vel_z Temperature] ---*/ - - if (nDim == 2) { - Flux_Tensor[0][0] = 0.0; - Flux_Tensor[1][0] = tau[0][0]; - Flux_Tensor[2][0] = tau[0][1]; - Flux_Tensor[3][0] = val_thermal_conductivity*val_gradprimvar[nDim+1][0]; - - Flux_Tensor[0][1] = 0.0; - Flux_Tensor[1][1] = tau[1][0]; - Flux_Tensor[2][1] = tau[1][1]; - Flux_Tensor[3][1] = val_thermal_conductivity*val_gradprimvar[nDim+1][1]; - - } else { - - Flux_Tensor[0][0] = 0.0; - Flux_Tensor[1][0] = tau[0][0]; - Flux_Tensor[2][0] = tau[0][1]; - Flux_Tensor[3][0] = tau[0][2]; - Flux_Tensor[4][0] = val_thermal_conductivity*val_gradprimvar[nDim+1][0]; - - Flux_Tensor[0][1] = 0.0; - Flux_Tensor[1][1] = tau[1][0]; - Flux_Tensor[2][1] = tau[1][1]; - Flux_Tensor[3][1] = tau[1][2]; - Flux_Tensor[4][1] = val_thermal_conductivity*val_gradprimvar[nDim+1][1]; - - Flux_Tensor[0][2] = 0.0; - Flux_Tensor[1][2] = tau[2][0]; - Flux_Tensor[2][2] = tau[2][1]; - Flux_Tensor[3][2] = tau[2][2]; - Flux_Tensor[4][2] = val_thermal_conductivity*val_gradprimvar[nDim+1][2]; - - } - - for (unsigned short iVar = 0; iVar < nVar; iVar++) { - Proj_Flux_Tensor[iVar] = 0.0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Proj_Flux_Tensor[iVar] += Flux_Tensor[iVar][iDim] * val_normal[iDim]; - } - -} - -void CAvgGradInc_Flow::GetViscousIncProjJacs(su2double val_dS, - su2double **val_Proj_Jac_Tensor_i, - su2double **val_Proj_Jac_Tensor_j) { - - if (nDim == 2) { - - val_Proj_Jac_Tensor_i[0][0] = 0.0; - val_Proj_Jac_Tensor_i[0][1] = 0.0; - val_Proj_Jac_Tensor_i[0][2] = 0.0; - val_Proj_Jac_Tensor_i[0][3] = 0.0; - - val_Proj_Jac_Tensor_i[1][0] = val_dS*tau_jacobian_i[0][0]; - val_Proj_Jac_Tensor_i[1][1] = val_dS*tau_jacobian_i[0][1]; - val_Proj_Jac_Tensor_i[1][2] = val_dS*tau_jacobian_i[0][2]; - val_Proj_Jac_Tensor_i[1][3] = val_dS*tau_jacobian_i[0][3]; - - val_Proj_Jac_Tensor_i[2][0] = val_dS*tau_jacobian_i[1][0]; - val_Proj_Jac_Tensor_i[2][1] = val_dS*tau_jacobian_i[1][1]; - val_Proj_Jac_Tensor_i[2][2] = val_dS*tau_jacobian_i[1][2]; - val_Proj_Jac_Tensor_i[2][3] = val_dS*tau_jacobian_i[1][3]; - - val_Proj_Jac_Tensor_i[3][0] = 0.0; - val_Proj_Jac_Tensor_i[3][1] = 0.0; - val_Proj_Jac_Tensor_i[3][2] = 0.0; - val_Proj_Jac_Tensor_i[3][3] = 0.0; - - } else { - - val_Proj_Jac_Tensor_i[0][0] = 0.0; - val_Proj_Jac_Tensor_i[0][1] = 0.0; - val_Proj_Jac_Tensor_i[0][2] = 0.0; - val_Proj_Jac_Tensor_i[0][3] = 0.0; - val_Proj_Jac_Tensor_i[0][4] = 0.0; - - val_Proj_Jac_Tensor_i[1][0] = val_dS*tau_jacobian_i[0][0]; - val_Proj_Jac_Tensor_i[1][1] = val_dS*tau_jacobian_i[0][1]; - val_Proj_Jac_Tensor_i[1][2] = val_dS*tau_jacobian_i[0][2]; - val_Proj_Jac_Tensor_i[1][3] = val_dS*tau_jacobian_i[0][3]; - val_Proj_Jac_Tensor_i[1][4] = val_dS*tau_jacobian_i[0][4]; - - val_Proj_Jac_Tensor_i[2][0] = val_dS*tau_jacobian_i[1][0]; - val_Proj_Jac_Tensor_i[2][1] = val_dS*tau_jacobian_i[1][1]; - val_Proj_Jac_Tensor_i[2][2] = val_dS*tau_jacobian_i[1][2]; - val_Proj_Jac_Tensor_i[2][3] = val_dS*tau_jacobian_i[1][3]; - val_Proj_Jac_Tensor_i[2][4] = val_dS*tau_jacobian_i[1][4]; - - val_Proj_Jac_Tensor_i[3][0] = val_dS*tau_jacobian_i[2][0]; - val_Proj_Jac_Tensor_i[3][1] = val_dS*tau_jacobian_i[2][1]; - val_Proj_Jac_Tensor_i[3][2] = val_dS*tau_jacobian_i[2][2]; - val_Proj_Jac_Tensor_i[3][3] = val_dS*tau_jacobian_i[2][3]; - val_Proj_Jac_Tensor_i[3][4] = val_dS*tau_jacobian_i[2][4]; - - val_Proj_Jac_Tensor_i[4][0] = 0.0; - val_Proj_Jac_Tensor_i[4][1] = 0.0; - val_Proj_Jac_Tensor_i[4][2] = 0.0; - val_Proj_Jac_Tensor_i[4][3] = 0.0; - val_Proj_Jac_Tensor_i[4][4] = 0.0; - - } - - for (unsigned short iVar = 0; iVar < nVar; iVar++) - for (unsigned short jVar = 0; jVar < nVar; jVar++) - val_Proj_Jac_Tensor_j[iVar][jVar] = -val_Proj_Jac_Tensor_i[iVar][jVar]; - -} - -CSourceIncBodyForce::CSourceIncBodyForce(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - /*--- Store the pointer to the constant body force vector. ---*/ - - Body_Force_Vector = new su2double[nDim]; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Body_Force_Vector[iDim] = config->GetBody_Force_Vector()[iDim]; - -} - -CSourceIncBodyForce::~CSourceIncBodyForce(void) { - - if (Body_Force_Vector != NULL) delete [] Body_Force_Vector; - -} - -void CSourceIncBodyForce::ComputeResidual(su2double *val_residual, CConfig *config) { - - unsigned short iDim; - su2double DensityInc_0 = 0.0; - su2double Force_Ref = config->GetForce_Ref(); - bool variable_density = (config->GetKind_DensityModel() == VARIABLE); - - /*--- Check for variable density. If we have a variable density - problem, we should subtract out the hydrostatic pressure component. ---*/ - - if (variable_density) DensityInc_0 = config->GetDensity_FreeStreamND(); - - /*--- Zero the continuity contribution ---*/ - - val_residual[0] = 0.0; - - /*--- Momentum contribution. Note that this form assumes we have - subtracted the operating density * gravity, i.e., removed the - hydrostatic pressure component (important for pressure BCs). ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = -Volume * (DensityInc_i - DensityInc_0) * Body_Force_Vector[iDim] / Force_Ref; - - /*--- Zero the temperature contribution ---*/ - - val_residual[nDim+1] = 0.0; - -} - -CSourceIncRotatingFrame_Flow::CSourceIncRotatingFrame_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - /*--- Retrieve the angular velocity vector from config. ---*/ - for (unsigned short iDim = 0; iDim < 3; iDim++) - Omega[iDim] = config->GetRotation_Rate(iDim)/config->GetOmega_Ref(); - -} - -CSourceIncRotatingFrame_Flow::~CSourceIncRotatingFrame_Flow(void) { } - -void CSourceIncRotatingFrame_Flow::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) { - - unsigned short iDim, iVar, jVar; - su2double Momentum[3] = {0,0,0}, - Velocity_i[3] = {0,0,0}; - - /*--- Primitive variables plus momentum at the node (point i) ---*/ - - DensityInc_i = V_i[nDim+2]; - - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Momentum[iDim] = DensityInc_i*Velocity_i[iDim]; - } - - /*--- Calculate rotating frame source term residual as ( Omega X Rho-U ) ---*/ - - if (nDim == 2) { - val_residual[0] = 0.0; - val_residual[1] = (Omega[1]*Momentum[2] - Omega[2]*Momentum[1])*Volume; - val_residual[2] = (Omega[2]*Momentum[0] - Omega[0]*Momentum[2])*Volume; - val_residual[3] = 0.0; - } else { - val_residual[0] = 0.0; - val_residual[1] = (Omega[1]*Momentum[2] - Omega[2]*Momentum[1])*Volume; - val_residual[2] = (Omega[2]*Momentum[0] - Omega[0]*Momentum[2])*Volume; - val_residual[3] = (Omega[0]*Momentum[1] - Omega[1]*Momentum[0])*Volume; - val_residual[4] = 0.0; - } - - /*--- Calculate the source term Jacobian ---*/ - - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) - for (jVar = 0; jVar < nVar; jVar++) - val_Jacobian_i[iVar][jVar] = 0.0; - if (nDim == 2) { - val_Jacobian_i[1][2] = -DensityInc_i*Omega[2]*Volume; - val_Jacobian_i[2][1] = DensityInc_i*Omega[2]*Volume; - } else { - val_Jacobian_i[1][2] = -DensityInc_i*Omega[2]*Volume; - val_Jacobian_i[1][3] = DensityInc_i*Omega[1]*Volume; - val_Jacobian_i[2][1] = DensityInc_i*Omega[2]*Volume; - val_Jacobian_i[2][3] = -DensityInc_i*Omega[0]*Volume; - val_Jacobian_i[3][1] = -DensityInc_i*Omega[1]*Volume; - val_Jacobian_i[3][2] = DensityInc_i*Omega[0]*Volume; - } - } - -} - -CSourceBoussinesq::CSourceBoussinesq(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - /*--- Store the pointer to the constant body force vector. ---*/ - - Gravity_Vector = new su2double[nDim]; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - Gravity_Vector[iDim] = 0.0; - - /*--- Gravity is downward in y-dir for 2D and downward z-dir for 3D. ---*/ - - Gravity_Vector[nDim-1] = -STANDARD_GRAVITY; - -} - -CSourceBoussinesq::~CSourceBoussinesq(void) { - - if (Gravity_Vector != NULL) delete [] Gravity_Vector; - -} - -void CSourceBoussinesq::ComputeResidual(su2double *val_residual, CConfig *config) { - - unsigned short iDim; - su2double Force_Ref = config->GetForce_Ref(); - su2double T0 = config->GetTemperature_FreeStreamND(); - su2double Beta = config->GetThermal_Expansion_CoeffND(); - - /*--- Zero the continuity contribution ---*/ - - val_residual[0] = 0.0; - - /*--- Momentum contribution. Note that this form assumes we have - subtracted the operating density * gravity, i.e., removed the - hydrostatic pressure component (important for pressure BCs). ---*/ - - for (iDim = 0; iDim < nDim; iDim++) - val_residual[iDim+1] = Volume * DensityInc_i * ( Beta * (U_i[nDim+1] - T0)) * Gravity_Vector[iDim] / Force_Ref; - - /*--- Zero the energy contribution ---*/ - - val_residual[nDim+1] = 0.0; - -} - -CSourceIncAxisymmetric_Flow::CSourceIncAxisymmetric_Flow(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - energy = config->GetEnergy_Equation(); - viscous = config->GetViscous(); - -} - -CSourceIncAxisymmetric_Flow::~CSourceIncAxisymmetric_Flow(void) { } - -void CSourceIncAxisymmetric_Flow::ComputeResidual(su2double *val_residual, su2double **Jacobian_i, CConfig *config) { - - su2double yinv, Velocity_i[3]; - unsigned short iDim, jDim, iVar, jVar; - - if (Coord_i[1] > EPS) { - - yinv = 1.0/Coord_i[1]; - - /*--- Set primitive variables at points iPoint. ---*/ - - Pressure_i = V_i[0]; - Temp_i = V_i[nDim+1]; - DensityInc_i = V_i[nDim+2]; - BetaInc2_i = V_i[nDim+3]; - Cp_i = V_i[nDim+7]; - Enthalpy_i = Cp_i*Temp_i; - - for (iDim = 0; iDim < nDim; iDim++) - Velocity_i[iDim] = V_i[iDim+1]; - - /*--- Inviscid component of the source term. ---*/ - - val_residual[0] = yinv*Volume*DensityInc_i*Velocity_i[1]; - val_residual[1] = yinv*Volume*DensityInc_i*Velocity_i[0]*Velocity_i[1]; - val_residual[2] = yinv*Volume*DensityInc_i*Velocity_i[1]*Velocity_i[1]; - val_residual[3] = yinv*Volume*DensityInc_i*Enthalpy_i*Velocity_i[1]; - - if (implicit) { - - Jacobian_i[0][0] = 0.0; - Jacobian_i[0][1] = 0.0; - Jacobian_i[0][2] = 1.0; - Jacobian_i[0][3] = 0.0; - - Jacobian_i[1][0] = 0.0; - Jacobian_i[1][1] = Velocity_i[1]; - Jacobian_i[1][2] = Velocity_i[0]; - Jacobian_i[1][3] = 0.0; - - Jacobian_i[2][0] = 0.0; - Jacobian_i[2][1] = 0.0; - Jacobian_i[2][2] = 2.0*Velocity_i[1]; - Jacobian_i[2][3] = 0.0; - - Jacobian_i[3][0] = 0.0; - Jacobian_i[3][1] = 0.0; - Jacobian_i[3][2] = Enthalpy_i; - Jacobian_i[3][3] = Cp_i*Velocity_i[1]; - - for (iVar=0; iVar < nVar; iVar++) - for (jVar=0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] *= yinv*Volume*DensityInc_i; - - } - - /*--- Add the viscous terms if necessary. ---*/ - - if (viscous) { - - Laminar_Viscosity_i = V_i[nDim+4]; - Eddy_Viscosity_i = V_i[nDim+5]; - Thermal_Conductivity_i = V_i[nDim+6]; - - su2double total_viscosity, div_vel; - - total_viscosity = (Laminar_Viscosity_i + Eddy_Viscosity_i); - - /*--- The full stress tensor is needed for variable density ---*/ - - div_vel = 0.0; - for (iDim = 0 ; iDim < nDim; iDim++) - div_vel += PrimVar_Grad_i[iDim+1][iDim]; - - for (iDim = 0 ; iDim < nDim; iDim++) - for (jDim = 0 ; jDim < nDim; jDim++) - tau[iDim][jDim] = (total_viscosity*(PrimVar_Grad_i[jDim+1][iDim] + - PrimVar_Grad_i[iDim+1][jDim] ) - -TWO3*total_viscosity*div_vel*delta[iDim][jDim]); - - /*--- Viscous terms. ---*/ - - val_residual[0] -= 0.0; - val_residual[1] -= Volume*(yinv*tau[0][1] - TWO3*AuxVar_Grad_i[0]); - val_residual[2] -= Volume*(yinv*2.0*total_viscosity*PrimVar_Grad_i[2][1] - - yinv*yinv*2.0*total_viscosity*Velocity_i[1] - - TWO3*AuxVar_Grad_i[1]); - val_residual[3] -= Volume*yinv*Thermal_Conductivity_i*PrimVar_Grad_i[nDim+1][1]; - - } - - } else { - - for (iVar=0; iVar < nVar; iVar++) - val_residual[iVar] = 0.0; - - if (implicit) { - for (iVar=0; iVar < nVar; iVar++) { - for (jVar=0; jVar < nVar; jVar++) - Jacobian_i[iVar][jVar] = 0.0; - } - } - - } - - if (!energy) { - val_residual[nDim+1] = 0.0; - if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - Jacobian_i[iVar][nDim+1] = 0.0; - Jacobian_i[nDim+1][iVar] = 0.0; - } - } - } - -} diff --git a/SU2_CFD/src/numerics_direct_turbulent.cpp b/SU2_CFD/src/numerics_direct_turbulent.cpp deleted file mode 100644 index fff1df4be577..000000000000 --- a/SU2_CFD/src/numerics_direct_turbulent.cpp +++ /dev/null @@ -1,1505 +0,0 @@ -/*! - * \file numerics_direct_turbulent.cpp - * \brief This file contains all the convective term discretization. - * \author F. Palacios, A. Bueno - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - - -#include "../include/numerics_structure.hpp" -#include - -CUpwScalar::CUpwScalar(unsigned short val_nDim, - unsigned short val_nVar, - CConfig *config) - : CNumerics(val_nDim, val_nVar, config) { - - implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); - incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - /* 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(); - - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - -} - -CUpwScalar::~CUpwScalar(void) { - - delete [] Velocity_i; - delete [] Velocity_j; - -} - -void CUpwScalar::ComputeResidual(su2double *val_residual, - su2double **val_Jacobian_i, - su2double **val_Jacobian_j, - CConfig *config) { - - AD::StartPreacc(); - AD::SetPreaccIn(Normal, nDim); - AD::SetPreaccIn(TurbVar_i, nVar); AD::SetPreaccIn(TurbVar_j, nVar); - if (dynamic_grid) { - AD::SetPreaccIn(GridVel_i, nDim); AD::SetPreaccIn(GridVel_j, nDim); - } - - ExtraADPreaccIn(); - - Density_i = V_i[nDim+2]; - Density_j = V_j[nDim+2]; - - q_ij = 0.0; - if (dynamic_grid) { - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1] - GridVel_i[iDim]; - Velocity_j[iDim] = V_j[iDim+1] - GridVel_j[iDim]; - q_ij += 0.5*(Velocity_i[iDim]+Velocity_j[iDim])*Normal[iDim]; - } - } - else { - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = V_i[iDim+1]; - Velocity_j[iDim] = V_j[iDim+1]; - q_ij += 0.5*(Velocity_i[iDim]+Velocity_j[iDim])*Normal[iDim]; - } - } - - a0 = 0.5*(q_ij+fabs(q_ij)); - a1 = 0.5*(q_ij-fabs(q_ij)); - - FinishResidualCalc(val_residual, val_Jacobian_i, val_Jacobian_j, config); - - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - -} - -CUpwSca_TurbSA::CUpwSca_TurbSA(unsigned short val_nDim, - unsigned short val_nVar, - CConfig *config) - : CUpwScalar(val_nDim, val_nVar, config) { -} - -CUpwSca_TurbSA::~CUpwSca_TurbSA(void) { -} - -void CUpwSca_TurbSA::ExtraADPreaccIn() { - AD::SetPreaccIn(V_i, nDim+1); AD::SetPreaccIn(V_j, nDim+1); -} - -void CUpwSca_TurbSA::FinishResidualCalc(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - val_residual[0] = a0*TurbVar_i[0]+a1*TurbVar_j[0]; - - if (implicit) { - val_Jacobian_i[0][0] = a0; - val_Jacobian_j[0][0] = a1; - } -} - -CAvgGrad_Scalar::CAvgGrad_Scalar(unsigned short val_nDim, - unsigned short val_nVar, - bool correct_grad, - CConfig *config) - : CNumerics(val_nDim, val_nVar, config), correct_gradient(correct_grad) { - - implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); - incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - - Edge_Vector = new su2double [nDim]; - Proj_Mean_GradTurbVar_Normal = new su2double [nVar]; - Proj_Mean_GradTurbVar_Edge = new su2double [nVar]; - Proj_Mean_GradTurbVar = new su2double [nVar]; - Mean_GradTurbVar = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar++) - Mean_GradTurbVar[iVar] = new su2double [nDim]; - -} - -CAvgGrad_Scalar::~CAvgGrad_Scalar(void) { - - delete [] Edge_Vector; - delete [] Proj_Mean_GradTurbVar_Normal; - delete [] Proj_Mean_GradTurbVar_Edge; - delete [] Proj_Mean_GradTurbVar; - for (iVar = 0; iVar < nVar; iVar++) - delete [] Mean_GradTurbVar[iVar]; - delete [] Mean_GradTurbVar; - -} - -void CAvgGrad_Scalar::ComputeResidual(su2double *val_residual, - su2double **Jacobian_i, - su2double **Jacobian_j, - CConfig *config) { - - AD::StartPreacc(); - AD::SetPreaccIn(Coord_i, nDim); AD::SetPreaccIn(Coord_j, nDim); - AD::SetPreaccIn(Normal, nDim); - AD::SetPreaccIn(TurbVar_Grad_i, nVar, nDim); - AD::SetPreaccIn(TurbVar_Grad_j, nVar, nDim); - if (correct_gradient) { - AD::SetPreaccIn(TurbVar_i, nVar); AD::SetPreaccIn(TurbVar_j ,nVar); - } - ExtraADPreaccIn(); - - if (incompressible) { - AD::SetPreaccIn(V_i, nDim+6); AD::SetPreaccIn(V_j, nDim+6); - - Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+4]; Laminar_Viscosity_j = V_j[nDim+4]; - Eddy_Viscosity_i = V_i[nDim+5]; Eddy_Viscosity_j = V_j[nDim+5]; - } - else { - AD::SetPreaccIn(V_i, nDim+7); AD::SetPreaccIn(V_j, nDim+7); - - Density_i = V_i[nDim+2]; Density_j = V_j[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+5]; Laminar_Viscosity_j = V_j[nDim+5]; - Eddy_Viscosity_i = V_i[nDim+6]; Eddy_Viscosity_j = V_j[nDim+6]; - } - - /*--- Compute vector going from iPoint to jPoint ---*/ - - dist_ij_2 = 0; proj_vector_ij = 0; - for (iDim = 0; iDim < nDim; iDim++) { - Edge_Vector[iDim] = Coord_j[iDim]-Coord_i[iDim]; - dist_ij_2 += Edge_Vector[iDim]*Edge_Vector[iDim]; - proj_vector_ij += Edge_Vector[iDim]*Normal[iDim]; - } - if (dist_ij_2 == 0.0) proj_vector_ij = 0.0; - else proj_vector_ij = proj_vector_ij/dist_ij_2; - - /*--- Mean gradient approximation ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - Proj_Mean_GradTurbVar_Normal[iVar] = 0.0; - Proj_Mean_GradTurbVar_Edge[iVar] = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - Mean_GradTurbVar[iVar][iDim] = 0.5*(TurbVar_Grad_i[iVar][iDim] + - TurbVar_Grad_j[iVar][iDim]); - Proj_Mean_GradTurbVar_Normal[iVar] += Mean_GradTurbVar[iVar][iDim] * - Normal[iDim]; - if (correct_gradient) - Proj_Mean_GradTurbVar_Edge[iVar] += Mean_GradTurbVar[iVar][iDim]*Edge_Vector[iDim]; - } - Proj_Mean_GradTurbVar[iVar] = Proj_Mean_GradTurbVar_Normal[iVar]; - if (correct_gradient) { - Proj_Mean_GradTurbVar[iVar] -= Proj_Mean_GradTurbVar_Edge[iVar]*proj_vector_ij - - (TurbVar_j[iVar]-TurbVar_i[iVar])*proj_vector_ij; - } - } - - FinishResidualCalc(val_residual, Jacobian_i, Jacobian_j, config); - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - -} - -CAvgGrad_TurbSA::CAvgGrad_TurbSA(unsigned short val_nDim, - unsigned short val_nVar, bool correct_grad, - CConfig *config) - : CAvgGrad_Scalar(val_nDim, val_nVar, correct_grad, config), sigma(2./3.) { -} - -CAvgGrad_TurbSA::~CAvgGrad_TurbSA(void) { -} - -void CAvgGrad_TurbSA::ExtraADPreaccIn() { -} - -void CAvgGrad_TurbSA::FinishResidualCalc(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config) { - - /*--- Compute mean effective viscosity ---*/ - - nu_i = Laminar_Viscosity_i/Density_i; - nu_j = Laminar_Viscosity_j/Density_j; - nu_e = 0.5*(nu_i+nu_j+TurbVar_i[0]+TurbVar_j[0]); - - val_residual[0] = nu_e*Proj_Mean_GradTurbVar[0]/sigma; - - /*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/ - - if (implicit) { - Jacobian_i[0][0] = (0.5*Proj_Mean_GradTurbVar[0]-nu_e*proj_vector_ij)/sigma; - Jacobian_j[0][0] = (0.5*Proj_Mean_GradTurbVar[0]+nu_e*proj_vector_ij)/sigma; - } - -} - -CAvgGrad_TurbSA_Neg::CAvgGrad_TurbSA_Neg(unsigned short val_nDim, - unsigned short val_nVar, - bool correct_grad, - CConfig *config) - : CAvgGrad_Scalar(val_nDim, val_nVar, correct_grad, config), - sigma(2./3.), cn1(16.0), fn(0.0) { -} - -CAvgGrad_TurbSA_Neg::~CAvgGrad_TurbSA_Neg(void) { -} - -void CAvgGrad_TurbSA_Neg::ExtraADPreaccIn() { -} - -void CAvgGrad_TurbSA_Neg::FinishResidualCalc(su2double *val_residual, - su2double **Jacobian_i, - su2double **Jacobian_j, - CConfig *config) { - - /*--- Compute mean effective viscosity ---*/ - - nu_i = Laminar_Viscosity_i/Density_i; - nu_j = Laminar_Viscosity_j/Density_j; - - nu_ij = 0.5*(nu_i+nu_j); - nu_tilde_ij = 0.5*(TurbVar_i[0]+TurbVar_j[0]); - - Xi = nu_tilde_ij/nu_ij; - - if (nu_tilde_ij > 0.0) { - nu_e = nu_ij + nu_tilde_ij; - } - else { - fn = (cn1 + Xi*Xi*Xi)/(cn1 - Xi*Xi*Xi); - nu_e = nu_ij + fn*nu_tilde_ij; - } - - val_residual[0] = nu_e*Proj_Mean_GradTurbVar_Normal[0]/sigma; - - /*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/ - - if (implicit) { - Jacobian_i[0][0] = (0.5*Proj_Mean_GradTurbVar[0]-nu_e*proj_vector_ij)/sigma; - Jacobian_j[0][0] = (0.5*Proj_Mean_GradTurbVar[0]+nu_e*proj_vector_ij)/sigma; - } - -} - -CSourcePieceWise_TurbSA::CSourcePieceWise_TurbSA(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - rotating_frame = config->GetRotating_Frame(); - transition = (config->GetKind_Trans_Model() == BC); - - /*--- Spalart-Allmaras closure constants ---*/ - - cv1_3 = pow(7.1, 3.0); - k2 = pow(0.41, 2.0); - cb1 = 0.1355; - cw2 = 0.3; - ct3 = 1.2; - ct4 = 0.5; - cw3_6 = pow(2.0, 6.0); - sigma = 2./3.; - cb2 = 0.622; - cb2_sigma = cb2/sigma; - cw1 = cb1/k2+(1.0+cb2)/sigma; - -} - -CSourcePieceWise_TurbSA::~CSourcePieceWise_TurbSA(void) { } - -void CSourcePieceWise_TurbSA::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - -// AD::StartPreacc(); -// AD::SetPreaccIn(V_i, nDim+6); -// AD::SetPreaccIn(Vorticity_i, nDim); -// AD::SetPreaccIn(StrainMag_i); -// AD::SetPreaccIn(TurbVar_i[0]); -// AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); -// AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); - -// BC Transition Model variables - su2double vmag, rey, re_theta, re_theta_t, re_v; - su2double tu , nu_cr, nu_t, nu_BC, chi_1, chi_2, term1, term2, term_exponential; - - if (incompressible) { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+4]; - } - else { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+5]; - } - - val_residual[0] = 0.0; - Production = 0.0; - Destruction = 0.0; - CrossProduction = 0.0; - val_Jacobian_i[0][0] = 0.0; - - gamma_BC = 0.0; - vmag = 0.0; - tu = config->GetTurbulenceIntensity_FreeStream(); - rey = config->GetReynolds(); - - if (nDim==2) { - vmag = sqrt(V_i[1]*V_i[1]+V_i[2]*V_i[2]); - } - else if (nDim==3) { - vmag = sqrt(V_i[1]*V_i[1]+V_i[2]*V_i[2]+V_i[3]*V_i[3]); - } - - /*--- Evaluate Omega ---*/ - - Omega = sqrt(Vorticity_i[0]*Vorticity_i[0] + Vorticity_i[1]*Vorticity_i[1] + Vorticity_i[2]*Vorticity_i[2]); - - /*--- Rotational correction term ---*/ - - if (rotating_frame) { Omega += 2.0*min(0.0, StrainMag_i-Omega); } - - if (dist_i > 1e-10) { - - /*--- Production term ---*/ - - dist_i_2 = dist_i*dist_i; - nu = Laminar_Viscosity_i/Density_i; - Ji = TurbVar_i[0]/nu; - Ji_2 = Ji*Ji; - Ji_3 = Ji_2*Ji; - fv1 = Ji_3/(Ji_3+cv1_3); - fv2 = 1.0 - Ji/(1.0+Ji*fv1); - ft2 = ct3*exp(-ct4*Ji_2); - S = Omega; - inv_k2_d2 = 1.0/(k2*dist_i_2); - - Shat = S + TurbVar_i[0]*fv2*inv_k2_d2; - Shat = max(Shat, 1.0e-10); - inv_Shat = 1.0/Shat; - -// Original SA model -// Production = cb1*(1.0-ft2)*Shat*TurbVar_i[0]*Volume; - - if (transition) { - -// BC model constants - chi_1 = 0.002; - chi_2 = 5.0; - - nu_t = (TurbVar_i[0]*fv1); //S-A variable - nu_cr = chi_2/rey; - nu_BC = (nu_t)/(vmag*dist_i); - - re_v = ((Density_i*pow(dist_i,2.))/(Laminar_Viscosity_i))*Omega; - re_theta = re_v/2.193; - re_theta_t = (803.73 * pow((tu + 0.6067),-1.027)); //MENTER correlation - //re_theta_t = 163.0 + exp(6.91-tu); //ABU-GHANNAM & SHAW correlation - - term1 = sqrt(max(re_theta-re_theta_t,0.)/(chi_1*re_theta_t)); - term2 = sqrt(max(nu_BC-nu_cr,0.)/(nu_cr)); - term_exponential = (term1 + term2); - gamma_BC = 1.0 - exp(-term_exponential); - - Production = gamma_BC*cb1*Shat*TurbVar_i[0]*Volume; - } - else { - Production = cb1*Shat*TurbVar_i[0]*Volume; - } - - /*--- Destruction term ---*/ - - r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); - g = r + cw2*(pow(r,6.0)-r); - g_6 = pow(g,6.0); - glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); - fw = g*glim; - -// Original SA model -// Destruction = (cw1*fw-cb1*ft2/k2)*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; - - Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; - - /*--- Diffusion term ---*/ - - norm2_Grad = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; - - CrossProduction = cb2_sigma*norm2_Grad*Volume; - - val_residual[0] = Production - Destruction + CrossProduction; - - /*--- Implicit part, production term ---*/ - - dfv1 = 3.0*Ji_2*cv1_3/(nu*pow(Ji_3+cv1_3,2.)); - dfv2 = -(1/nu-Ji_2*dfv1)/pow(1.+Ji*fv1,2.); - if ( Shat <= 1.0e-10 ) dShat = 0.0; - else dShat = (fv2+TurbVar_i[0]*dfv2)*inv_k2_d2; - - if (transition) { - val_Jacobian_i[0][0] += gamma_BC*cb1*(TurbVar_i[0]*dShat+Shat)*Volume; - } - else { - val_Jacobian_i[0][0] += cb1*(TurbVar_i[0]*dShat+Shat)*Volume; - } - - /*--- Implicit part, destruction term ---*/ - - dr = (Shat-TurbVar_i[0]*dShat)*inv_Shat*inv_Shat*inv_k2_d2; - if (r == 10.0) dr = 0.0; - dg = dr*(1.+cw2*(6.0*pow(r,5.0)-1.0)); - dfw = dg*glim*(1.-g_6/(g_6+cw3_6)); - val_Jacobian_i[0][0] -= cw1*(dfw*TurbVar_i[0] + 2.0*fw)*TurbVar_i[0]/dist_i_2*Volume; - - } - -// AD::SetPreaccOut(val_residual[0]); -// AD::EndPreacc(); - -} - -CSourcePieceWise_TurbSA_E::CSourcePieceWise_TurbSA_E(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - rotating_frame = config->GetRotating_Frame(); - - /*--- Spalart-Allmaras closure constants ---*/ - - cv1_3 = pow(7.1, 3.0); - k2 = pow(0.41, 2.0); - cb1 = 0.1355; - cw2 = 0.3; - ct3 = 1.2; - ct4 = 0.5; - cw3_6 = pow(2.0, 6.0); - sigma = 2./3.; - cb2 = 0.622; - cb2_sigma = cb2/sigma; - cw1 = cb1/k2+(1.0+cb2)/sigma; - -} - -CSourcePieceWise_TurbSA_E::~CSourcePieceWise_TurbSA_E(void) { } - -void CSourcePieceWise_TurbSA_E::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - // AD::StartPreacc(); - // AD::SetPreaccIn(V_i, nDim+6); - // AD::SetPreaccIn(Vorticity_i, nDim); - // AD::SetPreaccIn(StrainMag_i); - // AD::SetPreaccIn(TurbVar_i[0]); - // AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); - // AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); - - if (incompressible) { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+4]; - } - else { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+5]; - } - - val_residual[0] = 0.0; - Production = 0.0; - Destruction = 0.0; - CrossProduction = 0.0; - val_Jacobian_i[0][0] = 0.0; - - - /* - From NASA Turbulence model site. http://turbmodels.larc.nasa.gov/spalart.html - This form was developed primarily to improve the near-wall numerical behavior of the model (i.e., the goal was to improve the convergence behavior). The reference is: - Edwards, J. R. and Chandra, S. "Comparison of Eddy Viscosity-Transport Turbulence Models for Three-Dimensional, Shock-Separated Flowfields," AIAA Journal, Vol. 34, No. 4, 1996, pp. 756-763. - In this modificaton Omega is replaced by Strain Rate - */ - - /*--- Evaluate Omega, here Omega is the Strain Rate ---*/ - - Sbar = 0.0; - for(iDim=0;iDim 1e-10) { - - /*--- Production term ---*/ - - dist_i_2 = dist_i*dist_i; - nu = Laminar_Viscosity_i/Density_i; - Ji = TurbVar_i[0]/nu; - Ji_2 = Ji*Ji; - Ji_3 = Ji_2*Ji; - fv1 = Ji_3/(Ji_3+cv1_3); - fv2 = 1.0 - Ji/(1.0+Ji*fv1); - ft2 = ct3*exp(-ct4*Ji_2); - S = Omega; - inv_k2_d2 = 1.0/(k2*dist_i_2); - - //Shat = S + TurbVar_i[0]*fv2*inv_k2_d2; - Shat = max(S*((1.0/max(Ji,1.0e-16))+fv1),1.0e-16); - - Shat = max(Shat, 1.0e-10); - inv_Shat = 1.0/Shat; - - /*--- Production term ---*/; - - Production = cb1*Shat*TurbVar_i[0]*Volume; - - /*--- Destruction term ---*/ - - r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); - r=tanh(r)/tanh(1.0); - - g = r + cw2*(pow(r,6.0)-r); - g_6 = pow(g,6.0); - glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); - fw = g*glim; - - Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; - - /*--- Diffusion term ---*/ - - norm2_Grad = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; - - CrossProduction = cb2_sigma*norm2_Grad*Volume; - - val_residual[0] = Production - Destruction + CrossProduction; - - /*--- Implicit part, production term ---*/ - - dfv1 = 3.0*Ji_2*cv1_3/(nu*pow(Ji_3+cv1_3,2.)); - dfv2 = -(1/nu-Ji_2*dfv1)/pow(1.+Ji*fv1,2.); - - if ( Shat <= 1.0e-10 ) dShat = 0.0; - else dShat = -S*pow(Ji,-2.0)/nu + S*dfv1; - val_Jacobian_i[0][0] += cb1*(TurbVar_i[0]*dShat+Shat)*Volume; - - /*--- Implicit part, destruction term ---*/ - - dr = (Shat-TurbVar_i[0]*dShat)*inv_Shat*inv_Shat*inv_k2_d2; - dr=(1-pow(tanh(r),2.0))*(dr)/tanh(1.0); - dg = dr*(1.+cw2*(6.0*pow(r,5.0)-1.0)); - dfw = dg*glim*(1.-g_6/(g_6+cw3_6)); - val_Jacobian_i[0][0] -= cw1*(dfw*TurbVar_i[0] + 2.0*fw)*TurbVar_i[0]/dist_i_2*Volume; - - } - - // AD::SetPreaccOut(val_residual[0]); - // AD::EndPreacc(); - -} - -CSourcePieceWise_TurbSA_COMP::CSourcePieceWise_TurbSA_COMP(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - rotating_frame = config->GetRotating_Frame(); - - /*--- Spalart-Allmaras closure constants ---*/ - - cv1_3 = pow(7.1, 3.0); - k2 = pow(0.41, 2.0); - cb1 = 0.1355; - cw2 = 0.3; - ct3 = 1.2; - ct4 = 0.5; - cw3_6 = pow(2.0, 6.0); - sigma = 2./3.; - cb2 = 0.622; - cb2_sigma = cb2/sigma; - cw1 = cb1/k2+(1.0+cb2)/sigma; - c5 = 3.5; - -} - -CSourcePieceWise_TurbSA_COMP::~CSourcePieceWise_TurbSA_COMP(void) { } - -void CSourcePieceWise_TurbSA_COMP::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - // AD::StartPreacc(); - // AD::SetPreaccIn(V_i, nDim+6); - // AD::SetPreaccIn(Vorticity_i, nDim); - // AD::SetPreaccIn(StrainMag_i); - // AD::SetPreaccIn(TurbVar_i[0]); - // AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); - // AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); - - if (incompressible) { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+4]; - } - else { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+5]; - } - - val_residual[0] = 0.0; - Production = 0.0; - Destruction = 0.0; - CrossProduction = 0.0; - val_Jacobian_i[0][0] = 0.0; - - /*--- Evaluate Omega ---*/ - - Omega = sqrt(Vorticity_i[0]*Vorticity_i[0] + Vorticity_i[1]*Vorticity_i[1] + Vorticity_i[2]*Vorticity_i[2]); - - /*--- Rotational correction term ---*/ - - if (rotating_frame) { Omega += 2.0*min(0.0, StrainMag_i-Omega); } - - if (dist_i > 1e-10) { - - /*--- Production term ---*/ - - dist_i_2 = dist_i*dist_i; - nu = Laminar_Viscosity_i/Density_i; - Ji = TurbVar_i[0]/nu; - Ji_2 = Ji*Ji; - Ji_3 = Ji_2*Ji; - fv1 = Ji_3/(Ji_3+cv1_3); - fv2 = 1.0 - Ji/(1.0+Ji*fv1); - ft2 = ct3*exp(-ct4*Ji_2); - S = Omega; - inv_k2_d2 = 1.0/(k2*dist_i_2); - - Shat = S + TurbVar_i[0]*fv2*inv_k2_d2; - Shat = max(Shat, 1.0e-10); - inv_Shat = 1.0/Shat; - - /*--- Production term ---*/; - - Production = cb1*Shat*TurbVar_i[0]*Volume; - - /*--- Destruction term ---*/ - - r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); - g = r + cw2*(pow(r,6.0)-r); - g_6 = pow(g,6.0); - glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); - fw = g*glim; - - Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; - - /*--- Diffusion term ---*/ - - norm2_Grad = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; - - CrossProduction = cb2_sigma*norm2_Grad*Volume; - - val_residual[0] = Production - Destruction + CrossProduction; - - /*--- Compressibility Correction term ---*/ - Pressure_i = V_i[nDim+1]; - SoundSpeed_i = sqrt(Pressure_i*Gamma/Density_i); - aux_cc=0; - for(iDim=0;iDimGetKind_Regime() == INCOMPRESSIBLE); - rotating_frame = config->GetRotating_Frame(); - - /*--- Spalart-Allmaras closure constants ---*/ - - cv1_3 = pow(7.1, 3.0); - k2 = pow(0.41, 2.0); - cb1 = 0.1355; - cw2 = 0.3; - ct3 = 1.2; - ct4 = 0.5; - cw3_6 = pow(2.0, 6.0); - sigma = 2./3.; - cb2 = 0.622; - cb2_sigma = cb2/sigma; - cw1 = cb1/k2+(1.0+cb2)/sigma; - -} - -CSourcePieceWise_TurbSA_E_COMP::~CSourcePieceWise_TurbSA_E_COMP(void) { } - -void CSourcePieceWise_TurbSA_E_COMP::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - // AD::StartPreacc(); - // AD::SetPreaccIn(V_i, nDim+6); - // AD::SetPreaccIn(Vorticity_i, nDim); - // AD::SetPreaccIn(StrainMag_i); - // AD::SetPreaccIn(TurbVar_i[0]); - // AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); - // AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); - - if (incompressible) { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+4]; - } - else { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+5]; - } - - val_residual[0] = 0.0; - Production = 0.0; - Destruction = 0.0; - CrossProduction = 0.0; - val_Jacobian_i[0][0] = 0.0; - - /* - From NASA Turbulence model site. http://turbmodels.larc.nasa.gov/spalart.html - This form was developed primarily to improve the near-wall numerical behavior of the model (i.e., the goal was to improve the convergence behavior). The reference is: - Edwards, J. R. and Chandra, S. "Comparison of Eddy Viscosity-Transport Turbulence Models for Three-Dimensional, Shock-Separated Flowfields," AIAA Journal, Vol. 34, No. 4, 1996, pp. 756-763. - In this modificaton Omega is replaced by Strain Rate - */ - - /*--- Evaluate Omega, here Omega is the Strain Rate ---*/ - - Sbar = 0.0; - for(iDim=0;iDim 1e-10) { - - /*--- Production term ---*/ - - dist_i_2 = dist_i*dist_i; - nu = Laminar_Viscosity_i/Density_i; - Ji = TurbVar_i[0]/nu; - Ji_2 = Ji*Ji; - Ji_3 = Ji_2*Ji; - fv1 = Ji_3/(Ji_3+cv1_3); - fv2 = 1.0 - Ji/(1.0+Ji*fv1); - ft2 = ct3*exp(-ct4*Ji_2); - S = Omega; - inv_k2_d2 = 1.0/(k2*dist_i_2); - - Shat = max(S*((1.0/max(Ji,1.0e-16))+fv1),1.0e-16); - - Shat = max(Shat, 1.0e-10); - inv_Shat = 1.0/Shat; - - /*--- Production term ---*/; - - Production = cb1*Shat*TurbVar_i[0]*Volume; - - /*--- Destruction term ---*/ - - r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); - r=tanh(r)/tanh(1.0); - - g = r + cw2*(pow(r,6.0)-r); - g_6 = pow(g,6.0); - glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); - fw = g*glim; - - Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; - - /*--- Diffusion term ---*/ - - norm2_Grad = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; - - CrossProduction = cb2_sigma*norm2_Grad*Volume; - - val_residual[0] = Production - Destruction + CrossProduction; - - /*--- Compressibility Correction term ---*/ - Pressure_i = V_i[nDim+1]; - SoundSpeed_i = sqrt(Pressure_i*Gamma/Density_i); - aux_cc=0; - for(iDim=0;iDimGetKind_Regime() == INCOMPRESSIBLE); - rotating_frame = config->GetRotating_Frame(); - - /*--- Negative Spalart-Allmaras closure constants ---*/ - - cv1_3 = pow(7.1, 3.0); - k2 = pow(0.41, 2.0); - cb1 = 0.1355; - cw2 = 0.3; - ct3 = 1.2; - ct4 = 0.5; - cw3_6 = pow(2.0, 6.0); - sigma = 2./3.; - cb2 = 0.622; - cb2_sigma = cb2/sigma; - cw1 = cb1/k2+(1.0+cb2)/sigma; - -} - -CSourcePieceWise_TurbSA_Neg::~CSourcePieceWise_TurbSA_Neg(void) { - -} - -void CSourcePieceWise_TurbSA_Neg::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - -// AD::StartPreacc(); -// AD::SetPreaccIn(V_i, nDim+6); -// AD::SetPreaccIn(Vorticity_i, nDim); -// AD::SetPreaccIn(StrainMag_i); -// AD::SetPreaccIn(TurbVar_i[0]); -// AD::SetPreaccIn(TurbVar_Grad_i[0], nDim); -// AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); - - if (incompressible) { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+4]; - } - else { - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+5]; - } - - val_residual[0] = 0.0; - Production = 0.0; - Destruction = 0.0; - CrossProduction = 0.0; - val_Jacobian_i[0][0] = 0.0; - - /*--- Evaluate Omega ---*/ - - Omega = sqrt(Vorticity_i[0]*Vorticity_i[0] + Vorticity_i[1]*Vorticity_i[1] + Vorticity_i[2]*Vorticity_i[2]); - - /*--- Rotational correction term ---*/ - - if (rotating_frame) { Omega += 2.0*min(0.0, StrainMag_i-Omega); } - - if (dist_i > 1e-10) { - - if (TurbVar_i[0] > 0.0) { - - /*--- Production term ---*/ - - dist_i_2 = dist_i*dist_i; - nu = Laminar_Viscosity_i/Density_i; - Ji = TurbVar_i[0]/nu; - Ji_2 = Ji*Ji; - Ji_3 = Ji_2*Ji; - fv1 = Ji_3/(Ji_3+cv1_3); - fv2 = 1.0 - Ji/(1.0+Ji*fv1); - ft2 = ct3*exp(-ct4*Ji_2); - S = Omega; - inv_k2_d2 = 1.0/(k2*dist_i_2); - - Shat = S + TurbVar_i[0]*fv2*inv_k2_d2; - Shat = max(Shat, 1.0e-10); - inv_Shat = 1.0/Shat; - - /*--- Production term ---*/; - - // Original SA model - // Production = cb1*(1.0-ft2)*Shat*TurbVar_i[0]*Volume; - - Production = cb1*Shat*TurbVar_i[0]*Volume; - - /*--- Destruction term ---*/ - - r = min(TurbVar_i[0]*inv_Shat*inv_k2_d2,10.0); - g = r + cw2*(pow(r,6.0)-r); - g_6 = pow(g,6.0); - glim = pow((1.0+cw3_6)/(g_6+cw3_6),1.0/6.0); - fw = g*glim; - - Destruction = cw1*fw*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; - - /*--- Diffusion term ---*/ - - norm2_Grad = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; - - CrossProduction = cb2_sigma*norm2_Grad*Volume; - - val_residual[0] = Production - Destruction + CrossProduction; - - /*--- Implicit part, production term ---*/ - - dfv1 = 3.0*Ji_2*cv1_3/(nu*pow(Ji_3+cv1_3,2.)); - dfv2 = -(1/nu-Ji_2*dfv1)/pow(1.+Ji*fv1,2.); - if ( Shat <= 1.0e-10 ) dShat = 0.0; - else dShat = (fv2+TurbVar_i[0]*dfv2)*inv_k2_d2; - val_Jacobian_i[0][0] += cb1*(TurbVar_i[0]*dShat+Shat)*Volume; - - /*--- Implicit part, destruction term ---*/ - - dr = (Shat-TurbVar_i[0]*dShat)*inv_Shat*inv_Shat*inv_k2_d2; - if (r == 10.0) dr = 0.0; - dg = dr*(1.+cw2*(6.0*pow(r,5.0)-1.0)); - dfw = dg*glim*(1.-g_6/(g_6+cw3_6)); - val_Jacobian_i[0][0] -= cw1*(dfw*TurbVar_i[0] + 2.0*fw)*TurbVar_i[0]/dist_i_2*Volume; - - } - - else { - - /*--- Production term ---*/ - - dist_i_2 = dist_i*dist_i; - - /*--- Production term ---*/; - - Production = cb1*(1.0-ct3)*Omega*TurbVar_i[0]*Volume; - - /*--- Destruction term ---*/ - - Destruction = cw1*TurbVar_i[0]*TurbVar_i[0]/dist_i_2*Volume; - - /*--- Diffusion term ---*/ - - norm2_Grad = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - norm2_Grad += TurbVar_Grad_i[0][iDim]*TurbVar_Grad_i[0][iDim]; - - CrossProduction = cb2_sigma*norm2_Grad*Volume; - - val_residual[0] = Production + Destruction + CrossProduction; - - /*--- Implicit part, production term ---*/ - - val_Jacobian_i[0][0] += cb1*(1.0-ct3)*Omega*Volume; - - /*--- Implicit part, destruction term ---*/ - - val_Jacobian_i[0][0] += 2.0*cw1*TurbVar_i[0]/dist_i_2*Volume; - - } - - } - -// AD::SetPreaccOut(val_residual, nVar); -// AD::EndPreacc(); -} - -CUpwSca_TurbSST::CUpwSca_TurbSST(unsigned short val_nDim, - unsigned short val_nVar, - CConfig *config) - : CUpwScalar(val_nDim, val_nVar, config) { -} - -CUpwSca_TurbSST::~CUpwSca_TurbSST(void) { -} - -void CUpwSca_TurbSST::ExtraADPreaccIn() { - - AD::SetPreaccIn(V_i, nDim+3); - AD::SetPreaccIn(V_j, nDim+3); - -} - -void CUpwSca_TurbSST::FinishResidualCalc(su2double *val_residual, - su2double **val_Jacobian_i, - su2double **val_Jacobian_j, - CConfig *config) { - - val_residual[0] = a0*Density_i*TurbVar_i[0]+a1*Density_j*TurbVar_j[0]; - val_residual[1] = a0*Density_i*TurbVar_i[1]+a1*Density_j*TurbVar_j[1]; - - if (implicit) { - val_Jacobian_i[0][0] = a0; val_Jacobian_i[0][1] = 0.0; - val_Jacobian_i[1][0] = 0.0; val_Jacobian_i[1][1] = a0; - - val_Jacobian_j[0][0] = a1; val_Jacobian_j[0][1] = 0.0; - val_Jacobian_j[1][0] = 0.0; val_Jacobian_j[1][1] = a1; - } -} - -CAvgGrad_TurbSST::CAvgGrad_TurbSST(unsigned short val_nDim, - unsigned short val_nVar, - su2double *constants, bool correct_grad, - CConfig *config) - : CAvgGrad_Scalar(val_nDim, val_nVar, correct_grad, config) { - - sigma_k1 = constants[0]; - sigma_om1 = constants[2]; - sigma_k2 = constants[1]; - sigma_om2 = constants[3]; - - F1_i = 0.0; F1_j = 0.0; - diff_kine = 0.0; - diff_omega = 0.0; - -} - -CAvgGrad_TurbSST::~CAvgGrad_TurbSST(void) { -} - -void CAvgGrad_TurbSST::ExtraADPreaccIn() { - AD::SetPreaccIn(F1_i); AD::SetPreaccIn(F1_j); -} - -void CAvgGrad_TurbSST::FinishResidualCalc(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config) { - - su2double sigma_kine_i, sigma_kine_j, sigma_omega_i, sigma_omega_j; - su2double diff_i_kine, diff_i_omega, diff_j_kine, diff_j_omega; - - /*--- Compute the blended constant for the viscous terms ---*/ - sigma_kine_i = F1_i*sigma_k1 + (1.0 - F1_i)*sigma_k2; - sigma_kine_j = F1_j*sigma_k1 + (1.0 - F1_j)*sigma_k2; - sigma_omega_i = F1_i*sigma_om1 + (1.0 - F1_i)*sigma_om2; - sigma_omega_j = F1_j*sigma_om1 + (1.0 - F1_j)*sigma_om2; - - /*--- Compute mean effective viscosity ---*/ - diff_i_kine = Laminar_Viscosity_i + sigma_kine_i*Eddy_Viscosity_i; - diff_j_kine = Laminar_Viscosity_j + sigma_kine_j*Eddy_Viscosity_j; - diff_i_omega = Laminar_Viscosity_i + sigma_omega_i*Eddy_Viscosity_i; - diff_j_omega = Laminar_Viscosity_j + sigma_omega_j*Eddy_Viscosity_j; - - diff_kine = 0.5*(diff_i_kine + diff_j_kine); // Could instead use weighted average! - diff_omega = 0.5*(diff_i_omega + diff_j_omega); - - val_residual[0] = diff_kine*Proj_Mean_GradTurbVar[0]; - val_residual[1] = diff_omega*Proj_Mean_GradTurbVar[1]; - - /*--- For Jacobians -> Use of TSL approx. to compute derivatives of the gradients ---*/ - if (implicit) { - Jacobian_i[0][0] = -diff_kine*proj_vector_ij/Density_i; Jacobian_i[0][1] = 0.0; - Jacobian_i[1][0] = 0.0; Jacobian_i[1][1] = -diff_omega*proj_vector_ij/Density_i; - - Jacobian_j[0][0] = diff_kine*proj_vector_ij/Density_j; Jacobian_j[0][1] = 0.0; - Jacobian_j[1][0] = 0.0; Jacobian_j[1][1] = diff_omega*proj_vector_ij/Density_j; - } - -} - -CSourcePieceWise_TurbSST::CSourcePieceWise_TurbSST(unsigned short val_nDim, unsigned short val_nVar, su2double *constants, - su2double val_kine_Inf, su2double val_omega_Inf, CConfig *config) - : CNumerics(val_nDim, val_nVar, config) { - - incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - sustaining_terms = (config->GetKind_Turb_Model() == SST_SUST); - - /*--- Closure constants ---*/ - beta_star = constants[6]; - sigma_omega_1 = constants[2]; - sigma_omega_2 = constants[3]; - beta_1 = constants[4]; - beta_2 = constants[5]; - alfa_1 = constants[8]; - alfa_2 = constants[9]; - a1 = constants[7]; - - /*--- Set the ambient values of k and omega to the free stream values. ---*/ - kAmb = val_kine_Inf; - omegaAmb = val_omega_Inf; -} - -CSourcePieceWise_TurbSST::~CSourcePieceWise_TurbSST(void) { } - -void CSourcePieceWise_TurbSST::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - AD::StartPreacc(); - AD::SetPreaccIn(StrainMag_i); - AD::SetPreaccIn(TurbVar_i, nVar); - AD::SetPreaccIn(TurbVar_Grad_i, nVar, nDim); - AD::SetPreaccIn(Volume); AD::SetPreaccIn(dist_i); - AD::SetPreaccIn(F1_i); AD::SetPreaccIn(F2_i); AD::SetPreaccIn(CDkw_i); - AD::SetPreaccIn(PrimVar_Grad_i, nDim+1, nDim); - - unsigned short iDim; - su2double alfa_blended, beta_blended; - su2double diverg, pk, pw, zeta; - - if (incompressible) { - AD::SetPreaccIn(V_i, nDim+6); - - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+4]; - Eddy_Viscosity_i = V_i[nDim+5]; - } - else { - AD::SetPreaccIn(V_i, nDim+7); - - Density_i = V_i[nDim+2]; - Laminar_Viscosity_i = V_i[nDim+5]; - Eddy_Viscosity_i = V_i[nDim+6]; - } - - val_residual[0] = 0.0; val_residual[1] = 0.0; - val_Jacobian_i[0][0] = 0.0; val_Jacobian_i[0][1] = 0.0; - val_Jacobian_i[1][0] = 0.0; val_Jacobian_i[1][1] = 0.0; - - /*--- Computation of blended constants for the source terms---*/ - - alfa_blended = F1_i*alfa_1 + (1.0 - F1_i)*alfa_2; - beta_blended = F1_i*beta_1 + (1.0 - F1_i)*beta_2; - - if (dist_i > 1e-10) { - - /*--- Production ---*/ - - diverg = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - diverg += PrimVar_Grad_i[iDim+1][iDim]; - - /* if using UQ methodolgy, calculate production using perturbed Reynolds stress matrix */ - - if (using_uq){ - SetReynoldsStressMatrix(TurbVar_i[0]); - SetPerturbedRSM(TurbVar_i[0], config); - SetPerturbedStrainMag(TurbVar_i[0]); - pk = Eddy_Viscosity_i*PerturbedStrainMag*PerturbedStrainMag - - 2.0/3.0*Density_i*TurbVar_i[0]*diverg; - } - else { - pk = Eddy_Viscosity_i*StrainMag_i*StrainMag_i - 2.0/3.0*Density_i*TurbVar_i[0]*diverg; - } - - - pk = min(pk,20.0*beta_star*Density_i*TurbVar_i[1]*TurbVar_i[0]); - pk = max(pk,0.0); - - zeta = max(TurbVar_i[1], StrainMag_i*F2_i/a1); - - /* if using UQ methodolgy, calculate production using perturbed Reynolds stress matrix */ - - if (using_uq){ - pw = PerturbedStrainMag * PerturbedStrainMag - 2.0/3.0*zeta*diverg; - } - else { - pw = StrainMag_i*StrainMag_i - 2.0/3.0*zeta*diverg; - } - pw = alfa_blended*Density_i*max(pw,0.0); - - /*--- Sustaining terms, if desired. Note that if the production terms are - larger equal than the sustaining terms, the original formulation is - obtained again. This is in contrast to the version in literature - where the sustaining terms are simply added. This latter approach could - lead to problems for very big values of the free-stream turbulence - intensity. ---*/ - - if ( sustaining_terms ) { - const su2double sust_k = beta_star*Density_i*kAmb*omegaAmb; - const su2double sust_w = beta_blended*Density_i*omegaAmb*omegaAmb; - - pk = max(pk, sust_k); - pw = max(pw, sust_w); - } - - /*--- Add the production terms to the residuals. ---*/ - - val_residual[0] += pk*Volume; - val_residual[1] += pw*Volume; - - /*--- Dissipation ---*/ - - val_residual[0] -= beta_star*Density_i*TurbVar_i[1]*TurbVar_i[0]*Volume; - val_residual[1] -= beta_blended*Density_i*TurbVar_i[1]*TurbVar_i[1]*Volume; - - /*--- Cross diffusion ---*/ - - val_residual[1] += (1.0 - F1_i)*CDkw_i*Volume; - - /*--- Implicit part ---*/ - - val_Jacobian_i[0][0] = -beta_star*TurbVar_i[1]*Volume; - val_Jacobian_i[0][1] = -beta_star*TurbVar_i[0]*Volume; - val_Jacobian_i[1][0] = 0.0; - val_Jacobian_i[1][1] = -2.0*beta_blended*TurbVar_i[1]*Volume; - } - - AD::SetPreaccOut(val_residual, nVar); - AD::EndPreacc(); - -} - -void CSourcePieceWise_TurbSST::GetMeanRateOfStrainMatrix(su2double **S_ij) -{ - /* --- Calculate the rate of strain tensor, using mean velocity gradients --- */ - - if (nDim == 3){ - S_ij[0][0] = PrimVar_Grad_i[1][0]; - S_ij[1][1] = PrimVar_Grad_i[2][1]; - S_ij[2][2] = PrimVar_Grad_i[3][2]; - S_ij[0][1] = 0.5 * (PrimVar_Grad_i[1][1] + PrimVar_Grad_i[2][0]); - S_ij[0][2] = 0.5 * (PrimVar_Grad_i[1][2] + PrimVar_Grad_i[3][0]); - S_ij[1][2] = 0.5 * (PrimVar_Grad_i[2][2] + PrimVar_Grad_i[3][1]); - S_ij[1][0] = S_ij[0][1]; - S_ij[2][1] = S_ij[1][2]; - S_ij[2][0] = S_ij[0][2]; - } - else { - S_ij[0][0] = PrimVar_Grad_i[1][0]; - S_ij[1][1] = PrimVar_Grad_i[2][1]; - S_ij[2][2] = 0.0; - S_ij[0][1] = 0.5 * (PrimVar_Grad_i[1][1] + PrimVar_Grad_i[2][0]); - S_ij[0][2] = 0.0; - S_ij[1][2] = 0.0; - S_ij[1][0] = S_ij[0][1]; - S_ij[2][1] = S_ij[1][2]; - S_ij[2][0] = S_ij[0][2]; - - } -} - -void CSourcePieceWise_TurbSST::SetReynoldsStressMatrix(su2double turb_ke){ - unsigned short iDim, jDim; - su2double **S_ij = new su2double* [3]; - su2double divVel = 0; - su2double TWO3 = 2.0/3.0; - - - - for (iDim = 0; iDim < 3; iDim++){ - S_ij[iDim] = new su2double [3]; - } - - GetMeanRateOfStrainMatrix(S_ij); - - /* --- Using rate of strain matrix, calculate Reynolds stress tensor --- */ - - for (iDim = 0; iDim < 3; iDim++){ - divVel += S_ij[iDim][iDim]; - } - - for (iDim = 0; iDim < 3; iDim++){ - for (jDim = 0; jDim < 3; jDim++){ - MeanReynoldsStress[iDim][jDim] = TWO3 * turb_ke * delta3[iDim][jDim] - - Eddy_Viscosity_i / Density_i * (2 * S_ij[iDim][jDim] - TWO3 * divVel * delta3[iDim][jDim]); - } - } - - for (iDim = 0; iDim < 3; iDim++) - delete [] S_ij[iDim]; - delete [] S_ij; -} - -void CSourcePieceWise_TurbSST::SetPerturbedRSM(su2double turb_ke, CConfig *config){ - - unsigned short iDim,jDim; - - /* --- Calculate anisotropic part of Reynolds Stress tensor --- */ - - for (iDim = 0; iDim< 3; iDim++){ - for (jDim = 0; jDim < 3; jDim++){ - A_ij[iDim][jDim] = .5 * MeanReynoldsStress[iDim][jDim] / turb_ke - delta3[iDim][jDim] / 3.0; - Eig_Vec[iDim][jDim] = A_ij[iDim][jDim]; - } - } - - /* --- Get ordered eigenvectors and eigenvalues of A_ij --- */ - - EigenDecomposition(A_ij, Eig_Vec, Eig_Val, 3); - - /* compute convex combination coefficients */ - su2double c1c = Eig_Val[2] - Eig_Val[1]; - su2double c2c = 2.0 * (Eig_Val[1] - Eig_Val[0]); - su2double c3c = 3.0 * Eig_Val[0] + 1.0; - - /* define barycentric traingle corner points */ - Corners[0][0] = 1.0; - Corners[0][1] = 0.0; - Corners[1][0] = 0.0; - Corners[1][1] = 0.0; - Corners[2][0] = 0.5; - Corners[2][1] = 0.866025; - - /* define barycentric coordinates */ - Barycentric_Coord[0] = Corners[0][0] * c1c + Corners[1][0] * c2c + Corners[2][0] * c3c; - Barycentric_Coord[1] = Corners[0][1] * c1c + Corners[1][1] * c2c + Corners[2][1] * c3c; - - if (Eig_Val_Comp == 1) { - /* 1C turbulence */ - New_Coord[0] = Corners[0][0]; - New_Coord[1] = Corners[0][1]; - } - else if (Eig_Val_Comp == 2) { - /* 2C turbulence */ - New_Coord[0] = Corners[1][0]; - New_Coord[1] = Corners[1][1]; - } - else if (Eig_Val_Comp == 3) { - /* 3C turbulence */ - New_Coord[0] = Corners[2][0]; - New_Coord[1] = Corners[2][1]; - } - else { - /* 2C turbulence */ - New_Coord[0] = Corners[1][0]; - New_Coord[1] = Corners[1][1]; - } - /* calculate perturbed barycentric coordinates */ - - Barycentric_Coord[0] = Barycentric_Coord[0] + (uq_delta_b) * (New_Coord[0] - Barycentric_Coord[0]); - Barycentric_Coord[1] = Barycentric_Coord[1] + (uq_delta_b) * (New_Coord[1] - Barycentric_Coord[1]); - - /* rebuild c1c,c2c,c3c based on new barycentric coordinates */ - c3c = Barycentric_Coord[1] / Corners[2][1]; - c1c = Barycentric_Coord[0] - Corners[2][0] * c3c; - c2c = 1 - c1c - c3c; - - /* build new anisotropy eigenvalues */ - Eig_Val[0] = (c3c - 1) / 3.0; - Eig_Val[1] = 0.5 *c2c + Eig_Val[0]; - Eig_Val[2] = c1c + Eig_Val[1]; - - /* permute eigenvectors if required */ - if (uq_permute) { - for (iDim=0; iDim<3; iDim++) { - for (jDim=0; jDim<3; jDim++) { - New_Eig_Vec[iDim][jDim] = Eig_Vec[2-iDim][jDim]; - } - } - } - - else { - for (iDim=0; iDim<3; iDim++) { - for (jDim=0; jDim<3; jDim++) { - New_Eig_Vec[iDim][jDim] = Eig_Vec[iDim][jDim]; - } - } - } - - EigenRecomposition(newA_ij, New_Eig_Vec, Eig_Val, 3); - - /* compute perturbed Reynolds stress matrix; use under-relaxation factor (urlx)*/ - for (iDim = 0; iDim< 3; iDim++){ - for (jDim = 0; jDim < 3; jDim++){ - MeanPerturbedRSM[iDim][jDim] = 2.0 * turb_ke * (newA_ij[iDim][jDim] + 1.0/3.0 * delta3[iDim][jDim]); - MeanPerturbedRSM[iDim][jDim] = MeanReynoldsStress[iDim][jDim] + - uq_urlx*(MeanPerturbedRSM[iDim][jDim] - MeanReynoldsStress[iDim][jDim]); - } - } - -} - -void CSourcePieceWise_TurbSST::SetPerturbedStrainMag(su2double turb_ke){ - unsigned short iDim, jDim; - PerturbedStrainMag = 0; - su2double **StrainRate = new su2double* [nDim]; - for (iDim= 0; iDim< nDim; iDim++){ - StrainRate[iDim] = new su2double [nDim]; - } - - /* compute perturbed strain rate tensor */ - - for (iDim = 0; iDim < nDim; iDim++){ - for (jDim =0; jDim < nDim; jDim++){ - StrainRate[iDim][jDim] = MeanPerturbedRSM[iDim][jDim] - - TWO3 * turb_ke * delta[iDim][jDim]; - StrainRate[iDim][jDim] = - StrainRate[iDim][jDim] * Density_i / (2 * Eddy_Viscosity_i); - } - } - - /*--- Add diagonal part ---*/ - - for (iDim = 0; iDim < nDim; iDim++) { - PerturbedStrainMag += pow(StrainRate[iDim][iDim], 2.0); - } - - /*--- Add off diagonals ---*/ - - PerturbedStrainMag += 2.0*pow(StrainRate[1][0], 2.0); - - if (nDim == 3) { - PerturbedStrainMag += 2.0*pow(StrainRate[0][2], 2.0); - PerturbedStrainMag += 2.0*pow(StrainRate[1][2], 2.0); - } - - PerturbedStrainMag = sqrt(2.0*PerturbedStrainMag); - - for (iDim= 0; iDim< nDim; iDim++){ - delete [] StrainRate[iDim]; - } - - delete [] StrainRate; -} diff --git a/SU2_CFD/src/numerics_template.cpp b/SU2_CFD/src/numerics_template.cpp deleted file mode 100644 index 1f66f32f895d..000000000000 --- a/SU2_CFD/src/numerics_template.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/*! - * \file numerics_template.cpp - * \brief This file contains all the convective term discretization. - * \author F. Palacios - * \version 7.0.1 "Blackbird" - * - * SU2 Project Website: https://su2code.github.io - * - * The SU2 Project is maintained by the SU2 Foundation - * (http://su2foundation.org) - * - * Copyright 2012-2019, SU2 Contributors (cf. AUTHORS.md) - * - * SU2 is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * SU2 is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with SU2. If not, see . - */ - - -#include "../include/numerics_structure.hpp" -#include - -CConvective_Template::CConvective_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { - - - implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - Diff_U = new su2double [nVar]; - Velocity_i = new su2double [nDim]; - Velocity_j = new su2double [nDim]; - RoeVelocity = new su2double [nDim]; - delta_vel = new su2double [nDim]; - delta_wave = new su2double [nVar]; - ProjFlux_i = new su2double [nVar]; - ProjFlux_j = new su2double [nVar]; - Lambda = new su2double [nVar]; - Epsilon = new su2double [nVar]; - P_Tensor = new su2double* [nVar]; - invP_Tensor = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar++) { - P_Tensor[iVar] = new su2double [nVar]; - invP_Tensor[iVar] = new su2double [nVar]; - } -} - -CConvective_Template::~CConvective_Template(void) { - unsigned short iVar; - - delete [] Diff_U; - delete [] Velocity_i; - delete [] Velocity_j; - delete [] RoeVelocity; - delete [] delta_vel; - delete [] delta_wave; - delete [] ProjFlux_i; - delete [] ProjFlux_j; - delete [] Lambda; - delete [] Epsilon; - for (iVar = 0; iVar < nVar; iVar++) { - delete [] P_Tensor[iVar]; - delete [] invP_Tensor[iVar]; - } - delete [] P_Tensor; - delete [] invP_Tensor; -} - -void CConvective_Template::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, su2double **val_Jacobian_j, CConfig *config) { - - Area = 0; - for (iDim = 0; iDim < nDim; iDim++) - /*!< \brief Normal: Normal vector, it norm is the area of the face. */ - Area += Normal[iDim]*Normal[iDim]; - Area = sqrt(Area); /*! Area of the face*/ - - for (iDim = 0; iDim < nDim; iDim++) - UnitNormal[iDim] = Normal[iDim]/Area; /* ! Unit Normal*/ - - /*--- Point i, Needs to recompute SoundSpeed / Pressure / Enthalpy in case of 2nd order reconstruction ---*/ - Density_i = U_i[0]; - sq_vel = 0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_i[iDim] = U_i[iDim+1] / Density_i; - sq_vel += Velocity_i[iDim]*Velocity_i[iDim]; - } - Energy_i = U_i[nDim+1] / Density_i; - SoundSpeed_i = sqrt(Gamma*Gamma_Minus_One*(Energy_i-0.5*sq_vel)); - Pressure_i = (SoundSpeed_i * SoundSpeed_i * Density_i) / Gamma; - Enthalpy_i = (U_i[nDim+1] + Pressure_i) / Density_i; - - /*--- Point j, Needs to recompute SoundSpeed / Pressure / Enthalpy in case of 2nd order reconstruction ---*/ - Density_j = U_j[0]; - sq_vel = 0; - for (iDim = 0; iDim < nDim; iDim++) { - Velocity_j[iDim] = U_j[iDim+1] / Density_j; - sq_vel += Velocity_j[iDim]*Velocity_j[iDim]; - } - Energy_j = U_j[nDim+1] / Density_j; - SoundSpeed_j = sqrt(Gamma*Gamma_Minus_One*(Energy_j-0.5*sq_vel)); - Pressure_j = (SoundSpeed_j * SoundSpeed_j * Density_j) / Gamma; - Enthalpy_j = (U_j[nDim+1] + Pressure_j) / Density_j; - - /*--- Mean Roe variables iPoint and jPoint ---*/ - R = sqrt(Density_j/Density_i); - RoeDensity = R*Density_i; - sq_vel = 0; - for (iDim = 0; iDim < nDim; iDim++) { - RoeVelocity[iDim] = (R*Velocity_j[iDim]+Velocity_i[iDim])/(R+1); - sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; - } - RoeEnthalpy = (R*Enthalpy_j+Enthalpy_i)/(R+1); - RoeSoundSpeed = sqrt((Gamma-1)*(RoeEnthalpy-0.5*sq_vel)); - - /*--- Compute ProjFlux_i ---*/ - GetInviscidProjFlux(&Density_i, Velocity_i, &Pressure_i, &Enthalpy_i, Normal, ProjFlux_i); - - /*--- Compute ProjFlux_j ---*/ - GetInviscidProjFlux(&Density_j, Velocity_j, &Pressure_j, &Enthalpy_j, Normal, ProjFlux_j); - - /*--- Compute P and Lambda (do it with the Normal) ---*/ - GetPMatrix(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, P_Tensor); - - ProjVelocity = 0.0; ProjVelocity_i = 0.0; ProjVelocity_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjVelocity += RoeVelocity[iDim]*UnitNormal[iDim]; - ProjVelocity_i += Velocity_i[iDim]*UnitNormal[iDim]; - ProjVelocity_j += Velocity_j[iDim]*UnitNormal[iDim]; - } - - /*--- Flow eigenvalues and Entropy correctors ---*/ - for (iDim = 0; iDim < nDim; iDim++) { - Lambda[iDim] = ProjVelocity; - Epsilon[iDim] = 4.0*max(0.0, max(Lambda[iDim]-ProjVelocity_i, ProjVelocity_j-Lambda[iDim])); - } - Lambda[nVar-2] = ProjVelocity + RoeSoundSpeed; - Epsilon[nVar-2] = 4.0*max(0.0, max(Lambda[nVar-2]-(ProjVelocity_i+SoundSpeed_i),(ProjVelocity_j+SoundSpeed_j)-Lambda[nVar-2])); - Lambda[nVar-1] = ProjVelocity - RoeSoundSpeed; - Epsilon[nVar-1] = 4.0*max(0.0, max(Lambda[nVar-1]-(ProjVelocity_i-SoundSpeed_i),(ProjVelocity_j-SoundSpeed_j)-Lambda[nVar-1])); - - /*--- Entropy correction ---*/ - for (iVar = 0; iVar < nVar; iVar++) - if ( fabs(Lambda[iVar]) < Epsilon[iVar] ) - Lambda[iVar] = (Lambda[iVar]*Lambda[iVar] + Epsilon[iVar]*Epsilon[iVar])/(2.0*Epsilon[iVar]); - else - Lambda[iVar] = fabs(Lambda[iVar]); - - - if (!implicit) { - /*--- Compute wave amplitudes (characteristics) ---*/ - proj_delta_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - delta_vel[iDim] = Velocity_j[iDim] - Velocity_i[iDim]; - proj_delta_vel += delta_vel[iDim]*Normal[iDim]; - } - delta_p = Pressure_j - Pressure_i; - delta_rho = Density_j - Density_i; - proj_delta_vel = proj_delta_vel/Area; - - if (nDim == 3) { - delta_wave[0] = delta_rho - delta_p/(RoeSoundSpeed*RoeSoundSpeed); - delta_wave[1] = UnitNormal[0]*delta_vel[2]-UnitNormal[2]*delta_vel[0]; - delta_wave[2] = UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]; - delta_wave[3] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - delta_wave[4] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - } - else { - delta_wave[0] = delta_rho - delta_p/(RoeSoundSpeed*RoeSoundSpeed); - delta_wave[1] = UnitNormal[1]*delta_vel[0]-UnitNormal[0]*delta_vel[1]; - delta_wave[2] = proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - delta_wave[3] = -proj_delta_vel + delta_p/(RoeDensity*RoeSoundSpeed); - } - - /*--- Roe's Flux approximation ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = 0.5*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); - for (jVar = 0; jVar < nVar; jVar++) - val_residual[iVar] -= 0.5*Lambda[jVar]*delta_wave[jVar]*P_Tensor[iVar][jVar]*Area; - } - } - else { - - /*--- Compute inverse P ---*/ - GetPMatrix_inv(&RoeDensity, RoeVelocity, &RoeSoundSpeed, UnitNormal, invP_Tensor); - - /*--- Jacobias of the inviscid flux, scale = 0.5 because val_resconv ~ 0.5*(fc_i+fc_j)*Normal ---*/ - GetInviscidProjJac(Velocity_i, &Energy_i, Normal, 0.5, val_Jacobian_i); - GetInviscidProjJac(Velocity_j, &Energy_j, Normal, 0.5, val_Jacobian_j); - - /*--- Diference variables iPoint and jPoint ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Diff_U[iVar] = U_j[iVar]-U_i[iVar]; - - /*--- Roe's Flux approximation ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - val_residual[iVar] = 0.5*(ProjFlux_i[iVar]+ProjFlux_j[iVar]); - for (jVar = 0; jVar < nVar; jVar++) { - Proj_ModJac_Tensor_ij = 0.0; - /*--- Compute |Proj_ModJac_Tensor| = P x |Lambda| x inverse P ---*/ - for (kVar = 0; kVar < nVar; kVar++) - Proj_ModJac_Tensor_ij += P_Tensor[iVar][kVar]*Lambda[kVar]*invP_Tensor[kVar][jVar]; - val_residual[iVar] -= 0.5*Proj_ModJac_Tensor_ij*Diff_U[jVar]*Area; - val_Jacobian_i[iVar][jVar] += 0.5*Proj_ModJac_Tensor_ij*Area; - val_Jacobian_j[iVar][jVar] -= 0.5*Proj_ModJac_Tensor_ij*Area; - } - } - } -} - -CSource_Template::CSource_Template(unsigned short val_nDim, unsigned short val_nVar, - CConfig *config) : CNumerics(val_nDim, val_nVar, config) {} - -CSource_Template::~CSource_Template(void) { - -} - -void CSource_Template::ComputeResidual(su2double *val_residual, su2double **val_Jacobian_i, CConfig *config) {} - -CViscous_Template::CViscous_Template(unsigned short val_nDim, unsigned short val_nVar, CConfig *config) : CNumerics(val_nDim, val_nVar, config) { } - -CViscous_Template::~CViscous_Template(void) { } - -void CViscous_Template::ComputeResidual(su2double *val_residual, su2double **Jacobian_i, su2double **Jacobian_j, CConfig *config) { } diff --git a/SU2_CFD/src/output/CFlowCompOutput.cpp b/SU2_CFD/src/output/CFlowCompOutput.cpp index 73fe45157faa..3adb4f7b8f1c 100644 --- a/SU2_CFD/src/output/CFlowCompOutput.cpp +++ b/SU2_CFD/src/output/CFlowCompOutput.cpp @@ -484,24 +484,24 @@ void CFlowCompOutput::LoadVolumeData(CConfig *config, CGeometry *geometry, CSolv SetVolumeOutputValue("INTERMITTENCY", iPoint, Node_Turb->GetGammaBC(iPoint)); } - SetVolumeOutputValue("RES_DENSITY", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 0)); - SetVolumeOutputValue("RES_MOMENTUM-X", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 1)); - SetVolumeOutputValue("RES_MOMENTUM-Y", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 2)); + SetVolumeOutputValue("RES_DENSITY", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 0)); + SetVolumeOutputValue("RES_MOMENTUM-X", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 1)); + SetVolumeOutputValue("RES_MOMENTUM-Y", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 2)); if (nDim == 3){ - SetVolumeOutputValue("RES_MOMENTUM-Z", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 3)); - SetVolumeOutputValue("RES_ENERGY", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 4)); + SetVolumeOutputValue("RES_MOMENTUM-Z", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 3)); + SetVolumeOutputValue("RES_ENERGY", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 4)); } else { - SetVolumeOutputValue("RES_ENERGY", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 3)); + SetVolumeOutputValue("RES_ENERGY", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 3)); } switch(config->GetKind_Turb_Model()){ case SST: case SST_SUST: - SetVolumeOutputValue("RES_TKE", iPoint, solver[TURB_SOL]->LinSysRes.GetBlock(iPoint, 0)); - SetVolumeOutputValue("RES_DISSIPATION", iPoint, solver[TURB_SOL]->LinSysRes.GetBlock(iPoint, 1)); + SetVolumeOutputValue("RES_TKE", iPoint, solver[TURB_SOL]->LinSysRes(iPoint, 0)); + SetVolumeOutputValue("RES_DISSIPATION", iPoint, solver[TURB_SOL]->LinSysRes(iPoint, 1)); break; case SA: case SA_COMP: case SA_E: case SA_E_COMP: case SA_NEG: - SetVolumeOutputValue("RES_NU_TILDE", iPoint, solver[TURB_SOL]->LinSysRes.GetBlock(iPoint, 0)); + SetVolumeOutputValue("RES_NU_TILDE", iPoint, solver[TURB_SOL]->LinSysRes(iPoint, 0)); break; case NONE: break; diff --git a/SU2_CFD/src/output/CFlowIncOutput.cpp b/SU2_CFD/src/output/CFlowIncOutput.cpp index 016ea7c5cf6d..9c1581e326e9 100644 --- a/SU2_CFD/src/output/CFlowIncOutput.cpp +++ b/SU2_CFD/src/output/CFlowIncOutput.cpp @@ -518,24 +518,24 @@ void CFlowIncOutput::LoadVolumeData(CConfig *config, CGeometry *geometry, CSolve SetVolumeOutputValue("INTERMITTENCY", iPoint, Node_Turb->GetGammaBC(iPoint)); } - SetVolumeOutputValue("RES_PRESSURE", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 0)); - SetVolumeOutputValue("RES_VELOCITY-X", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 1)); - SetVolumeOutputValue("RES_VELOCITY-Y", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 2)); + SetVolumeOutputValue("RES_PRESSURE", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 0)); + SetVolumeOutputValue("RES_VELOCITY-X", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 1)); + SetVolumeOutputValue("RES_VELOCITY-Y", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 2)); if (nDim == 3){ - SetVolumeOutputValue("RES_VELOCITY-Z", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 3)); - SetVolumeOutputValue("RES_TEMPERATURE", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 4)); + SetVolumeOutputValue("RES_VELOCITY-Z", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 3)); + SetVolumeOutputValue("RES_TEMPERATURE", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 4)); } else { - SetVolumeOutputValue("RES_TEMPERATURE", iPoint, solver[FLOW_SOL]->LinSysRes.GetBlock(iPoint, 3)); + SetVolumeOutputValue("RES_TEMPERATURE", iPoint, solver[FLOW_SOL]->LinSysRes(iPoint, 3)); } switch(config->GetKind_Turb_Model()){ case SST: case SST_SUST: - SetVolumeOutputValue("RES_TKE", iPoint, solver[TURB_SOL]->LinSysRes.GetBlock(iPoint, 0)); - SetVolumeOutputValue("RES_DISSIPATION", iPoint, solver[TURB_SOL]->LinSysRes.GetBlock(iPoint, 1)); + SetVolumeOutputValue("RES_TKE", iPoint, solver[TURB_SOL]->LinSysRes(iPoint, 0)); + SetVolumeOutputValue("RES_DISSIPATION", iPoint, solver[TURB_SOL]->LinSysRes(iPoint, 1)); break; case SA: case SA_COMP: case SA_E: case SA_E_COMP: case SA_NEG: - SetVolumeOutputValue("RES_NU_TILDE", iPoint, solver[TURB_SOL]->LinSysRes.GetBlock(iPoint, 0)); + SetVolumeOutputValue("RES_NU_TILDE", iPoint, solver[TURB_SOL]->LinSysRes(iPoint, 0)); break; case NONE: break; diff --git a/SU2_CFD/src/output/CHeatOutput.cpp b/SU2_CFD/src/output/CHeatOutput.cpp index c384d3e108b7..106791abbc76 100644 --- a/SU2_CFD/src/output/CHeatOutput.cpp +++ b/SU2_CFD/src/output/CHeatOutput.cpp @@ -147,7 +147,7 @@ void CHeatOutput::LoadVolumeData(CConfig *config, CGeometry *geometry, CSolver * SetVolumeOutputValue("TEMPERATURE", iPoint, Node_Heat->GetSolution(iPoint, 0)); // Residuals - SetVolumeOutputValue("RES_TEMPERATURE", iPoint, solver[HEAT_SOL]->LinSysRes.GetBlock(iPoint, 0)); + SetVolumeOutputValue("RES_TEMPERATURE", iPoint, solver[HEAT_SOL]->LinSysRes(iPoint, 0)); } diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp index a4d29610ed5b..dae30caac104 100644 --- a/SU2_CFD/src/output/COutput.cpp +++ b/SU2_CFD/src/output/COutput.cpp @@ -2029,7 +2029,7 @@ void COutput::LoadCommonHistoryData(CConfig *config){ /*--- Update the current time only if the time iteration has changed ---*/ - if (SU2_TYPE::Int(GetHistoryFieldValue("TIME_ITER")) != curTimeIter){ + if (SU2_TYPE::Int(GetHistoryFieldValue("TIME_ITER")) != static_cast(curTimeIter)) { SetHistoryOutputValue("CUR_TIME", GetHistoryFieldValue("CUR_TIME") + GetHistoryFieldValue("TIME_STEP")); } diff --git a/SU2_CFD/src/output/filewriter/CParaviewXMLFileWriter.cpp b/SU2_CFD/src/output/filewriter/CParaviewXMLFileWriter.cpp index 77b8b60947b1..cafeb7f2b35d 100644 --- a/SU2_CFD/src/output/filewriter/CParaviewXMLFileWriter.cpp +++ b/SU2_CFD/src/output/filewriter/CParaviewXMLFileWriter.cpp @@ -333,7 +333,7 @@ void CParaviewXMLFileWriter::WriteDataArray(void* data, VTKDatatype type, unsign int totalByteSize, byteSize; std::string typeStr; - unsigned long typeSize; + unsigned long typeSize = 0; GetTypeInfo(type, typeStr, typeSize); @@ -375,14 +375,10 @@ void CParaviewXMLFileWriter::AddDataArray(VTKDatatype type, string name, string offsetStr = ss.str(); std::string typeStr; - unsigned long typeSize, byteSize, totalByteSize; + unsigned long typeSize = 0, totalByteSize; GetTypeInfo(type, typeStr, typeSize); - /*--- Compute the size of the data to write in bytes ---*/ - - byteSize = arraySize*typeSize; - /*--- Total data size ---*/ totalByteSize = globalSize*typeSize; diff --git a/SU2_CFD/src/output/output_structure_legacy.cpp b/SU2_CFD/src/output/output_structure_legacy.cpp index 41aa2f31875f..0017dfa4c704 100644 --- a/SU2_CFD/src/output/output_structure_legacy.cpp +++ b/SU2_CFD/src/output/output_structure_legacy.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -37,9 +37,9 @@ COutputLegacy::COutputLegacy(CConfig *config) { size = SU2_MPI::GetSize(); unsigned short iDim, iZone, iSpan, iMarker; - + /*--- Initialize point and connectivity counters to zero. ---*/ - + nGlobal_Poin = 0; nSurf_Poin = 0; nGlobal_Elem = 0; @@ -55,15 +55,15 @@ COutputLegacy::COutputLegacy(CConfig *config) { nGlobal_BoundQuad = 0; /*--- Initialize pointers to NULL ---*/ - + Coords = NULL; Conn_Line = NULL; Conn_BoundTria = NULL; Conn_BoundQuad = NULL; Conn_Tria = NULL; Conn_Quad = NULL; Conn_Tetr = NULL; Conn_Hexa = NULL; Conn_Pris = NULL; Conn_Pyra = NULL; Data = NULL; - + /*--- Initialize parallel pointers to NULL ---*/ - + nGlobal_Poin_Par = 0; nGlobal_Elem_Par = 0; nGlobal_Surf_Poin = 0; @@ -79,13 +79,13 @@ COutputLegacy::COutputLegacy(CConfig *config) { nParallel_Line = 0; nParallel_BoundTria = 0; nParallel_BoundQuad = 0; - + /*--- Initialize pointers to NULL ---*/ - + Conn_BoundLine_Par = NULL; Conn_BoundTria_Par = NULL; Conn_BoundQuad_Par = NULL; Conn_Tria_Par = NULL; Conn_Quad_Par = NULL; Conn_Tetr_Par = NULL; Conn_Hexa_Par = NULL; Conn_Pris_Par = NULL; Conn_Pyra_Par = NULL; - + Local_Data = NULL; Local_Data_Copy = NULL; Parallel_Data = NULL; @@ -106,27 +106,27 @@ COutputLegacy::COutputLegacy(CConfig *config) { nPointCumulative = NULL; /*--- Initialize CGNS write flag ---*/ - + wrote_base_file = false; - + /*--- Initialize CGNS write flag ---*/ - + wrote_CGNS_base = false; - + /*--- Initialize Tecplot surface flag ---*/ - + wrote_surf_file = false; - + /*--- Initialize Paraview write flag ---*/ - + wrote_Paraview_base = false; - + /*--- Initialize residual ---*/ - + RhoRes_New = EPS; RhoRes_Old = new su2double[config->GetnZone()]; for (iZone = 0; iZone < config->GetnZone(); iZone++) RhoRes_Old[iZone] = EPS; - + wrote_Paraview_base = false; /*--- Initialize turbo flag ---*/ @@ -433,25 +433,25 @@ COutputLegacy::~COutputLegacy(void) { void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, CSolver *FlowSolver, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_iInst) { - + unsigned short iMarker; unsigned long iPoint, iVertex, Global_Index; su2double PressCoeff = 0.0, SkinFrictionCoeff[3], HeatFlux; su2double xCoord = 0.0, yCoord = 0.0, zCoord = 0.0, Mach, Pressure; char cstr[200]; - + unsigned short solver = config->GetKind_Solver(); unsigned short nDim = geometry->GetnDim(); - + #ifndef HAVE_MPI - + unsigned short iDim; char buffer [50]; ofstream SurfFlow_file; - + /*--- Write file name with extension if unsteady ---*/ strcpy (cstr, config->GetSurfCoeff_FileName().c_str()); - + if (config->GetTime_Marching() == HARMONIC_BALANCE) { SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst)); @@ -464,15 +464,15 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, } else SPRINTF (buffer, ".csv"); - + strcat (cstr, buffer); SurfFlow_file.precision(15); SurfFlow_file.open(cstr, ios::out); - + SurfFlow_file << "\"Global_Index\", \"x_coord\", \"y_coord\", "; if (nDim == 3) SurfFlow_file << "\"z_coord\", "; SurfFlow_file << "\"Pressure\", \"Pressure_Coefficient\", "; - + switch (solver) { case EULER : case INC_EULER: SurfFlow_file << "\"Mach_Number\"" << "\n"; break; case NAVIER_STOKES: case RANS: case INC_NAVIER_STOKES: case INC_RANS: @@ -480,7 +480,7 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, if (nDim == 3) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Skin_Friction_Coefficient_Z\", \"Heat_Flux\"" << "\n"; break; } - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_Plotting(iMarker) == YES) { for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { @@ -489,14 +489,14 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, xCoord = geometry->node[iPoint]->GetCoord(0); yCoord = geometry->node[iPoint]->GetCoord(1); if (nDim == 3) zCoord = geometry->node[iPoint]->GetCoord(2); - + /*--- The output should be in inches ---*/ - + if (config->GetSystemMeasurements() == US) { xCoord *= 12.0; yCoord *= 12.0; if (nDim == 3) zCoord *= 12.0; } - + Pressure = FlowSolver->GetNodes()->GetPressure(iPoint); PressCoeff = FlowSolver->GetCPressure(iMarker, iVertex); SurfFlow_file << scientific << Global_Index << ", " << xCoord << ", " << yCoord << ", "; @@ -507,35 +507,35 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, Mach = sqrt(FlowSolver->GetNodes()->GetVelocity2(iPoint)) / FlowSolver->GetNodes()->GetSoundSpeed(iPoint); SurfFlow_file << scientific << Mach << "\n"; break; - case NAVIER_STOKES: case RANS: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES: + case NAVIER_STOKES: case RANS: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES: case INC_NAVIER_STOKES: case INC_RANS: for (iDim = 0; iDim < nDim; iDim++) SkinFrictionCoeff[iDim] = FlowSolver->GetCSkinFriction(iMarker, iVertex, iDim); HeatFlux = FlowSolver->GetHeatFlux(iMarker, iVertex); - + if (nDim == 2) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << HeatFlux << "\n"; if (nDim == 3) SurfFlow_file << scientific << SkinFrictionCoeff[0] << ", " << SkinFrictionCoeff[1] << ", " << SkinFrictionCoeff[2] << ", " << HeatFlux << "\n"; - + break; } } } } - + SurfFlow_file.close(); - + #else - + int iProcessor, nProcessor = size; unsigned long Buffer_Send_nVertex[1], *Buffer_Recv_nVertex = NULL; unsigned long nVertex_Surface = 0, nLocalVertex_Surface = 0; unsigned long MaxLocalVertex_Surface = 0; - + /*--- Find the max number of surface vertices among all partitions and set up buffers. The master node will handle the writing of the CSV file after gathering all of the data. ---*/ - + nLocalVertex_Surface = 0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) if (config->GetMarker_All_Plotting(iMarker) == YES) @@ -543,53 +543,53 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); if (geometry->node[iPoint]->GetDomain()) nLocalVertex_Surface++; } - + /*--- Communicate the number of local vertices on each partition to the master node ---*/ - + Buffer_Send_nVertex[0] = nLocalVertex_Surface; if (rank == MASTER_NODE) Buffer_Recv_nVertex = new unsigned long [nProcessor]; - + SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); - + /*--- Send and Recv buffers ---*/ - + su2double *Buffer_Send_Coord_x = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_Coord_x = NULL; - + su2double *Buffer_Send_Coord_y = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_Coord_y = NULL; - + su2double *Buffer_Send_Coord_z = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_Coord_z = NULL; - + su2double *Buffer_Send_Press = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_Press = NULL; - + su2double *Buffer_Send_CPress = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_CPress = NULL; - + su2double *Buffer_Send_Mach = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_Mach = NULL; - + su2double *Buffer_Send_SkinFriction_x = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_SkinFriction_x = NULL; - + su2double *Buffer_Send_SkinFriction_y = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_SkinFriction_y = NULL; - + su2double *Buffer_Send_SkinFriction_z = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_SkinFriction_z = NULL; - + su2double *Buffer_Send_HeatTransfer = new su2double [MaxLocalVertex_Surface]; su2double *Buffer_Recv_HeatTransfer = NULL; - + unsigned long *Buffer_Send_GlobalIndex = new unsigned long [MaxLocalVertex_Surface]; unsigned long *Buffer_Recv_GlobalIndex = NULL; - + /*--- Prepare the receive buffers on the master node only. ---*/ - + if (rank == MASTER_NODE) { Buffer_Recv_Coord_x = new su2double [nProcessor*MaxLocalVertex_Surface]; Buffer_Recv_Coord_y = new su2double [nProcessor*MaxLocalVertex_Surface]; @@ -603,11 +603,11 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, Buffer_Recv_HeatTransfer = new su2double [nProcessor*MaxLocalVertex_Surface]; Buffer_Recv_GlobalIndex = new unsigned long [nProcessor*MaxLocalVertex_Surface]; } - + /*--- Loop over all vertices in this partition and load the data of the specified type into the buffer to be sent to the master node. ---*/ - + nVertex_Surface = 0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) if (config->GetMarker_All_Plotting(iMarker) == YES) @@ -619,18 +619,18 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, Buffer_Send_Coord_x[nVertex_Surface] = geometry->node[iPoint]->GetCoord(0); Buffer_Send_Coord_y[nVertex_Surface] = geometry->node[iPoint]->GetCoord(1); if (nDim == 3) { Buffer_Send_Coord_z[nVertex_Surface] = geometry->node[iPoint]->GetCoord(2); } - + /*--- If US system, the output should be in inches ---*/ - + if (config->GetSystemMeasurements() == US) { Buffer_Send_Coord_x[nVertex_Surface] *= 12.0; Buffer_Send_Coord_y[nVertex_Surface] *= 12.0; if (nDim == 3) Buffer_Send_Coord_z[nVertex_Surface] *= 12.0; } - + Buffer_Send_GlobalIndex[nVertex_Surface] = geometry->node[iPoint]->GetGlobalIndex(); - - if (solver == EULER || solver == FEM_EULER || solver == INC_EULER) + + if (solver == EULER || solver == FEM_EULER || solver == INC_EULER) Buffer_Send_Mach[nVertex_Surface] = sqrt(FlowSolver->GetNodes()->GetVelocity2(iPoint)) / FlowSolver->GetNodes()->GetSoundSpeed(iPoint); if (solver == NAVIER_STOKES || solver == RANS || solver == INC_NAVIER_STOKES || solver == INC_RANS || @@ -643,9 +643,9 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, nVertex_Surface++; } } - + /*--- Send the information to the master node ---*/ - + SU2_MPI::Gather(Buffer_Send_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -659,21 +659,21 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, SU2_MPI::Gather(Buffer_Send_HeatTransfer, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_HeatTransfer, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); } SU2_MPI::Gather(Buffer_Send_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, MaxLocalVertex_Surface, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); - + /*--- The master node unpacks the data and writes the surface CSV file ---*/ - + if (rank == MASTER_NODE) { - + /*--- Write file name with extension if unsteady ---*/ char buffer[50]; string filename = config->GetSurfCoeff_FileName(); ofstream SurfFlow_file; - + /*--- Write file name with extension if unsteady ---*/ strcpy (cstr, filename.c_str()); if (config->GetTime_Marching() == HARMONIC_BALANCE) { SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst)); - + } else if (config->GetTime_Marching() && config->GetTime_Domain()) { if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter)); if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter)); @@ -683,15 +683,15 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, } else SPRINTF (buffer, ".csv"); - + strcat (cstr, buffer); SurfFlow_file.precision(15); SurfFlow_file.open(cstr, ios::out); - + SurfFlow_file << "\"Global_Index\", \"x_coord\", \"y_coord\", "; if (nDim == 3) SurfFlow_file << "\"z_coord\", "; SurfFlow_file << "\"Pressure\", \"Pressure_Coefficient\", "; - + switch (solver) { case EULER : case FEM_EULER: case INC_EULER: SurfFlow_file << "\"Mach_Number\"" << "\n"; break; case NAVIER_STOKES: case RANS: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES: case INC_NAVIER_STOKES: case INC_RANS: @@ -699,29 +699,29 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, if (nDim == 3) SurfFlow_file << "\"Skin_Friction_Coefficient_X\", \"Skin_Friction_Coefficient_Y\", \"Skin_Friction_Coefficient_Z\", \"Heat_Flux\"" << "\n"; break; } - + /*--- Loop through all of the collected data and write each node's values ---*/ - + unsigned long Total_Index; for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) { - + /*--- Current index position and global index ---*/ Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex; Global_Index = Buffer_Recv_GlobalIndex[Total_Index]; - + /*--- Retrieve the merged data for this node ---*/ xCoord = Buffer_Recv_Coord_x[Total_Index]; yCoord = Buffer_Recv_Coord_y[Total_Index]; if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index]; Pressure = Buffer_Recv_Press[Total_Index]; PressCoeff = Buffer_Recv_CPress[Total_Index]; - + /*--- Write the first part of the data ---*/ SurfFlow_file << scientific << Global_Index << ", " << xCoord << ", " << yCoord << ", "; if (nDim == 3) SurfFlow_file << scientific << zCoord << ", "; SurfFlow_file << scientific << Pressure << ", " << PressCoeff << ", "; - + /*--- Write the solver-dependent part of the data ---*/ switch (solver) { case EULER : @@ -743,12 +743,12 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, } } } - + /*--- Close the CSV file ---*/ SurfFlow_file.close(); - + /*--- Release the recv buffers on the master node ---*/ - + delete [] Buffer_Recv_Coord_x; delete [] Buffer_Recv_Coord_y; if (nDim == 3) delete [] Buffer_Recv_Coord_z; @@ -760,13 +760,13 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, if (nDim == 3) delete [] Buffer_Recv_SkinFriction_z; delete [] Buffer_Recv_HeatTransfer; delete [] Buffer_Recv_GlobalIndex; - + delete [] Buffer_Recv_nVertex; - + } - + /*--- Release the memory for the remaining buffers and exit ---*/ - + delete [] Buffer_Send_Coord_x; delete [] Buffer_Send_Coord_y; delete [] Buffer_Send_Coord_z; @@ -778,28 +778,28 @@ void COutputLegacy::SetSurfaceCSV_Flow(CConfig *config, CGeometry *geometry, delete [] Buffer_Send_SkinFriction_z; delete [] Buffer_Send_HeatTransfer; delete [] Buffer_Send_GlobalIndex; - + #endif - + } void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, CSolver *AdjSolver, CSolver *FlowSolution, unsigned long iExtIter, unsigned short val_iZone, unsigned short val_iInst) { - + #ifndef HAVE_MPI - + unsigned long iPoint, iVertex, Global_Index; su2double *Solution, xCoord, yCoord, zCoord; unsigned short iMarker; char cstr[200], buffer[50]; ofstream SurfAdj_file; - + /*--- Write file name with extension if unsteady ---*/ - + strcpy (cstr, config->GetSurfAdjCoeff_FileName().c_str()); - + if (config->GetTime_Marching() == HARMONIC_BALANCE) { SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst)); - + } else if (config->GetTime_Marching() && config->GetTime_Domain()) { if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter)); if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter)); @@ -809,11 +809,11 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, } else SPRINTF (buffer, ".csv"); - + strcat(cstr, buffer); SurfAdj_file.precision(15); SurfAdj_file.open(cstr, ios::out); - + SurfAdj_file << "SENS_AOA=" << AdjSolver->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl; if (geometry->GetnDim() == 2) { @@ -826,7 +826,7 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, SurfAdj_file << ",\"x_Sens\",\"y_Sens\""; } SurfAdj_file << "\n"; - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_Plotting(iMarker) == YES) for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { @@ -835,9 +835,9 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, Solution = AdjSolver->GetNodes()->GetSolution(iPoint); xCoord = geometry->node[iPoint]->GetCoord(0); yCoord = geometry->node[iPoint]->GetCoord(1); - + /*--- If US system, the output should be in inches ---*/ - + if (config->GetSystemMeasurements() == US) { xCoord *= 12.0; yCoord *= 12.0; @@ -855,7 +855,7 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, } } } - + if (geometry->GetnDim() == 3) { if (config ->GetKind_Regime() == COMPRESSIBLE) SurfAdj_file << "\"Point\",\"Sensitivity\",\"PsiRho\",\"Phi_x\",\"Phi_y\",\"Phi_z\",\"PsiE\",\"x_coord\",\"y_coord\",\"z_coord\""; @@ -872,13 +872,13 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); Global_Index = geometry->node[iPoint]->GetGlobalIndex(); Solution = AdjSolver->GetNodes()->GetSolution(iPoint); - + xCoord = geometry->node[iPoint]->GetCoord(0); yCoord = geometry->node[iPoint]->GetCoord(1); zCoord = geometry->node[iPoint]->GetCoord(2); - + /*--- If US system, the output should be in inches ---*/ - + if (config->GetSystemMeasurements() == US) { xCoord *= 12.0; yCoord *= 12.0; @@ -898,9 +898,9 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, } } } - + SurfAdj_file.close(); - + #else int iProcessor, nProcessor = size; @@ -910,7 +910,7 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, MaxLocalVertex_Surface = 0, nBuffer_Scalar; unsigned long *Buffer_Receive_nVertex = NULL; ofstream SurfAdj_file; - + /*--- Write the surface .csv file ---*/ nLocalVertex_Surface = 0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) @@ -919,15 +919,15 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); if (geometry->node[iPoint]->GetDomain()) nLocalVertex_Surface ++; } - + if (rank == MASTER_NODE) Buffer_Receive_nVertex = new unsigned long [nProcessor]; - + Buffer_Send_nVertex[0] = nLocalVertex_Surface; - + SU2_MPI::Allreduce(&nLocalVertex_Surface, &MaxLocalVertex_Surface, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); SU2_MPI::Gather(&Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); - + su2double *Buffer_Send_Coord_x = new su2double[MaxLocalVertex_Surface]; su2double *Buffer_Send_Coord_y= new su2double[MaxLocalVertex_Surface]; su2double *Buffer_Send_Coord_z= new su2double[MaxLocalVertex_Surface]; @@ -943,7 +943,7 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, Buffer_Send_PsiE = new su2double[MaxLocalVertex_Surface]; su2double *Buffer_Send_Sens_x = NULL, *Buffer_Send_Sens_y = NULL, *Buffer_Send_Sens_z = NULL; - + if (config->GetDiscrete_Adjoint()) { Buffer_Send_Sens_x = new su2double[MaxLocalVertex_Surface]; Buffer_Send_Sens_y = new su2double[MaxLocalVertex_Surface]; @@ -951,7 +951,7 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, Buffer_Send_Sens_z = new su2double[MaxLocalVertex_Surface]; } } - + nVertex_Surface = 0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) if (config->GetMarker_All_Plotting(iMarker) == YES) @@ -982,24 +982,24 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, Buffer_Send_Sens_z[nVertex_Surface] = AdjSolver->GetNodes()->GetSensitivity(iPoint, 2); } } - + /*--- If US system, the output should be in inches ---*/ - + if (config->GetSystemMeasurements() == US) { Buffer_Send_Coord_x[nVertex_Surface] *= 12.0; Buffer_Send_Coord_y[nVertex_Surface] *= 12.0; if (nDim == 3) Buffer_Send_Coord_z[nVertex_Surface] *= 12.0; } - + nVertex_Surface++; } } - + su2double *Buffer_Receive_Coord_x = NULL, *Buffer_Receive_Coord_y = NULL, *Buffer_Receive_Coord_z = NULL, *Buffer_Receive_Sensitivity = NULL, *Buffer_Receive_PsiRho = NULL, *Buffer_Receive_Phi_x = NULL, *Buffer_Receive_Phi_y = NULL, *Buffer_Receive_Phi_z = NULL, *Buffer_Receive_PsiE = NULL, *Buffer_Receive_Sens_x = NULL, *Buffer_Receive_Sens_y = NULL, *Buffer_Receive_Sens_z = NULL; unsigned long *Buffer_Receive_GlobalPoint = NULL; - + if (rank == MASTER_NODE) { Buffer_Receive_Coord_x = new su2double [nProcessor*MaxLocalVertex_Surface]; Buffer_Receive_Coord_y = new su2double [nProcessor*MaxLocalVertex_Surface]; @@ -1020,9 +1020,9 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, } } } - + nBuffer_Scalar = MaxLocalVertex_Surface; - + /*--- Send the information to the Master node ---*/ SU2_MPI::Gather(Buffer_Send_Coord_x, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Coord_x, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Coord_y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Coord_y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -1042,20 +1042,20 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, SU2_MPI::Gather(Buffer_Send_Sens_z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Receive_Sens_z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); } } - + /*--- The master node is the one who writes the surface files ---*/ if (rank == MASTER_NODE) { unsigned long iVertex, GlobalPoint, position; char cstr[200], buffer[50]; ofstream SurfAdj_file; string filename = config->GetSurfAdjCoeff_FileName(); - + /*--- Write file name with extension if unsteady ---*/ strcpy (cstr, filename.c_str()); - + if (config->GetTime_Marching() == HARMONIC_BALANCE) { SPRINTF (buffer, "_%d.csv", SU2_TYPE::Int(val_iInst)); - + } else if (config->GetTime_Marching() && config->GetTime_Domain()) { if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.csv", SU2_TYPE::Int(iExtIter)); if ((SU2_TYPE::Int(iExtIter) >= 10) && (SU2_TYPE::Int(iExtIter) < 100)) SPRINTF (buffer, "_000%d.csv", SU2_TYPE::Int(iExtIter)); @@ -1065,11 +1065,11 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, } else SPRINTF (buffer, ".csv"); - + strcat (cstr, buffer); SurfAdj_file.open(cstr, ios::out); SurfAdj_file.precision(15); - + SurfAdj_file << "SENS_AOA=" << AdjSolver->GetTotal_Sens_AoA() * PI_NUMBER / 180.0 << endl; /*--- Write the 2D surface flow coefficient file ---*/ @@ -1083,10 +1083,10 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, SurfAdj_file << ",\" x_Sens\",\"y_Sens\""; } SurfAdj_file << "\n"; - + for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) for (iVertex = 0; iVertex < Buffer_Receive_nVertex[iProcessor]; iVertex++) { - + position = iProcessor*MaxLocalVertex_Surface+iVertex; GlobalPoint = Buffer_Receive_GlobalPoint[position]; @@ -1108,7 +1108,7 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, SurfAdj_file << "\n"; } } - + /*--- Write the 3D surface flow coefficient file ---*/ if (geometry->GetnDim() == 3) { if (config->GetKind_Regime() == COMPRESSIBLE) @@ -1120,12 +1120,12 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, SurfAdj_file << ",\"x_Sens\",\"y_Sens\",\"z_Sens\""; } SurfAdj_file << "\n"; - + for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) for (iVertex = 0; iVertex < Buffer_Receive_nVertex[iProcessor]; iVertex++) { position = iProcessor*MaxLocalVertex_Surface+iVertex; GlobalPoint = Buffer_Receive_GlobalPoint[position]; - + if (config->GetKind_Regime() == COMPRESSIBLE) SurfAdj_file << scientific << GlobalPoint << ", " << Buffer_Receive_Sensitivity[position] << ", " << Buffer_Receive_PsiRho[position] << @@ -1145,9 +1145,9 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, SurfAdj_file << "\n"; } } - + } - + if (rank == MASTER_NODE) { delete [] Buffer_Receive_nVertex; delete [] Buffer_Receive_Coord_x; @@ -1169,7 +1169,7 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, } } } - + delete [] Buffer_Send_Coord_x; delete [] Buffer_Send_Coord_y; delete [] Buffer_Send_Coord_z; @@ -1183,107 +1183,107 @@ void COutputLegacy::SetSurfaceCSV_Adjoint(CConfig *config, CGeometry *geometry, if (Buffer_Send_Sens_x != NULL) delete [] Buffer_Send_Sens_x; if (Buffer_Send_Sens_y != NULL) delete [] Buffer_Send_Sens_y; if (Buffer_Send_Sens_z != NULL) delete [] Buffer_Send_Sens_z; - + SurfAdj_file.close(); - + #endif } void COutputLegacy::MergeConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone) { - + /*--- Flags identifying the types of files to be written. ---*/ - + bool Wrt_Vol = config->GetWrt_Vol_Sol(); bool Wrt_Srf = config->GetWrt_Srf_Sol(); - + /*--- Merge connectivity for each type of element (excluding halos). Note that we only need to merge the connectivity once, as it does not change during computation. Check whether the base file has been written. ---*/ - + /*--- Merge volumetric grid. ---*/ - + if (Wrt_Vol) { - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tria != 0)) cout <<"Merging volumetric triangle grid connectivity." << endl; MergeVolumetricConnectivity(config, geometry, TRIANGLE ); - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Quad != 0)) cout <<"Merging volumetric quadrilateral grid connectivity." << endl; MergeVolumetricConnectivity(config, geometry, QUADRILATERAL ); - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Tetr != 0)) cout <<"Merging volumetric tetrahedron grid connectivity." << endl; MergeVolumetricConnectivity(config, geometry, TETRAHEDRON ); - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Hexa != 0)) cout <<"Merging volumetric hexahedron grid connectivity." << endl; MergeVolumetricConnectivity(config, geometry, HEXAHEDRON ); - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pris != 0)) cout <<"Merging volumetric prism grid connectivity." << endl; MergeVolumetricConnectivity(config, geometry, PRISM ); - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Pyra != 0)) cout <<"Merging volumetric pyramid grid connectivity." << endl; MergeVolumetricConnectivity(config, geometry, PYRAMID ); - + } - + /*--- Merge surface grid. ---*/ - + if (Wrt_Srf) { - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_Line != 0)) cout <<"Merging surface line grid connectivity." << endl; MergeSurfaceConnectivity(config, geometry, LINE); - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundTria != 0)) cout <<"Merging surface triangle grid connectivity." << endl; MergeSurfaceConnectivity(config, geometry, TRIANGLE); - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE) && (nGlobal_BoundQuad != 0)) cout <<"Merging surface quadrilateral grid connectivity." << endl; MergeSurfaceConnectivity(config, geometry, QUADRILATERAL); - + } - + /*--- Update total number of volume elements after merge. ---*/ - + nGlobal_Elem = nGlobal_Tria + nGlobal_Quad + nGlobal_Tetr + nGlobal_Hexa + nGlobal_Pyra + nGlobal_Pris; - + /*--- Update total number of surface elements after merge. ---*/ - + nSurf_Elem = nGlobal_Line + nGlobal_BoundTria + nGlobal_BoundQuad; - + } void COutputLegacy::MergeCoordinates(CConfig *config, CGeometry *geometry) { - + /*--- Local variables needed on all processors ---*/ - + unsigned short iDim, nDim = geometry->GetnDim(); unsigned long iPoint; - + unsigned short kind_SU2 = config->GetKind_SU2(); - + #ifndef HAVE_MPI - + /*--- In serial, the single process has access to all geometry, so simply load the coordinates into the data structure. ---*/ - + unsigned short iMarker; unsigned long iVertex, nTotalPoints = 0; int SendRecv; - + bool isPeriodic; - + /*--- First, create a structure to locate any periodic halo nodes ---*/ int *Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); @@ -1305,88 +1305,88 @@ void COutputLegacy::MergeCoordinates(CConfig *config, CGeometry *geometry) { Local_Halo[iPoint] = false; } } - + } } - + /*--- Total number of points in the mesh (this might include periodic points). ---*/ for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (!Local_Halo[iPoint]) nTotalPoints++; - + nGlobal_Poin = nTotalPoints; nGlobal_Doma = geometry->GetnPointDomain(); - + /*--- Allocate the coordinates data structure. ---*/ - + Coords = new su2double*[nDim]; for (iDim = 0; iDim < nDim; iDim++) { Coords[iDim] = new su2double[nGlobal_Poin]; } - + /*--- Loop over the mesh to collect the coords of the local points ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check if the node belongs to the domain (i.e, not a halo node). Sort by the global index, even in serial there is a renumbering (e.g. RCM). ---*/ - + if (!Local_Halo[iPoint]) { - + /*--- Retrieve the current coordinates at this node. ---*/ - + unsigned long iGlobal_Index = geometry->node[iPoint]->GetGlobalIndex(); - + for (iDim = 0; iDim < nDim; iDim++) { Coords[iDim][iGlobal_Index] = geometry->node[iPoint]->GetCoord(iDim); - + /*--- If US system, the output should be in inches ---*/ - + if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) { Coords[iDim][iGlobal_Index] *= 12.0; } - + } - + } } - - + + delete [] Local_Halo; - + #else - + /*--- MPI preprocessing ---*/ int iProcessor, nProcessor = size; unsigned long jPoint; bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic; - + /*--- Local variables needed for merging the geometry with MPI. ---*/ - + unsigned long iVertex, iMarker; unsigned long Buffer_Send_nPoin[1], *Buffer_Recv_nPoin = NULL; unsigned long nLocalPoint = 0, MaxLocalPoint = 0; unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0; - + if (rank == MASTER_NODE) Buffer_Recv_nPoin = new unsigned long[nProcessor]; - + int *Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + /*--- Search all send/recv boundaries on this partition for any periodic nodes that were part of the original domain. We want to recover these for visualization purposes. ---*/ - + if (Wrt_Halo) { nLocalPoint = geometry->GetnPoint(); } else { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { - + /*--- Checking for less than or equal to the rank, because there may be some periodic halo nodes that send info to the same rank. ---*/ - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); @@ -1406,21 +1406,21 @@ void COutputLegacy::MergeCoordinates(CConfig *config, CGeometry *geometry) { } } } - + /*--- Sum total number of nodes that belong to the domain ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (Local_Halo[iPoint] == false) nLocalPoint++; } Buffer_Send_nPoin[0] = nLocalPoint; - + /*--- Communicate the total number of nodes on this domain. ---*/ - + SU2_MPI::Gather(&Buffer_Send_nPoin, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoin, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); - + if (rank == MASTER_NODE) { nGlobal_Doma = 0; for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { @@ -1428,30 +1428,30 @@ void COutputLegacy::MergeCoordinates(CConfig *config, CGeometry *geometry) { } } nBuffer_Scalar = MaxLocalPoint; - + /*--- Send and Recv buffers. ---*/ - + su2double *Buffer_Send_X = new su2double[MaxLocalPoint]; su2double *Buffer_Recv_X = NULL; - + su2double *Buffer_Send_Y = new su2double[MaxLocalPoint]; su2double *Buffer_Recv_Y = NULL; - + su2double *Buffer_Send_Z = NULL, *Buffer_Recv_Z = NULL; if (nDim == 3) Buffer_Send_Z = new su2double[MaxLocalPoint]; - + unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint]; unsigned long *Buffer_Recv_GlobalIndex = NULL; - + /*--- Prepare the receive buffers in the master node only. ---*/ - + if (rank == MASTER_NODE) { - + Buffer_Recv_X = new su2double[nProcessor*MaxLocalPoint]; Buffer_Recv_Y = new su2double[nProcessor*MaxLocalPoint]; if (nDim == 3) Buffer_Recv_Z = new su2double[nProcessor*MaxLocalPoint]; Buffer_Recv_GlobalIndex = new unsigned long[nProcessor*MaxLocalPoint]; - + /*--- Sum total number of nodes to be written and allocate arrays ---*/ nGlobal_Poin = 0; for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { @@ -1462,55 +1462,55 @@ void COutputLegacy::MergeCoordinates(CConfig *config, CGeometry *geometry) { Coords[iDim] = new su2double[nGlobal_Poin]; } } - + /*--- Main communication routine. Loop over each coordinate and perform the MPI comm. Temporary 1-D buffers are used to send the coordinates at all nodes on each partition to the master node. These are then unpacked by the master and sorted by global index in one large n-dim. array. ---*/ - + /*--- Loop over this partition to collect the coords of the local points. ---*/ su2double *Coords_Local; jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos and write only if requested ---*/ if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Retrieve local coordinates at this node. ---*/ Coords_Local = geometry->node[iPoint]->GetCoord(); - + /*--- Load local coords into the temporary send buffer. ---*/ Buffer_Send_X[jPoint] = Coords_Local[0]; Buffer_Send_Y[jPoint] = Coords_Local[1]; if (nDim == 3) Buffer_Send_Z[jPoint] = Coords_Local[2]; - + /*--- If US system, the output should be in inches ---*/ - + if ((config->GetSystemMeasurements() == US) && (config->GetKind_SU2() != SU2_DEF)) { Buffer_Send_X[jPoint] *= 12.0; Buffer_Send_Y[jPoint] *= 12.0; if (nDim == 3) Buffer_Send_Z[jPoint] *= 12.0; } - + /*--- Store the global index for this local node. ---*/ Buffer_Send_GlobalIndex[jPoint] = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- Increment jPoint as the counter. We need this because iPoint may include halo nodes that we skip over during this loop. ---*/ jPoint++; } } - + /*--- Gather the coordinate data on the master node using MPI. ---*/ - + SU2_MPI::Gather(Buffer_Send_X, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_X, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Y, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Y, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); if (nDim == 3) { SU2_MPI::Gather(Buffer_Send_Z, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Z, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); } SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { @@ -1529,9 +1529,9 @@ void COutputLegacy::MergeCoordinates(CConfig *config, CGeometry *geometry) { jPoint = (iProcessor+1)*nBuffer_Scalar; } } - + /*--- Immediately release the temporary data buffers. ---*/ - + delete [] Local_Halo; delete [] Buffer_Send_X; delete [] Buffer_Send_Y; @@ -1544,40 +1544,40 @@ void COutputLegacy::MergeCoordinates(CConfig *config, CGeometry *geometry) { delete [] Buffer_Recv_GlobalIndex; delete [] Buffer_Recv_nPoin; } - + #endif - + } void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) { - + int iProcessor; unsigned short NODES_PER_ELEMENT = 0; unsigned long iPoint, iNode, jNode; unsigned long iElem = 0; unsigned long nLocalElem = 0, nElem_Total = 0; - + unsigned long iVertex, iMarker; unsigned long jElem; int SendRecv, RecvFrom; - + unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL; unsigned long nBuffer_Scalar = 0; unsigned long kNode = 0, kElem = 0; unsigned long MaxLocalElem = 0, iGlobal_Index, jPoint, kPoint; - + bool Wrt_Halo = config->GetWrt_Halo(); bool *Write_Elem = NULL, notPeriodic, notHalo, addedPeriodic, isPeriodic; - + unsigned short kind_SU2 = config->GetKind_SU2(); - + int *Conn_Elem = NULL; - + /*--- Store the local number of this element type and the number of nodes per this element type. In serial, this will be the total number of this element type in the entire mesh. In parallel, it is the number on only the current partition. ---*/ - + switch (Elem_Type) { case TRIANGLE: nLocalElem = geometry->GetnElemTria(); @@ -1606,13 +1606,13 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom default: SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION); } - + /*--- Find the max number of this element type among all partitions and set up buffers. ---*/ - + Buffer_Send_nElem[0] = nLocalElem; if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size]; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); @@ -1620,40 +1620,40 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom MaxLocalElem = nLocalElem; Buffer_Recv_nElem[0] = Buffer_Send_nElem[0]; #endif - + nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT; - + /*--- Send and Recv buffers ---*/ - + unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar]; unsigned long *Buffer_Recv_Elem = NULL; - + unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem]; unsigned short *Buffer_Recv_Halo = NULL; - + /*--- Prepare the receive buffers on the master node only. ---*/ - + if (rank == MASTER_NODE) { Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar]; Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem]; if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT]; } - + /*--- Force the removal of all added periodic elements (use global index). First, we isolate and create a list of all added periodic points, excluding those that we part of the original domain (we want these to be in the output files). ---*/ - + vector Added_Periodic; Added_Periodic.clear(); - + if (kind_SU2 != SU2_DEF) { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - + if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) && (SendRecv < 0)) { @@ -1663,20 +1663,20 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom } } } - + /*--- Now we communicate this information to all processors, so that they can force the removal of these particular nodes by flagging them as halo points. In general, this should be a small percentage of the total mesh, so the communication/storage costs here shouldn't be prohibitive. ---*/ - + /*--- First communicate the number of points that each rank has found ---*/ unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0; unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL; Buffer_Recv_nAddedPeriodic = new unsigned long[size]; - + nAddedPeriodic = Added_Periodic.size(); Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); @@ -1686,18 +1686,18 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom maxAddedPeriodic = nAddedPeriodic; Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0]; #endif - + /*--- Communicate the global index values of all added periodic nodes. ---*/ unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic]; unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic]; - + for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) { Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint]; } - + /*--- Gather the element connectivity information. All processors will now have a copy of the global index values for all added periodic points. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, @@ -1705,43 +1705,43 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom #else for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++) Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint]; #endif - + /*--- Search all send/recv boundaries on this partition for halo cells. In particular, consider only the recv conditions (these are the true halo nodes). Check the ranks of the processors that are communicating and choose to keep only the halo cells from the higher rank processor. Here, we are also choosing to keep periodic nodes that were part of the original domain. We will check the communicated list of added periodic points. ---*/ - + int *Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); RecvFrom = abs(SendRecv)-1; - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); iGlobal_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- We need to keep one copy of overlapping halo cells. ---*/ notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) && (SendRecv < 0) && (rank > RecvFrom)); - + /*--- We want to keep the periodic nodes that were part of the original domain. For SU2_DEF we want to keep all periodic nodes. ---*/ - + if (kind_SU2 == SU2_DEF) { isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0)); }else { isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1)); } - + notPeriodic = (isPeriodic && (SendRecv < 0)); - + /*--- Lastly, check that this isn't an added periodic point that we will forcibly remove. Use the communicated list of these points. ---*/ addedPeriodic = false; kPoint = 0; @@ -1753,7 +1753,7 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom /*--- Adjust jNode to index of next proc's data in the buffers. ---*/ kPoint = (iProcessor+1)*maxAddedPeriodic; } - + /*--- If we found either of these types of nodes, flag them to be kept. ---*/ if ((notHalo || notPeriodic) && !addedPeriodic) { Local_Halo[iPoint] = false; @@ -1761,45 +1761,45 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom } } } - + /*--- Loop over all elements in this partition and load the elements of the current type into the buffer to be sent to the master node. ---*/ - + jNode = 0; jElem = 0; for (iElem = 0; iElem < geometry->GetnElem(); iElem++) { if (geometry->elem[iElem]->GetVTK_Type() == Elem_Type) { - + /*--- Loop over all nodes in this element and load the connectivity into the send buffer. ---*/ - + Buffer_Send_Halo[jElem] = false; for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) { - + /*--- Store the global index values directly. ---*/ - + iPoint = geometry->elem[iElem]->GetNode(iNode); Buffer_Send_Elem[jNode] = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- Check if this is a halo node. If so, flag this element as a halo cell. We will use this later to sort and remove any duplicates from the connectivity list. ---*/ - + if (Local_Halo[iPoint]) { Buffer_Send_Halo[jElem] = true; } - + /*--- Increment jNode as the counter. We need this because iElem may include other elements that we skip over during this loop. ---*/ - + jNode++; } jElem++; } } - + /*--- Gather the element connectivity information. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD); @@ -1807,56 +1807,56 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint]; for (iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint]; #endif - + /*--- The master node unpacks and sorts the connectivity. ---*/ - + if (rank == MASTER_NODE) { - + /*--- We need to remove any duplicate elements (halo cells) that exist on multiple partitions. Start by initializing all elements to the "write" state by using a boolean array. ---*/ - + Write_Elem = new bool[size*MaxLocalElem]; for (iElem = 0; iElem < size*MaxLocalElem; iElem++) { Write_Elem[iElem] = true; } - + /*--- Remove the rind layer from the solution only if requested ---*/ - + if (!Wrt_Halo) { - + /*--- Loop for flagging duplicate elements so that they are not included in the final connectivity list. ---*/ - + kElem = 0; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) { - + /*--- Check if this element was marked as a halo. ---*/ if (Buffer_Recv_Halo[kElem+iElem]) Write_Elem[kElem+iElem] = false; - + } kElem = (iProcessor+1)*MaxLocalElem; } } - + /*--- Store the unique connectivity list for this element type. ---*/ - + jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) { - + /*--- Only write the elements that were flagged for it. ---*/ if (Write_Elem[jElem+iElem]) { - + /*--- Increment total count for this element type ---*/ nElem_Total++; - + /*--- Get global index, then loop over each variable and store. Note that we are adding one to the index value because CGNS/Tecplot use 1-based indexing.---*/ - + for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) { Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1; kNode++; @@ -1868,7 +1868,7 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom jNode = (iProcessor+1)*nBuffer_Scalar; } } - + /*--- Immediately release the temporary buffers. ---*/ delete [] Buffer_Send_Elem; delete [] Buffer_Send_Halo; @@ -1882,10 +1882,10 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom delete [] Buffer_Recv_Halo; delete [] Write_Elem; } - + /*--- Store the particular global element count in the class data, and set the class data pointer to the connectivity array. ---*/ - + if (rank == MASTER_NODE) { switch (Elem_Type) { case TRIANGLE: @@ -1917,43 +1917,43 @@ void COutputLegacy::MergeVolumetricConnectivity(CConfig *config, CGeometry *geom break; } } - + } void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) { - + unsigned short NODES_PER_ELEMENT; - + unsigned short iMarker; unsigned long iPoint, iNode, jNode; unsigned long iElem = 0; unsigned long nLocalElem = 0, nElem_Total = 0; - + int iProcessor; unsigned long jElem; - + unsigned long iVertex; - + int SendRecv, RecvFrom; - + unsigned long Buffer_Send_nElem[1], *Buffer_Recv_nElem = NULL; unsigned long nBuffer_Scalar = 0; unsigned long kNode = 0, kElem = 0; unsigned long MaxLocalElem = 0, iGlobal_Index, jPoint, kPoint; - + bool Wrt_Halo = config->GetWrt_Halo(); bool *Write_Elem = NULL, notPeriodic, notHalo, addedPeriodic; - - + + int *Conn_Elem = NULL; - + /*--- Store the local number of this element type and the number of nodes per this element type. In serial, this will be the total number of this element type in the entire mesh. In parallel, it is the number on only the current partition. ---*/ - + nLocalElem = 0; - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_Plotting(iMarker) == YES) { for (iElem = 0; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { @@ -1963,7 +1963,7 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr } } } - + switch (Elem_Type) { case LINE: NODES_PER_ELEMENT = N_POINTS_LINE; @@ -1979,13 +1979,13 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr NODES_PER_ELEMENT = 0; break; } - + /*--- Find the max number of this element type among all partitions and set up buffers. ---*/ - + Buffer_Send_nElem[0] = nLocalElem; if (rank == MASTER_NODE) Buffer_Recv_nElem = new unsigned long[size]; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nLocalElem, &MaxLocalElem, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); SU2_MPI::Gather(&Buffer_Send_nElem, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nElem, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); @@ -1993,30 +1993,30 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr MaxLocalElem = nLocalElem; Buffer_Recv_nElem[0] = Buffer_Send_nElem[0]; #endif - + nBuffer_Scalar = MaxLocalElem*NODES_PER_ELEMENT; - + /*--- Send and Recv buffers ---*/ - + unsigned long *Buffer_Send_Elem = new unsigned long[nBuffer_Scalar]; unsigned long *Buffer_Recv_Elem = NULL; - + unsigned short *Buffer_Send_Halo = new unsigned short[MaxLocalElem]; unsigned short *Buffer_Recv_Halo = NULL; - + /*--- Prepare the receive buffers on the master node only. ---*/ - + if (rank == MASTER_NODE) { Buffer_Recv_Elem = new unsigned long[size*nBuffer_Scalar]; Buffer_Recv_Halo = new unsigned short[size*MaxLocalElem]; if (MaxLocalElem > 0) Conn_Elem = new int[size*MaxLocalElem*NODES_PER_ELEMENT]; } - + /*--- Force the removal of all added periodic elements (use global index). First, we isolate and create a list of all added periodic points, excluding those that we part of the original domain (we want these to be in the output files). ---*/ - + vector Added_Periodic; Added_Periodic.clear(); for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { @@ -2032,20 +2032,20 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr } } } - + /*--- Now we communicate this information to all processors, so that they can force the removal of these particular nodes by flagging them as halo points. In general, this should be a small percentage of the total mesh, so the communication/storage costs here shouldn't be prohibitive. ---*/ - + /*--- First communicate the number of points that each rank has found ---*/ unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0; unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL; Buffer_Recv_nAddedPeriodic = new unsigned long[size]; - + nAddedPeriodic = Added_Periodic.size(); Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); @@ -2055,18 +2055,18 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr maxAddedPeriodic = nAddedPeriodic; Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0]; #endif - + /*--- Communicate the global index values of all added periodic nodes. ---*/ unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic]; unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic]; - + for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) { Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint]; } - + /*--- Gather the element connectivity information. All processors will now have a copy of the global index values for all added periodic points. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, @@ -2074,36 +2074,36 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr #else for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++) Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint]; #endif - + /*--- Search all send/recv boundaries on this partition for halo cells. In particular, consider only the recv conditions (these are the true halo nodes). Check the ranks of the processors that are communicating and choose to keep only the halo cells from the higher rank processor. Here, we are also choosing to keep periodic nodes that were part of the original domain. We will check the communicated list of added periodic points. ---*/ - + int *Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); RecvFrom = abs(SendRecv)-1; - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); iGlobal_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- We need to keep one copy of overlapping halo cells. ---*/ notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) && (SendRecv < 0) && (rank > RecvFrom)); - + /*--- We want to keep the periodic nodes that were part of the original domain ---*/ notPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1) && (SendRecv < 0)); - + /*--- Lastly, check that this isn't an added periodic point that we will forcibly remove. Use the communicated list of these points. ---*/ addedPeriodic = false; kPoint = 0; @@ -2115,7 +2115,7 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr /*--- Adjust jNode to index of next proc's data in the buffers. ---*/ kPoint = (iProcessor+1)*maxAddedPeriodic; } - + /*--- If we found either of these types of nodes, flag them to be kept. ---*/ if ((notHalo || notPeriodic) && !addedPeriodic) { Local_Halo[iPoint] = false; @@ -2123,7 +2123,7 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr } } } - + /*--- Loop over all elements in this partition and load the elements of the current type into the buffer to be sent to the master node. ---*/ @@ -2131,38 +2131,38 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) if (config->GetMarker_All_Plotting(iMarker) == YES) for (iElem = 0; iElem < geometry->GetnElem_Bound(iMarker); iElem++) { - + if (geometry->bound[iMarker][iElem]->GetVTK_Type() == Elem_Type) { - + /*--- Loop over all nodes in this element and load the connectivity into the send buffer. ---*/ - + Buffer_Send_Halo[jElem] = false; for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) { - + /*--- Store the global index values directly. ---*/ - + iPoint = geometry->bound[iMarker][iElem]->GetNode(iNode); Buffer_Send_Elem[jNode] = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- Check if this is a halo node. If so, flag this element as a halo cell. We will use this later to sort and remove any duplicates from the connectivity list. ---*/ - + if (Local_Halo[iPoint]) Buffer_Send_Halo[jElem] = true; - + /*--- Increment jNode as the counter. We need this because iElem may include other elements that we skip over during this loop. ---*/ - + jNode++; } jElem++; } } - + /*--- Gather the element connectivity information. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_Elem, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, Buffer_Recv_Halo, MaxLocalElem, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD); @@ -2170,56 +2170,56 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Elem[iPoint] = Buffer_Send_Elem[iPoint]; for (iPoint = 0; iPoint < MaxLocalElem; iPoint++) Buffer_Recv_Halo[iPoint] = Buffer_Send_Halo[iPoint]; #endif - + /*--- The master node unpacks and sorts the connectivity. ---*/ - + if (rank == MASTER_NODE) { - + /*--- We need to remove any duplicate elements (halo cells) that exist on multiple partitions. Start by initializing all elements to the "write" state by using a boolean array. ---*/ - + Write_Elem = new bool[size*MaxLocalElem]; for (iElem = 0; iElem < size*MaxLocalElem; iElem++) { Write_Elem[iElem] = true; } - + /*--- Remove the rind layer from the solution only if requested ---*/ - + if (!Wrt_Halo) { - + /*--- Loop for flagging duplicate elements so that they are not included in the final connectivity list. ---*/ - + kElem = 0; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) { - + /*--- Check if this element was marked as a halo. ---*/ if (Buffer_Recv_Halo[kElem+iElem]) Write_Elem[kElem+iElem] = false; - + } kElem = (iProcessor+1)*MaxLocalElem; } } - + /*--- Store the unique connectivity list for this element type. ---*/ - + jNode = 0; kNode = 0; jElem = 0; nElem_Total = 0; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iElem = 0; iElem < Buffer_Recv_nElem[iProcessor]; iElem++) { - + /*--- Only write the elements that were flagged for it. ---*/ if (Write_Elem[jElem+iElem]) { - + /*--- Increment total count for this element type ---*/ nElem_Total++; - + /*--- Get global index, then loop over each variable and store. Note that we are adding one to the index value because CGNS/Tecplot use 1-based indexing.---*/ - + for (iNode = 0; iNode < NODES_PER_ELEMENT; iNode++) { Conn_Elem[kNode] = (int)Buffer_Recv_Elem[jNode+iElem*NODES_PER_ELEMENT+iNode] + 1; kNode++; @@ -2231,7 +2231,7 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr jNode = (iProcessor+1)*nBuffer_Scalar; } } - + /*--- Immediately release the temporary buffers. ---*/ delete [] Buffer_Send_Elem; delete [] Buffer_Send_Halo; @@ -2245,10 +2245,10 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr delete [] Buffer_Recv_Halo; delete [] Write_Elem; } - + /*--- Store the particular global element count in the class data, and set the class data pointer to the connectivity array. ---*/ - + if (rank == MASTER_NODE) { switch (Elem_Type) { case LINE: @@ -2268,11 +2268,11 @@ void COutputLegacy::MergeSurfaceConnectivity(CConfig *config, CGeometry *geometr break; } } - + } void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) { - + unsigned short Kind_Solver = config->GetKind_Solver(); unsigned short iVar = 0, jVar = 0, FirstIndex = NONE, SecondIndex = NONE, ThirdIndex = NONE; unsigned short nVar_First = 0, nVar_Second = 0, nVar_Third = 0; @@ -2282,18 +2282,18 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver iVar_FEA_Extra = 0, iVar_SensDim = 0; unsigned long iPoint = 0, jPoint = 0, iVertex = 0, iMarker = 0; su2double Gas_Constant, Mach2Vel, Mach_Motion, RefDensity, RefPressure = 0.0, factor = 0.0; - + su2double *Aux_Frict_x = NULL, *Aux_Frict_y = NULL, *Aux_Frict_z = NULL, *Aux_Heat = NULL, *Aux_yPlus = NULL, *Aux_Sens = NULL; - + unsigned short CurrentIndex; int *Local_Halo; unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL; unsigned long nLocalPoint = 0, MaxLocalPoint = 0; unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0; bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic; - + int iProcessor; - + bool dynamic_grid = config->GetDynamic_Grid(); bool compressible = (config->GetKind_Regime() == COMPRESSIBLE); bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); @@ -2312,13 +2312,13 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver ( config->GetKind_Solver() == ADJ_NAVIER_STOKES ) || ( config->GetKind_Solver() == ADJ_RANS ) ); bool fem = (config->GetKind_Solver() == FEM_ELASTICITY); - + unsigned short iDim; unsigned short nDim = geometry->GetnDim(); su2double RefArea = config->GetRefArea(); su2double Gamma = config->GetGamma(); su2double RefVel2, *Normal, Area; - + /*--- Set the non-dimensionalization ---*/ if (flow) { if (dynamic_grid) { @@ -2336,11 +2336,11 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver RefPressure = solver[FLOW_SOL]->GetPressure_Inf(); factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2); } - + /*--- Prepare send buffers for the conservative variables. Need to find the total number of conservative variables and also the index for their particular solution container. ---*/ - + switch (Kind_Solver) { case EULER : case NAVIER_STOKES: case INC_EULER: case INC_NAVIER_STOKES: FirstIndex = FLOW_SOL; if(config->GetWeakly_Coupled_Heat()) SecondIndex = HEAT_SOL; else SecondIndex = NONE; ThirdIndex = NONE; break; case RANS : case INC_RANS: FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; if (transition) ThirdIndex=TRANS_SOL; else ThirdIndex = NONE; if(config->GetWeakly_Coupled_Heat()) ThirdIndex = HEAT_SOL; else ThirdIndex = NONE; break; @@ -2354,32 +2354,32 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver case DISC_ADJ_FEM: FirstIndex = ADJFEA_SOL; SecondIndex = NONE; ThirdIndex = NONE; break; default: SecondIndex = NONE; ThirdIndex = NONE; break; } - + nVar_First = solver[FirstIndex]->GetnVar(); if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar(); if (ThirdIndex != NONE) nVar_Third = solver[ThirdIndex]->GetnVar(); nVar_Consv = nVar_First + nVar_Second + nVar_Third; nVar_Total = nVar_Consv; - - + + /*--- Add the limiters ---*/ - + if (config->GetWrt_Limiters()) nVar_Total += nVar_Consv; - + /*--- Add the residuals ---*/ - + if (config->GetWrt_Residuals()) nVar_Total += nVar_Consv; - + /*--- Add the grid velocity to the restart file for the unsteady adjoint ---*/ - + if (dynamic_grid && !fem) { iVar_GridVel = nVar_Total; if (geometry->GetnDim() == 2) nVar_Total += 2; else if (geometry->GetnDim() == 3) nVar_Total += 3; } - + /*--- Add Pressure, Temperature, Cp, Mach to the restart file ---*/ - + if (Kind_Solver == EULER || Kind_Solver == NAVIER_STOKES || Kind_Solver == RANS || Kind_Solver == INC_EULER || Kind_Solver == INC_NAVIER_STOKES || Kind_Solver == INC_RANS || Kind_Solver == FEM_EULER || Kind_Solver == FEM_NAVIER_STOKES || Kind_Solver == FEM_RANS || @@ -2387,9 +2387,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver iVar_PressCp = nVar_Total; nVar_Total += 3; iVar_MachMean = nVar_Total; nVar_Total += 1; } - + /*--- Add Laminar Viscosity, Skin Friction, Heat Flux, & yPlus to the restart file ---*/ - + if (Kind_Solver == NAVIER_STOKES || Kind_Solver == RANS || Kind_Solver == INC_NAVIER_STOKES || Kind_Solver == INC_RANS || Kind_Solver == FEM_NAVIER_STOKES || Kind_Solver == FEM_RANS || Kind_Solver == FEM_LES) { @@ -2401,15 +2401,15 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver iVar_HeatCoeffs = nVar_Total; nVar_Total += 2; } - + /*--- Add Eddy Viscosity to the restart file ---*/ - + if (Kind_Solver == RANS || Kind_Solver == FEM_RANS || Kind_Solver == FEM_LES || Kind_Solver == INC_RANS) { iVar_Eddy = nVar_Total; nVar_Total += 1; } - + /*--- Add Sharp edges to the restart file ---*/ - + if (config->GetWrt_SharpEdges()) { if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) || ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) || @@ -2417,14 +2417,14 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver iVar_Sharp = nVar_Total; nVar_Total += 1; } } - - + + if (( Kind_Solver == ADJ_EULER ) || ( Kind_Solver == ADJ_NAVIER_STOKES ) || ( Kind_Solver == ADJ_RANS )) { iVar_Sens = nVar_Total; nVar_Total += 2; } - + if (Kind_Solver == FEM_ELASTICITY) { /*--- If the analysis is dynamic... ---*/ if (config->GetTime_Domain()) { @@ -2441,7 +2441,7 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver if (geometry->GetnDim() == 3) {iVar_FEA_Stress_3D = nVar_Total; nVar_Total += 3;} iVar_FEA_Extra = nVar_Total; nVar_Total += 1; } - + if ((Kind_Solver == DISC_ADJ_EULER) || (Kind_Solver == DISC_ADJ_NAVIER_STOKES) || (Kind_Solver == DISC_ADJ_RANS) || @@ -2451,36 +2451,36 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver iVar_Sens = nVar_Total; nVar_Total += 1; iVar_SensDim = nVar_Total; nVar_Total += nDim; } - + if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())){ iVar_FEA_Extra = nVar_Total; nVar_Total += 2; } - + if (config->GetExtraOutput()) { if (Kind_Solver == RANS || Kind_Solver == INC_RANS) { iVar_Extra = nVar_Total; nVar_Extra = solver[TURB_SOL]->GetnOutputVariables(); nVar_Total += nVar_Extra; } } - - - + + + Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + /*--- Search all send/recv boundaries on this partition for any periodic nodes that were part of the original domain. We want to recover these for visualization purposes. ---*/ - + if (Wrt_Halo) { nLocalPoint = geometry->GetnPoint(); } else { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { - + /*--- Checking for less than or equal to the rank, because there may be some periodic halo nodes that send info to the same rank. ---*/ - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && @@ -2489,20 +2489,20 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver } } } - + /*--- Sum total number of nodes that belong to the domain ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (Local_Halo[iPoint] == false) nLocalPoint++; - + } Buffer_Send_nPoint[0] = nLocalPoint; - + /*--- Each processor sends its local number of nodes to the master. ---*/ - + if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[size]; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); @@ -2510,25 +2510,25 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver MaxLocalPoint = nLocalPoint; Buffer_Recv_nPoint[0] = Buffer_Send_nPoint[0]; #endif - + nBuffer_Scalar = MaxLocalPoint; - + /*--- Send and Recv buffers. ---*/ - + su2double *Buffer_Send_Var = new su2double[MaxLocalPoint]; su2double *Buffer_Recv_Var = NULL; - + su2double *Buffer_Send_Res = new su2double[MaxLocalPoint]; su2double *Buffer_Recv_Res = NULL; - + su2double *Buffer_Send_Vol = new su2double[MaxLocalPoint]; su2double *Buffer_Recv_Vol = NULL; - + unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint]; unsigned long *Buffer_Recv_GlobalIndex = NULL; - + /*--- Auxiliary vectors for surface coefficients ---*/ - + if (((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) || ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) || ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) { @@ -2538,7 +2538,7 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Aux_Heat = new su2double[geometry->GetnPoint()]; Aux_yPlus = new su2double[geometry->GetnPoint()]; } - + if ((Kind_Solver == ADJ_EULER) || (Kind_Solver == ADJ_NAVIER_STOKES) || (Kind_Solver == ADJ_RANS) || @@ -2550,16 +2550,16 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver (Kind_Solver == DISC_ADJ_INC_RANS)) { Aux_Sens = new su2double[geometry->GetnPoint()]; } - + /*--- Prepare the receive buffers in the master node only. ---*/ - + if (rank == MASTER_NODE) { - + Buffer_Recv_Var = new su2double[size*MaxLocalPoint]; Buffer_Recv_Res = new su2double[size*MaxLocalPoint]; Buffer_Recv_Vol = new su2double[size*MaxLocalPoint]; Buffer_Recv_GlobalIndex = new unsigned long[size*MaxLocalPoint]; - + /*--- Sum total number of nodes to be written and allocate arrays ---*/ nGlobal_Poin = 0; for (iProcessor = 0; iProcessor < size; iProcessor++) { @@ -2570,17 +2570,17 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Data[iVar] = new su2double[nGlobal_Poin]; } } - + /*--- Main communication routine. Loop over each variable that has been requested by the user and perform the MPI comm. Temporary 1-D buffers are used to send the solution for each variable at all nodes on each partition to the master node. These are then unpacked by the master and sorted by global index in one large n-dim. array. ---*/ - + for (iVar = 0; iVar < nVar_Consv; iVar++) { - + /*--- Logic for which solution class to draw from. ---*/ - + jVar = iVar; CurrentIndex = FirstIndex; if ((SecondIndex != NONE) && (iVar > nVar_First-1)) { @@ -2591,54 +2591,54 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jVar = iVar - nVar_First - nVar_Second; CurrentIndex = ThirdIndex; } - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Get this variable into the temporary send buffer. ---*/ - + Buffer_Send_Var[jPoint] = solver[CurrentIndex]->GetNodes()->GetSolution(iPoint, jVar); if (config->GetWrt_Limiters()) { Buffer_Send_Vol[jPoint] = solver[CurrentIndex]->GetNodes()->GetLimiter_Primitive(iPoint, jVar); } - + if (config->GetWrt_Residuals()) { if (!config->GetDiscrete_Adjoint()) { - Buffer_Send_Res[jPoint] = solver[CurrentIndex]->LinSysRes.GetBlock(iPoint, jVar); + Buffer_Send_Res[jPoint] = solver[CurrentIndex]->LinSysRes(iPoint, jVar); } else { Buffer_Send_Res[jPoint] = solver[CurrentIndex]->GetNodes()->GetSolution(iPoint, jVar) - solver[CurrentIndex]->GetNodes()->GetSolution_Old(iPoint, jVar); } } - - + + /*--- Only send/recv the volumes & global indices during the first loop ---*/ - + if (iVar == 0) { Buffer_Send_GlobalIndex[jPoint] = geometry->node[iPoint]->GetGlobalIndex(); } - + jPoint++; - + } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); #else for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint]; #endif - + if (config->GetWrt_Limiters()) { #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -2646,7 +2646,7 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; #endif } - + if (config->GetWrt_Residuals()) { #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -2654,9 +2654,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint]; #endif } - - - + + + if (iVar == 0) { #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); @@ -2664,61 +2664,61 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_GlobalIndex[iPoint] = Buffer_Send_GlobalIndex[iPoint]; #endif } - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; - + Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; - - + + if (config->GetWrt_Limiters()) { Data[iVar+nVar_Consv][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; } - + if (config->GetWrt_Residuals()) { unsigned short ExtraIndex; ExtraIndex = nVar_Consv; if (config->GetWrt_Limiters()) ExtraIndex = 2*nVar_Consv; Data[iVar+ExtraIndex][iGlobal_Index] = Buffer_Recv_Res[jPoint]; } - - - + + + jPoint++; } /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ jPoint = (iProcessor+1)*nBuffer_Scalar; } } - + } - + /*--- Additional communication routine for the grid velocity. Note that we are reusing the same temporary buffers from above for efficiency. Also, in the future more routines like this could be used to write an arbitrary number of additional variables to the file. ---*/ - + if (dynamic_grid && !fem) { - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; su2double *Grid_Vel; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the three grid velocity components. ---*/ - + Grid_Vel = geometry->node[iPoint]->GetGridVel(); Buffer_Send_Var[jPoint] = Grid_Vel[0]; Buffer_Send_Res[jPoint] = Grid_Vel[1]; @@ -2726,9 +2726,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -2742,16 +2742,16 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; } #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_GridVel; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint]; @@ -2759,34 +2759,34 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } - + /*--- Communicate Pressure, Cp, and Mach ---*/ - + if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) || ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) || ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) { - + /*--- First, loop through the mesh in order to find and store the value of the coefficient of pressure at any surface nodes. They will be placed in an auxiliary vector and then communicated like all other volumetric variables. ---*/ - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the pressure, Cp, and mach variables. ---*/ Buffer_Send_Var[jPoint] = solver[FLOW_SOL]->GetNodes()->GetPressure(iPoint); @@ -2800,9 +2800,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -2812,47 +2812,47 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint]; for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_PressCp; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint]; Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } - + /*--- Communicate Mach---*/ - + if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) || - ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) || + ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) || ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) { - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the temperature and laminar viscosity variables. ---*/ - + if (compressible) { Buffer_Send_Var[jPoint] = sqrt(solver[FLOW_SOL]->GetNodes()->GetVelocity2(iPoint))/ solver[FLOW_SOL]->GetNodes()->GetSoundSpeed(iPoint); @@ -2864,94 +2864,94 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); #else for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_MachMean; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } - + /*--- Laminar Viscosity ---*/ - + if (((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) || - ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) || + ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) || ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) { - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the temperature and laminar viscosity variables. ---*/ - + Buffer_Send_Res[jPoint] = solver[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); #else for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_Lam; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Res[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } - + /*--- Communicate skin friction ---*/ - + /*--- First, loop through the mesh in order to find and store the value of the viscous coefficients at any surface nodes. They will be placed in an auxiliary vector and then communicated like all other volumetric variables. ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { Aux_Frict_x[iPoint] = 0.0; Aux_Frict_y[iPoint] = 0.0; @@ -2966,18 +2966,18 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver if (geometry->GetnDim() == 3) Aux_Frict_z[iPoint] = solver[FLOW_SOL]->GetCSkinFriction(iMarker, iVertex, 2); } } - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the three grid velocity components. ---*/ - + Buffer_Send_Var[jPoint] = Aux_Frict_x[iPoint]; Buffer_Send_Res[jPoint] = Aux_Frict_y[iPoint]; if (geometry->GetnDim() == 3) @@ -2985,9 +2985,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -3004,17 +3004,17 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; } #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_ViscCoeffs; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; Data[iVar + 1][iGlobal_Index] = Buffer_Recv_Res[jPoint]; @@ -3022,20 +3022,20 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Data[iVar + 2][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor + 1) * nBuffer_Scalar; } } - + /*--- Communicate heat transfer, y+ ---*/ - + /*--- First, loop through the mesh in order to find and store the value of the viscous coefficients at any surface nodes. They will be placed in an auxiliary vector and then communicated like all other volumetric variables. ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { Aux_Heat[iPoint] = 0.0; Aux_yPlus[iPoint] = 0.0; @@ -3048,18 +3048,18 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Aux_yPlus[iPoint] = solver[FLOW_SOL]->GetYPlus(iMarker, iVertex); } } - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/ - + if (compressible) { Buffer_Send_Res[jPoint] = Aux_Heat[iPoint]; Buffer_Send_Vol[jPoint] = Aux_yPlus[iPoint]; @@ -3071,9 +3071,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Vol, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Vol, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -3083,138 +3083,138 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_HeatCoeffs; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar + 0][iGlobal_Index] = Buffer_Recv_Res[jPoint]; Data[iVar + 1][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor + 1) * nBuffer_Scalar; } } } - - + + /*--- Communicate the Eddy Viscosity ---*/ - + if (Kind_Solver == RANS || Kind_Solver == FEM_RANS || Kind_Solver == FEM_LES || Kind_Solver == INC_RANS) { - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the pressure and mach variables. ---*/ - + Buffer_Send_Var[jPoint] = solver[FLOW_SOL]->GetNodes()->GetEddyViscosity(iPoint); jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); #else for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_Eddy; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } - + } - + /*--- Communicate the Sharp Edges ---*/ - + if (config->GetWrt_SharpEdges()) { - + if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) || ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) || ((Kind_Solver == FEM_EULER) || (Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) { - + /*--- Loop over this partition to collect the current variable ---*/ jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the pressure and mach variables. ---*/ - + Buffer_Send_Var[jPoint] = geometry->node[iPoint]->GetSharpEdge_Distance(); jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); #else for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_Sharp; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } } - + /*--- Communicate the surface sensitivity ---*/ - + if ((Kind_Solver == ADJ_EULER) || (Kind_Solver == ADJ_NAVIER_STOKES) || (Kind_Solver == ADJ_RANS) || @@ -3224,12 +3224,12 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver (Kind_Solver == DISC_ADJ_INC_EULER) || (Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES) || (Kind_Solver == DISC_ADJ_INC_RANS)) { - + /*--- First, loop through the mesh in order to find and store the value of the surface sensitivity at any surface nodes. They will be placed in an auxiliary vector and then communicated like all other volumetric variables. ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Aux_Sens[iPoint] = 0.0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) if (config->GetMarker_All_Plotting(iMarker) == YES) { @@ -3242,30 +3242,30 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Aux_Sens[iPoint] = solver[ADJFLOW_SOL]->GetCSensitivity(iMarker, iVertex)/Area; } } - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/ - + Buffer_Send_Var[jPoint] = Aux_Sens[iPoint]; if ((config->GetKind_ConvNumScheme() == SPACE_CENTERED) && (!config->GetDiscrete_Adjoint())) Buffer_Send_Res[jPoint] = solver[ADJFLOW_SOL]->GetNodes()->GetSensor(iPoint, iPoint); if ((config->GetKind_ConvNumScheme() == SPACE_UPWIND) && (!config->GetDiscrete_Adjoint())) Buffer_Send_Res[jPoint] = solver[ADJFLOW_SOL]->GetNodes()->GetLimiter(iPoint, 0); - + jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); if (!config->GetDiscrete_Adjoint()) @@ -3275,30 +3275,30 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver if (!config->GetDiscrete_Adjoint()) for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_Sens; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar+0][iGlobal_Index] = Buffer_Recv_Var[jPoint]; if (!config->GetDiscrete_Adjoint()) Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } - + if ((Kind_Solver == DISC_ADJ_EULER) || (Kind_Solver == DISC_ADJ_NAVIER_STOKES) || (Kind_Solver == DISC_ADJ_RANS) || @@ -3306,16 +3306,16 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver (Kind_Solver == DISC_ADJ_INC_NAVIER_STOKES) || (Kind_Solver == DISC_ADJ_INC_RANS)) { /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the skin friction, heat transfer, y+ variables. ---*/ - + Buffer_Send_Var[jPoint] = solver[ADJFLOW_SOL]->GetNodes()->GetSensitivity(iPoint, 0); Buffer_Send_Res[jPoint] = solver[ADJFLOW_SOL]->GetNodes()->GetSensitivity(iPoint, 1); if (nDim == 3) @@ -3323,9 +3323,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -3337,16 +3337,16 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver if (nDim == 3) for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_SensDim; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar+0][iGlobal_Index] = Buffer_Recv_Var[jPoint]; Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint]; @@ -3354,30 +3354,30 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } - - + + /*--- Communicate the Velocities for dynamic FEM problem ---*/ - + if ((Kind_Solver == FEM_ELASTICITY) && (config->GetTime_Domain())) { - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; su2double *Node_Vel; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the three grid velocity components. ---*/ - + Node_Vel = solver[FEA_SOL]->GetNodes()->GetSolution_Vel(iPoint); Buffer_Send_Var[jPoint] = Node_Vel[0]; Buffer_Send_Res[jPoint] = Node_Vel[1]; @@ -3385,9 +3385,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -3401,16 +3401,16 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; } #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_FEA_Vel; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint]; @@ -3418,29 +3418,29 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } - + /*--- Communicate the Accelerations for dynamic FEM problem ---*/ - + if ((Kind_Solver == FEM_ELASTICITY) && (config->GetTime_Domain())) { - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; su2double *Node_Accel; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the three grid velocity components. ---*/ - + Node_Accel = solver[FEA_SOL]->GetNodes()->GetSolution_Accel(iPoint); Buffer_Send_Var[jPoint] = Node_Accel[0]; Buffer_Send_Res[jPoint] = Node_Accel[1]; @@ -3448,9 +3448,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -3464,16 +3464,16 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; } #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_FEA_Accel; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint]; @@ -3481,29 +3481,29 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } /*--- Communicate the FEM elasticity stresses (2D) - New elasticity solver---*/ - + if (Kind_Solver == FEM_ELASTICITY) { - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; const su2double *Stress; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the three grid velocity components. ---*/ - + Stress = solver[FEA_SOL]->GetNodes()->GetStress_FEM(iPoint); /*--- Sigma xx ---*/ Buffer_Send_Var[jPoint] = Stress[0]; @@ -3514,9 +3514,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -3526,45 +3526,45 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint]; for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_FEA_Stress; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint]; Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } - + /*--- Communicate the FEM elasticity stresses (3D) - New elasticity solver---*/ - + if ((Kind_Solver == FEM_ELASTICITY) && (geometry->GetnDim() == 3)) { - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; const su2double *Stress; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the three grid velocity components. ---*/ - + Stress = solver[FEA_SOL]->GetNodes()->GetStress_FEM(iPoint); /*--- Sigma zz ---*/ Buffer_Send_Var[jPoint] = Stress[3]; @@ -3575,9 +3575,9 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Res, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Res, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -3586,81 +3586,81 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint]; for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Res[iPoint] = Buffer_Send_Res[iPoint]; for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Vol[iPoint] = Buffer_Send_Vol[iPoint]; - + #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_FEA_Stress_3D; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; Data[iVar+1][iGlobal_Index] = Buffer_Recv_Res[jPoint]; Data[iVar+2][iGlobal_Index] = Buffer_Recv_Vol[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } - - + + /*--- Communicate the Linear elasticity ---*/ - + if ( Kind_Solver == FEM_ELASTICITY ) { - + /*--- Loop over this partition to collect the current variable ---*/ jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Load buffers with the temperature and laminar viscosity variables. ---*/ - + Buffer_Send_Var[jPoint] = solver[FEA_SOL]->GetNodes()->GetVonMises_Stress(iPoint); jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); #else for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_FEA_Extra; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } - + if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())) { /*--- Loop over this partition to collect the current variable ---*/ @@ -3720,62 +3720,62 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver } if (config->GetExtraOutput()) { - + for (jVar = 0; jVar < nVar_Extra; jVar++) { - + /*--- Loop over this partition to collect the current variable ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Get this variable into the temporary send buffer. ---*/ - + if (Kind_Solver == RANS) { Buffer_Send_Var[jPoint] = solver[TURB_SOL]->OutputVariables[iPoint*nVar_Extra+jVar]; } jPoint++; - + } } - + /*--- Gather the data on the master node. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); #else for (iPoint = 0; iPoint < nBuffer_Scalar; iPoint++) Buffer_Recv_Var[iPoint] = Buffer_Send_Var[iPoint]; #endif - + /*--- The master node unpacks and sorts this variable by global index ---*/ - + if (rank == MASTER_NODE) { jPoint = 0; iVar = iVar_Extra; for (iProcessor = 0; iProcessor < size; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ - + iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar+jVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; jPoint++; } - + /*--- Adjust jPoint to index of next proc's data in the buffers. ---*/ - + jPoint = (iProcessor+1)*nBuffer_Scalar; } } } } - - - + + + /*--- Immediately release the temporary buffers. ---*/ - + delete [] Buffer_Send_Var; delete [] Buffer_Send_Res; delete [] Buffer_Send_Vol; @@ -3787,11 +3787,11 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver delete [] Buffer_Recv_Vol; delete [] Buffer_Recv_GlobalIndex; } - + /*--- Release memory needed for surface coefficients ---*/ - + delete [] Local_Halo; - + if (((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) || ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) || ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_RANS) || (Kind_Solver == FEM_LES))) { @@ -3809,33 +3809,33 @@ void COutputLegacy::MergeSolution(CConfig *config, CGeometry *geometry, CSolver ( Kind_Solver == DISC_ADJ_INC_RANS )) { delete [] Aux_Sens; } - + } void COutputLegacy::MergeBaselineSolution(CConfig *config, CGeometry *geometry, CSolver *solver, unsigned short val_iZone) { - + /*--- Local variables needed on all processors ---*/ unsigned short iVar; unsigned long iPoint = 0, jPoint = 0; - + nVar_Total = config->fields.size() - 1; - + /*--- Merge the solution either in serial or parallel. ---*/ - + #ifndef HAVE_MPI - + /*--- In serial, the single process has access to all solution data, so it is simple to retrieve and store inside Solution_Data. ---*/ - + unsigned short iMarker; unsigned long iVertex, nTotalPoints = 0; int SendRecv; - + /*--- First, create a structure to locate any periodic halo nodes ---*/ int *Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); @@ -3847,76 +3847,76 @@ void COutputLegacy::MergeBaselineSolution(CConfig *config, CGeometry *geometry, Local_Halo[iPoint] = false; } } - + } } - + /*--- Total number of points in the mesh (this might include periodic points). ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (!Local_Halo[iPoint]) nTotalPoints++; - + nGlobal_Poin = nTotalPoints; Data = new su2double*[nVar_Total]; for (iVar = 0; iVar < nVar_Total; iVar++) { Data[iVar] = new su2double[nGlobal_Poin]; } - + /*--- Loop over all points in the mesh, but only write data for nodes in the domain (ignore periodic halo nodes). ---*/ - + jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { if (!Local_Halo[iPoint]) { - + /*--- Solution (first, and second system of equations) ---*/ - + unsigned short jVar = 0; for (iVar = 0; iVar < nVar_Total; iVar++) { Data[jVar][jPoint] = solver->GetNodes()->GetSolution(iPoint,iVar); jVar++; } } - + /*--- Increment jPoint as the counter. We need this because iPoint may include halo nodes that we skip over during this loop. ---*/ - + jPoint++; - + } - + #else - + /*--- MPI preprocessing ---*/ - + int nProcessor = size, iProcessor; - + /*--- Local variables needed for merging with MPI ---*/ - + unsigned long iVertex, iMarker; unsigned long Buffer_Send_nPoint[1], *Buffer_Recv_nPoint = NULL; unsigned long nLocalPoint = 0, MaxLocalPoint = 0; unsigned long iGlobal_Index = 0, nBuffer_Scalar = 0; - + int *Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic; - + /*--- Search all send/recv boundaries on this partition for any periodic nodes that were part of the original domain. We want to recover these for visualization purposes. ---*/ - + if (Wrt_Halo) { nLocalPoint = geometry->GetnPoint(); } else { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { - + /*--- Checking for less than or equal to the rank, because there may be some periodic halo nodes that send info to the same rank. ---*/ - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && @@ -3925,37 +3925,37 @@ void COutputLegacy::MergeBaselineSolution(CConfig *config, CGeometry *geometry, } } } - + /*--- Sum total number of nodes that belong to the domain ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (Local_Halo[iPoint] == false) nLocalPoint++; - + } Buffer_Send_nPoint[0] = nLocalPoint; - + if (rank == MASTER_NODE) Buffer_Recv_nPoint = new unsigned long[nProcessor]; - + SU2_MPI::Allreduce(&nLocalPoint, &MaxLocalPoint, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); SU2_MPI::Gather(&Buffer_Send_nPoint, 1, MPI_UNSIGNED_LONG, Buffer_Recv_nPoint, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); - + nBuffer_Scalar = MaxLocalPoint; - + /*--- Send and Recv buffers. ---*/ - + su2double *Buffer_Send_Var = new su2double[MaxLocalPoint]; su2double *Buffer_Recv_Var = NULL; - + unsigned long *Buffer_Send_GlobalIndex = new unsigned long[MaxLocalPoint]; unsigned long *Buffer_Recv_GlobalIndex = NULL; - + /*--- Prepare the receive buffers in the master node only. ---*/ if (rank == MASTER_NODE) { - + Buffer_Recv_Var = new su2double[nProcessor*MaxLocalPoint]; Buffer_Recv_GlobalIndex = new unsigned long[nProcessor*MaxLocalPoint]; - + /*--- Sum total number of nodes to be written and allocate arrays ---*/ nGlobal_Poin = 0; for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { @@ -3965,27 +3965,27 @@ void COutputLegacy::MergeBaselineSolution(CConfig *config, CGeometry *geometry, for (iVar = 0; iVar < nVar_Total; iVar++) { Data[iVar] = new su2double[nGlobal_Poin]; } - + } - + /*--- Main communication routine. Loop over each variable that has been requested by the user and perform the MPI comm. Temporary 1-D buffers are used to send the solution for each variable at all nodes on each partition to the master node. These are then unpacked by the master and sorted by global index in one large n-dim. array. ---*/ - + for (iVar = 0; iVar < nVar_Total; iVar++) { - + /*--- Loop over this partition to collect the current variable ---*/ jPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos and write only if requested ---*/ if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Get this variable into the temporary send buffer. ---*/ Buffer_Send_Var[jPoint] = solver->GetNodes()->GetSolution(iPoint,iVar); - + /*--- Only send/recv the volumes & global indices during the first loop ---*/ if (iVar == 0) { Buffer_Send_GlobalIndex[jPoint] = geometry->node[iPoint]->GetGlobalIndex(); @@ -3993,20 +3993,20 @@ void COutputLegacy::MergeBaselineSolution(CConfig *config, CGeometry *geometry, jPoint++; } } - + /*--- Gather the data on the master node. ---*/ - + SU2_MPI::Gather(Buffer_Send_Var, nBuffer_Scalar, MPI_DOUBLE, Buffer_Recv_Var, nBuffer_Scalar, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); if (iVar == 0) { SU2_MPI::Gather(Buffer_Send_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, Buffer_Recv_GlobalIndex, nBuffer_Scalar, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); } - + /*--- The master node unpacks and sorts this variable by global index ---*/ if (rank == MASTER_NODE) { jPoint = 0; for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { for (iPoint = 0; iPoint < Buffer_Recv_nPoint[iProcessor]; iPoint++) { - + /*--- Get global index, then loop over each variable and store ---*/ iGlobal_Index = Buffer_Recv_GlobalIndex[jPoint]; Data[iVar][iGlobal_Index] = Buffer_Recv_Var[jPoint]; @@ -4017,26 +4017,26 @@ void COutputLegacy::MergeBaselineSolution(CConfig *config, CGeometry *geometry, } } } - + /*--- Immediately release the temporary buffers. ---*/ - + delete [] Buffer_Send_Var; delete [] Buffer_Send_GlobalIndex; if (rank == MASTER_NODE) { delete [] Buffer_Recv_Var; delete [] Buffer_Recv_GlobalIndex; } - + #endif - + delete [] Local_Halo; - + } void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) { - + /*--- Local variables ---*/ - + unsigned short nZone = geometry->GetnZone(); unsigned short Kind_Solver = config->GetKind_Solver(); unsigned short iVar, iDim, nDim = geometry->GetnDim(); @@ -4049,9 +4049,9 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s ofstream meta_file; string filename, meta_filename; bool adjoint = config->GetContinuous_Adjoint() || config->GetDiscrete_Adjoint(); - + /*--- Retrieve filename from config ---*/ - + // if (((config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint())) && ((config->GetKind_Solver() != DISC_ADJ_FEM))) { // filename = config->GetRestart_AdjFileName(); // filename = config->GetObjFunc_Extension(filename); @@ -4062,11 +4062,11 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s // } else { // filename = config->GetRestart_FileName(); // } - + /*--- Append the zone number if multizone problems ---*/ if (nZone > 1) filename= config->GetMultizone_FileName(filename, val_iZone, ".dat"); - + /*--- Unsteady problems require an iteration number to be appended. ---*/ if (config->GetTime_Marching() == HARMONIC_BALANCE) { filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(config->GetiInst()), ".dat"); @@ -4075,31 +4075,31 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s } else if ((fem || disc_adj_fem) && (config->GetWrt_Dynamic())) { filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter), ".dat"); } - + /*--- Open the restart file and write the solution. ---*/ - + restart_file.open(filename.c_str(), ios::out); restart_file.precision(15); - + /*--- Write the header line based on the particular solver ----*/ - + restart_file << "\"PointID\""; - + /*--- Mesh coordinates are always written to the restart first ---*/ - + if (nDim == 2) { restart_file << "\t\"x\"\t\"y\""; } else { restart_file << "\t\"x\"\t\"y\"\t\"z\""; } - + for (iVar = 0; iVar < nVar_Consv; iVar++) { if (( Kind_Solver == FEM_ELASTICITY ) || ( Kind_Solver == DISC_ADJ_FEM)) restart_file << "\t\"Displacement_" << iVar+1<<"\""; else restart_file << "\t\"Conservative_" << iVar+1<<"\""; } - + if (config->GetWrt_Limiters()) { for (iVar = 0; iVar < nVar_Consv; iVar++) { restart_file << "\t\"Limiter_" << iVar+1<<"\""; @@ -4110,9 +4110,9 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s restart_file << "\t\"Residual_" << iVar+1<<"\""; } } - + /*--- Mesh velocities for dynamic mesh cases ---*/ - + if (dynamic_grid && !fem) { if (nDim == 2) { restart_file << "\t\"Grid_Velx\"\t\"Grid_Vely\""; @@ -4120,7 +4120,7 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s restart_file << "\t\"Grid_Velx\"\t\"Grid_Vely\"\t\"Grid_Velz\""; } } - + if ((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS) || (Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) { if (config->GetTabular_FileFormat() == TAB_CSV) { @@ -4128,7 +4128,7 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s } else restart_file << "\t\"Pressure\"\t\"Temperature\"\t\"Cp\"\t\"Mach\""; } - + if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) { if (config->GetTabular_FileFormat() == TAB_CSV) { @@ -4139,21 +4139,21 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s if (nDim == 3) restart_file << "\t\"m\"\t\"Cf_x\"\t\"Cf_y\"\t\"Cf_z\"\t\"h\"\t\"y+\""; } } - + if (Kind_Solver == RANS || Kind_Solver == INC_RANS) { if ((config->GetTabular_FileFormat() == TAB_CSV)) { restart_file << "\t\"Eddy_Viscosity\""; } else restart_file << "\t\"mt\""; } - + if (config->GetWrt_SharpEdges()) { if (((Kind_Solver == EULER) || (Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) || ((Kind_Solver == INC_EULER) || (Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS))) { restart_file << "\t\"Sharp_Edge_Dist\""; } } - + if ((Kind_Solver == ADJ_EULER ) || (Kind_Solver == ADJ_NAVIER_STOKES ) || (Kind_Solver == ADJ_RANS ) ) { @@ -4170,7 +4170,7 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s restart_file << "\t\"Sensitivity_z\""; } } - + if (Kind_Solver == FEM_ELASTICITY) { if (!dynamic_fem) { if (geometry->GetnDim() == 2) @@ -4189,21 +4189,21 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s } } } - + if ((Kind_Solver == DISC_ADJ_FEM) && (config->GetFSI_Simulation())){ if (geometry->GetnDim() == 2) restart_file << "\t\"CrossTerm_1\"\t\"CrossTerm_2\""; if (geometry->GetnDim() == 3) restart_file << "\t\"CrossTerm_1\"\t\"CrossTerm_2\"\t\"CrossTerm_3\""; } - - + + if (config->GetExtraOutput()) { string *headings = NULL; //if (Kind_Solver == RANS) { headings = solver[TURB_SOL]->OutputHeadingNames; //} - + for (iVar = 0; iVar < nVar_Extra; iVar++) { if (headings == NULL) { restart_file << "\t\"ExtraOutput_" << iVar+1<<"\""; @@ -4212,36 +4212,36 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s } } } - - + + restart_file << "\n"; - + /*--- Write the restart file ---*/ - + /*--- Determine whether or not the FEM solver is used, which decides the type of geometry classes that are instantiated. ---*/ bool fem_solver = ((config->GetKind_Solver() == FEM_EULER) || (config->GetKind_Solver() == FEM_NAVIER_STOKES) || (config->GetKind_Solver() == FEM_RANS) || (config->GetKind_Solver() == FEM_LES)); - + unsigned long nPointTotal = 0; if ( fem_solver ) { nPointTotal = solver[FLOW_SOL]->GetnDOFsGlobal(); } else { nPointTotal = geometry->GetGlobal_nPointDomain(); } - + for (iPoint = 0; iPoint < nPointTotal; iPoint++) { - + /*--- Index of the point ---*/ restart_file << iPoint << "\t"; - + /*--- Write the grid coordinates first ---*/ for (iDim = 0; iDim < nDim; iDim++) { restart_file << scientific << Coords[iDim][iPoint] << "\t"; } - + /*--- Loop over the variables and write the values to file ---*/ for (iVar = 0; iVar < nVar_Total; iVar++) { restart_file << scientific << Data[iVar][iPoint] << "\t"; @@ -4271,15 +4271,15 @@ void COutputLegacy::SetRestart(CConfig *config, CGeometry *geometry, CSolver **s } void COutputLegacy::DeallocateCoordinates(CConfig *config, CGeometry *geometry) { - + unsigned short iDim, nDim = geometry->GetnDim(); - + /*--- The master node alone owns all data found in this routine. ---*/ - + if (rank == MASTER_NODE) { - + /*--- Deallocate memory for coordinate data ---*/ - + for (iDim = 0; iDim < nDim; iDim++) { delete [] Coords[iDim]; } @@ -4291,7 +4291,7 @@ void COutputLegacy::DeallocateConnectivity(CConfig *config, CGeometry *geometry, /*--- The master node alone owns all data found in this routine. ---*/ if (rank == MASTER_NODE) { - + /*--- Deallocate memory for connectivity data ---*/ if (surf_sol) { if (nGlobal_Line > 0 && Conn_Line != NULL) delete [] Conn_Line; @@ -4305,9 +4305,9 @@ void COutputLegacy::DeallocateConnectivity(CConfig *config, CGeometry *geometry, if (nGlobal_Hexa > 0 && Conn_Hexa != NULL) delete [] Conn_Hexa; if (nGlobal_Pris > 0 && Conn_Pris != NULL) delete [] Conn_Pris; if (nGlobal_Pyra > 0 && Conn_Pyra != NULL) delete [] Conn_Pyra; - + } - + } } @@ -4315,13 +4315,13 @@ void COutputLegacy::DeallocateSolution(CConfig *config, CGeometry *geometry) { /*--- The master node alone owns all data found in this routine. ---*/ if (rank == MASTER_NODE) { - + /*--- Deallocate memory for solution data ---*/ for (unsigned short iVar = 0; iVar < nVar_Total; iVar++) { delete [] Data[iVar]; } delete [] Data; - + } } @@ -4329,7 +4329,7 @@ void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *conf char cstr[200], turb_resid[1000], adj_turb_resid[1000]; unsigned short iMarker_Monitoring; string Monitoring_Tag, monitoring_coeff, aeroelastic_coeff, turbo_coeff; - + bool rotating_frame = config->GetRotating_Frame(); bool aeroelastic = config->GetAeroelastic_Simulation(); bool equiv_area = config->GetEquivArea(); @@ -4343,7 +4343,7 @@ void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *conf bool disc_adj = config->GetDiscrete_Adjoint(); bool frozen_visc = (cont_adj && config->GetFrozen_Visc_Cont()) ||( disc_adj && config->GetFrozen_Visc_Disc()); bool inv_design = (config->GetInvDesign_Cp() || config->GetInvDesign_HeatFlux()); - + bool output_surface = (config->GetnMarker_Analyze() != 0); bool output_comboObj = (config->GetnObj() > 1); bool output_per_surface = config->GetWrt_Surface(); @@ -4361,34 +4361,34 @@ void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *conf config->GetKind_Solver() == INC_RANS || config->GetKind_Solver() == INC_NAVIER_STOKES) { thermal = true; } - + /*--- Write file name with extension ---*/ string filename = config->GetConv_FileName(); string hist_ext = ".csv"; if (config->GetTabular_FileFormat() == TAB_TECPLOT) hist_ext = ".dat"; - + if(config->GetnZone() > 1){ filename = config->GetMultizone_HistoryFileName(filename, val_iZone, hist_ext); } if(config->GetnTimeInstances() > 1){ filename = config->GetMultiInstance_HistoryFileName(filename, val_iInst); } - + if (config->GetTime_Domain() && config->GetRestart()) { filename = config->GetUnsteady_FileName(filename, config->GetRestart_Iter(), hist_ext); } - + strcpy (cstr, filename.data()); ConvHist_file->open(cstr, ios::out); ConvHist_file->precision(15); - + /*--- Begin of the header ---*/ - + char begin[]= "\"Iteration\""; - + /*--- Header for the coefficients ---*/ - + char flow_coeff[]= ",\"CL\",\"CD\",\"CSF\",\"CMx\",\"CMy\",\"CMz\",\"CFx\",\"CFy\",\"CFz\",\"CL/CD\",\"AoA\",\"Custom_ObjFunc\""; char heat_coeff[]= ",\"HeatFlux_Total\",\"HeatFlux_Maximum\",\"Temperature_Total\""; char equivalent_area_coeff[]= ",\"CEquivArea\",\"CNearFieldOF\""; @@ -4410,7 +4410,7 @@ void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *conf char d_surface_outputs[]= ",\"D(Uniformity)\",\"D(Secondary_Strength)\",\"D(Momentum_Distortion)\",\"D(Secondary_Over_Uniformity)\",\"D(Pressure_Drop)\""; /*--- Find the markers being monitored and create a header for them ---*/ - + for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { Monitoring_Tag = config->GetMarker_Monitoring_TagBound(iMarker_Monitoring); monitoring_coeff += ",\"CL_" + Monitoring_Tag + "\""; @@ -4455,13 +4455,13 @@ void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *conf } char combo_obj[] = ",\"ComboObj\""; - + /*--- Header for the residuals ---*/ - + char flow_resid[]= ",\"Res_Flow[0]\",\"Res_Flow[1]\",\"Res_Flow[2]\",\"Res_Flow[3]\",\"Res_Flow[4]\""; char adj_flow_resid[]= ",\"Res_AdjFlow[0]\",\"Res_AdjFlow[1]\",\"Res_AdjFlow[2]\",\"Res_AdjFlow[3]\",\"Res_AdjFlow[4]\""; switch (config->GetKind_Turb_Model()) { - case SA:case SA_NEG:case SA_E: case SA_COMP: case SA_E_COMP: + case SA:case SA_NEG:case SA_E: case SA_COMP: case SA_E_COMP: SPRINTF (turb_resid, ",\"Res_Turb[0]\""); break; case SST:case SST_SUST: @@ -4478,22 +4478,22 @@ void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *conf } char fem_resid[]= ",\"Res_FEM[0]\",\"Res_FEM[1]\",\"Res_FEM[2]\""; char heat_resid[]= ",\"Res_Heat\""; - + /*--- End of the header ---*/ - + char end[]= ",\"Linear_Solver_Iterations\",\"CFL_Number\",\"Time(min)\"\n"; char endfea[]= ",\"Linear_Solver_Iterations\",\"Time(min)\"\n"; - + if ((config->GetTabular_FileFormat() == TECPLOT) || (config->GetTabular_FileFormat() == TECPLOT_BINARY)) { ConvHist_file[0] << "TITLE = \"SU2 Simulation\"" << endl; ConvHist_file[0] << "VARIABLES = "; } - + /*--- Write the header, case depending ---*/ - + switch (config->GetKind_Solver()) { - + case EULER : case NAVIER_STOKES: case RANS : case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS : case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_RANS : case FEM_LES: @@ -4525,9 +4525,9 @@ void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *conf } if (output_comboObj) ConvHist_file[0] << combo_obj; ConvHist_file[0] << end; - + break; - + case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS: case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS: case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: @@ -4548,13 +4548,13 @@ void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *conf ConvHist_file[0] << begin << heat_coeff; ConvHist_file[0] << heat_resid << end; break; - + case FEM_ELASTICITY: ConvHist_file[0] << begin << fem_coeff; if (incload) ConvHist_file[0] << fem_incload; ConvHist_file[0] << fem_resid << endfea; break; - + case DISC_ADJ_FEM: ConvHist_file[0] << begin << fem_coeff; ConvHist_file[0] << fem_resid << endfea; @@ -4566,7 +4566,7 @@ void COutputLegacy::SetConvHistory_Header(ofstream *ConvHist_file, CConfig *conf config->GetTabular_FileFormat() == TECPLOT_BINARY) { ConvHist_file[0] << "ZONE T= \"Convergence history\"" << endl; } - + } @@ -4579,7 +4579,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, su2double timeused, unsigned short val_iZone, unsigned short val_iInst) { - + bool output_surface = (config[val_iZone]->GetnMarker_Analyze() != 0); bool output_comboObj = (config[val_iZone]->GetnObj() > 1); bool fluid_structure = (config[val_iZone]->GetFSI_Simulation()); @@ -4600,27 +4600,27 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, bool incompressible = (config[val_iZone]->GetKind_Regime() == INCOMPRESSIBLE); if (!disc_adj && !cont_adj && !DualTime_Iteration) { - + if (fixed_cl && - (solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetStart_AoA_FD()) && + (solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetStart_AoA_FD()) && (iExtIter != solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetIter_Update_AoA())) { output_files = false; } - + if (fea || fluid_structure) output_files = false; /*--- We need to evaluate some of the objective functions to write the value on the history file ---*/ - + if (((iExtIter % (config[val_iZone]->GetWrt_Sol_Freq())) == 0) || (!fixed_cl && (iExtIter == (config[val_iZone]->GetnInner_Iter()-1))) || /*--- If CL mode we need to compute the complete solution at two very particular iterations ---*/ (fixed_cl && (iExtIter == (config[val_iZone]->GetnInner_Iter()-2) || - (solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetStart_AoA_FD() && + (solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetStart_AoA_FD() && iExtIter == solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL]->GetIter_Update_AoA())))) { - + if ((rank == MASTER_NODE) && output_files) cout << endl << "------------------------ Evaluate Special Output ------------------------"; - + switch (config[val_iZone]->GetKind_Solver()) { case EULER: case NAVIER_STOKES: case RANS: @@ -4645,45 +4645,45 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, SpecialOutput_SonicBoom(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL], geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files); } - + /*--- For specific applications, evaluate and plot the cp coefficent at different stations. ---*/ - + if (config[val_iZone]->GetPlot_Section_Forces()) { SpecialOutput_SpanLoad(solver_container[val_iZone][val_iInst][MESH_0][FLOW_SOL], geometry[val_iZone][val_iInst][MESH_0], config[val_iZone], output_files); } - + break; } - + /*--- Output a file with the forces breakdown. ---*/ - + if (config[val_iZone]->GetTime_Marching() == HARMONIC_BALANCE) { SpecialOutput_HarmonicBalance(solver_container, geometry, config, val_iInst, nInst, output_files); } - + /*--- Compute span-wise values file for turbomachinery. ---*/ - + if (config[val_iZone]->GetBoolTurbomachinery()) { SpecialOutput_Turbo(solver_container, geometry, config, val_iZone, output_files); } - + /*--- Output a file with the forces breakdown. ---*/ - + SpecialOutput_ForcesBreakdown(solver_container, geometry, config, val_iZone, output_files); - + if ((rank == MASTER_NODE) && output_files) cout << "-------------------------------------------------------------------------" << endl << endl; - + } - + } - + /*--- Output using only the master node ---*/ - + if (rank == MASTER_NODE) { - + /*-- Compute the total objective if a "combo" objective is used ---*/ - + if (output_comboObj) { solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->SetTotal_ComboObj(0.0); switch (config[val_iZone]->GetKind_Solver()) { @@ -4693,7 +4693,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, break; } } - + unsigned long ExtIter_OffSet = config[val_iZone]->GetExtIter_OffSet(); if (config[val_iZone]->GetTime_Marching() == DT_STEPPING_1ST || config[val_iZone]->GetTime_Marching() == DT_STEPPING_2ND) @@ -4701,7 +4701,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, /*--- WARNING: These buffers have hard-coded lengths. Note that you may have to adjust them to be larger if adding more entries. ---*/ - + char begin[1000], direct_coeff[1000], heat_coeff[1000], equivalent_area_coeff[1000], engine_coeff[1000], rotating_frame_coeff[1000], Cp_inverse_design[1000], Heat_inverse_design[1000], surface_coeff[1000], aeroelastic_coeff[1000], monitoring_coeff[10000], buffet_coeff[1000], adjoint_coeff[1000], flow_resid[1000], adj_flow_resid[1000], turb_resid[1000], trans_resid[1000], adj_turb_resid[1000], @@ -4711,13 +4711,13 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, su2double dummy = 0.0, *Coord; unsigned short iVar, iMarker_Monitoring; - + unsigned long LinSolvIter = 0, iPointMaxResid; su2double timeiter = timeused/su2double(iExtIter+1); - + unsigned short nDim = geometry[val_iZone][val_iInst][FinestMesh]->GetnDim(); - + bool rotating_frame = config[val_iZone]->GetRotating_Frame(); bool aeroelastic = config[val_iZone]->GetAeroelastic_Simulation(); bool equiv_area = config[val_iZone]->GetEquivArea(); @@ -4735,26 +4735,26 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, bool heat = ((config[val_iZone]->GetKind_Solver() == HEAT_EQUATION) || (config[val_iZone]->GetWeakly_Coupled_Heat())); bool weakly_coupled_heat = config[val_iZone]->GetWeakly_Coupled_Heat(); bool flow = (config[val_iZone]->GetKind_Solver() == EULER) || (config[val_iZone]->GetKind_Solver() == NAVIER_STOKES) || - (config[val_iZone]->GetKind_Solver() == RANS) || (config[val_iZone]->GetKind_Solver() == FEM_EULER) || - (config[val_iZone]->GetKind_Solver() == FEM_NAVIER_STOKES) || (config[val_iZone]->GetKind_Solver() == FEM_RANS) || + (config[val_iZone]->GetKind_Solver() == RANS) || (config[val_iZone]->GetKind_Solver() == FEM_EULER) || + (config[val_iZone]->GetKind_Solver() == FEM_NAVIER_STOKES) || (config[val_iZone]->GetKind_Solver() == FEM_RANS) || (config[val_iZone]->GetKind_Solver() == FEM_LES) || (config[val_iZone]->GetKind_Solver() == ADJ_EULER) || (config[val_iZone]->GetKind_Solver() == ADJ_NAVIER_STOKES) || (config[val_iZone]->GetKind_Solver() == ADJ_RANS) || (config[val_iZone]->GetKind_Solver() == INC_EULER) || (config[val_iZone]->GetKind_Solver() == INC_NAVIER_STOKES) || (config[val_iZone]->GetKind_Solver() == INC_RANS); bool buffet = (config[val_iZone]->GetBuffet_Monitoring() || config[val_iZone]->GetKind_ObjFunc() == BUFFET_SENSOR); - + bool fem = ((config[val_iZone]->GetKind_Solver() == FEM_ELASTICITY) || // FEM structural solver. (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM)); bool linear_analysis = (config[val_iZone]->GetGeometricConditions() == SMALL_DEFORMATIONS); // Linear analysis. bool nonlinear_analysis = (config[val_iZone]->GetGeometricConditions() == LARGE_DEFORMATIONS); // Nonlinear analysis. bool fsi = (config[val_iZone]->GetFSI_Simulation()); // FEM structural solver. bool discadj_fem = (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM); - + bool turbo = config[val_iZone]->GetBoolTurbomachinery(); unsigned short nTurboPerf = config[val_iZone]->GetnMarker_TurboPerformance(); - bool output_per_surface = config[val_iZone]->GetWrt_Surface(); + bool output_per_surface = config[val_iZone]->GetWrt_Surface(); unsigned short direct_diff = config[val_iZone]->GetDirectDiff(); @@ -4777,7 +4777,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } /*--- Initialize variables to store information from all domains (direct solution) ---*/ - + su2double Total_CL = 0.0, Total_CD = 0.0, Total_CSF = 0.0, Total_CMx = 0.0, Total_CMy = 0.0, Total_CMz = 0.0, Total_CEff = 0.0, Total_CEquivArea = 0.0, Total_CNearFieldOF = 0.0, Total_CFx = 0.0, Total_CFy = 0.0, Total_CFz = 0.0, Total_CMerit = 0.0, Total_CT = 0.0, Total_CQ = 0.0, @@ -4802,9 +4802,9 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, su2double D_Total_CL = 0.0, D_Total_CD = 0.0, D_Total_CSF = 0.0, D_Total_CMx = 0.0, D_Total_CMy = 0.0, D_Total_CMz = 0.0, D_Total_CEff = 0.0, D_Total_CFx = 0.0, D_Total_CFy = 0.0, D_Total_CFz = 0.0, D_Total_NetThrust = 0.0, D_Total_Power = 0.0, D_Total_AeroCD = 0.0, D_Total_SolidCD = 0.0, D_Total_IDR = 0.0, D_Total_IDC = 0.0, D_Total_Custom_ObjFunc = 0.0, D_Total_Heat = 0.0, D_Total_MaxHeat = 0.0, D_TotalPressure_Loss = 0.0, D_FlowAngle_Out = 0.0, D_TotalStaticEfficiency = 0.0, - D_TotalTotalEfficiency = 0.0, D_EntropyGen = 0.0, + D_TotalTotalEfficiency = 0.0, D_EntropyGen = 0.0, D_Surface_Uniformity = 0.0, D_Surface_SecondaryStrength = 0.0, D_Surface_MomentumDistortion = 0.0, D_Surface_SecondOverUniform = 0.0, D_Surface_PressureDrop = 0.0; - + /*--- Residual arrays ---*/ su2double *residual_flow = NULL, *residual_turbulent = NULL, @@ -4815,7 +4815,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, su2double *residual_fea = NULL; su2double *residual_fem = NULL; su2double *residual_heat = NULL; - + /*--- Coefficients Monitored arrays ---*/ su2double *aeroelastic_plunge = NULL, *aeroelastic_pitch = NULL, @@ -4830,13 +4830,13 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, *Surface_CMy = NULL, *Surface_CMz = NULL, *Surface_Buffet_Metric = NULL; - + /*--- Initialize number of variables ---*/ unsigned short nVar_Flow = 0, nVar_Turb = 0, nVar_Trans = 0, nVar_Heat = 0, nVar_AdjFlow = 0, nVar_AdjTurb = 0, nVar_AdjHeat = 0, nVar_FEM = 0; - + /*--- Direct problem variables ---*/ if (compressible) nVar_Flow = nDim+2; else nVar_Flow = nDim+2; if (turbulent) { @@ -4855,7 +4855,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, if (config[val_iZone]->GetKind_Solver() == DISC_ADJ_FEM) nVar_FEM = nDim; } - + /*--- Adjoint problem variables ---*/ if (compressible) nVar_AdjFlow = nDim+2; else nVar_AdjFlow = nDim+2; if (turbulent) { @@ -4865,18 +4865,18 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } } if (weakly_coupled_heat) nVar_AdjHeat = 1; - + /*--- Allocate memory for the residual ---*/ residual_flow = new su2double[nVar_Flow]; residual_turbulent = new su2double[nVar_Turb]; residual_transition = new su2double[nVar_Trans]; residual_heat = new su2double[nVar_Heat]; residual_fem = new su2double[nVar_FEM]; - + residual_adjflow = new su2double[nVar_AdjFlow]; residual_adjturbulent = new su2double[nVar_AdjTurb]; residual_adjheat = new su2double[nVar_AdjHeat]; - + /*--- Allocate memory for the coefficients being monitored ---*/ aeroelastic_plunge = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; aeroelastic_pitch = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; @@ -4891,20 +4891,20 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, Surface_CMy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CMz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; if(buffet) Surface_Buffet_Metric = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; - + /*--- Write information from nodes ---*/ - + switch (config[val_iZone]->GetKind_Solver()) { - + case EULER: case NAVIER_STOKES: case RANS: - case INC_EULER: case INC_NAVIER_STOKES: case INC_RANS: + case INC_EULER: case INC_NAVIER_STOKES: case INC_RANS: case FEM_EULER: case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES: case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS: case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS: case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: - + /*--- Flow solution coefficients ---*/ - + Total_CL = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CL(); Total_CD = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CD(); Total_CSF = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CSF(); @@ -4930,7 +4930,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, Total_Temperature = solver_container[val_iZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_AvgTemperature(); } } - + if(buffet){ Total_Buffet_Metric = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_Buffet_Metric(); } @@ -4962,17 +4962,17 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, D_Total_IDR = SU2_TYPE::GetDerivative(Total_IDR); D_Total_IDC = SU2_TYPE::GetDerivative(Total_IDC); } - + } - + if (equiv_area) { Total_CEquivArea = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CEquivArea(); Total_CNearFieldOF = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CNearFieldOF(); - + Total_CEquivArea = config[val_iZone]->GetWeightCd()*Total_CD + (1.0-config[val_iZone]->GetWeightCd())*Total_CEquivArea; Total_CNearFieldOF = config[val_iZone]->GetWeightCd()*Total_CD + (1.0-config[val_iZone]->GetWeightCd())*Total_CNearFieldOF; } - + if (engine || actuator_disk) { Total_NetThrust = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_NetThrust(); Total_Power = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_Power(); @@ -4981,13 +4981,13 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, Total_IDR = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_IDR(); Total_IDC = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_IDC(); } - + if (rotating_frame) { Total_CT = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CT(); Total_CQ = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CQ(); Total_CMerit = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CMerit(); } - + if (aeroelastic) { /*--- Look over the markers being monitored and get the desired values ---*/ for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) { @@ -4995,7 +4995,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, aeroelastic_pitch[iMarker_Monitoring] = config[val_iZone]->GetAeroelastic_pitch(iMarker_Monitoring); } } - + if (output_per_surface) { /*--- Look over the markers being monitored and get the desired values ---*/ for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) { @@ -5009,11 +5009,11 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, Surface_CMx[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CMx(iMarker_Monitoring); Surface_CMy[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CMy(iMarker_Monitoring); Surface_CMz[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_CMz(iMarker_Monitoring); - + if(buffet) Surface_Buffet_Metric[iMarker_Monitoring] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetSurface_Buffet_Metric(iMarker_Monitoring); } } - + if (turbo) { /*--- Loop over the nMarker of turboperformance and get the desired values ---*/ for (iMarker_Monitoring = 0; iMarker_Monitoring < nTurboPerf; iMarker_Monitoring++) { @@ -5030,7 +5030,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, D_EntropyGen = SU2_TYPE::GetDerivative(EntropyGen[nTurboPerf-1][nSpanWiseSections]); } } - + /*--- Get flux-averaged values at the specified surface ---*/ if (output_surface) { @@ -5059,14 +5059,14 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, D_Surface_PressureDrop = SU2_TYPE::GetDerivative(Surface_PressureDrop); } } - + /*--- Flow Residuals ---*/ - + for (iVar = 0; iVar < nVar_Flow; iVar++) residual_flow[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetRes_RMS(iVar); - + /*--- Turbulent residual ---*/ - + if (turbulent) { for (iVar = 0; iVar < nVar_Turb; iVar++) residual_turbulent[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][TURB_SOL]->GetRes_RMS(iVar); @@ -5078,31 +5078,31 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } } - + /*--- Transition residual ---*/ - + if (transition) { for (iVar = 0; iVar < nVar_Trans; iVar++) residual_transition[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][TRANS_SOL]->GetRes_RMS(iVar); } - - + + /*--- FEA residual ---*/ // if (fluid_structure) { // for (iVar = 0; iVar < nVar_FEA; iVar++) // residual_fea[iVar] = solver_container[ZONE_0][FinestMesh][FEA_SOL]->GetRes_RMS(iVar); // } - + /*--- Iterations of the linear solver ---*/ - + LinSolvIter = (unsigned long) solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetIterLinSolver(); - + /*--- Adjoint solver ---*/ - + if (adjoint) { - + /*--- Adjoint solution coefficients ---*/ - + Total_Sens_Geo = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Geo(); Total_Sens_Mach = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_Mach(); Total_Sens_AoA = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_AoA() * PI_NUMBER / 180.0; @@ -5112,13 +5112,13 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, Total_Sens_ModVel = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetTotal_Sens_ModVel(); /*--- Adjoint flow residuals ---*/ - + for (iVar = 0; iVar < nVar_AdjFlow; iVar++) { residual_adjflow[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][ADJFLOW_SOL]->GetRes_RMS(iVar); } - + /*--- Adjoint turbulent residuals ---*/ - + if (turbulent) { if (!frozen_visc) { for (iVar = 0; iVar < nVar_AdjTurb; iVar++) @@ -5131,11 +5131,11 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, residual_adjheat[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][ADJHEAT_SOL]->GetRes_RMS(iVar); } } - + } - + break; - + case HEAT_EQUATION: @@ -5152,13 +5152,13 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } break; - + case FEM_ELASTICITY: - + /*--- FEM coefficients -- As of now, this is the Von Mises Stress ---*/ - + Total_VMStress = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetTotal_CFEA(); - + Total_ForceCoeff = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetForceCoeff(); Total_IncLoad = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetLoad_Increment(); @@ -5168,7 +5168,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, /*--- Residuals: ---*/ /*--- Linear analysis: RMS of the displacements in the nDim coordinates ---*/ /*--- Nonlinear analysis: UTOL, RTOL and DTOL (defined in the Postprocessing function) ---*/ - + if (linear_analysis) { for (iVar = 0; iVar < nVar_FEM; iVar++) { residual_fem[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetRes_RMS(iVar); @@ -5179,7 +5179,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, residual_fem[iVar] = solver_container[val_iZone][val_iInst][FinestMesh][FEA_SOL]->GetRes_FEM(iVar); } } - + break; case DISC_ADJ_FEM: @@ -5205,9 +5205,9 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, //Extra_Total_Temperature = solver_container[ExtraHeatOutputZone][val_iInst][FinestMesh][HEAT_SOL]->GetTotal_Temperature(); Extra_Heat_Residual = log10(solver_container[ExtraHeatOutputZone][val_iInst][FinestMesh][HEAT_SOL]->GetRes_RMS(0)); } - + /*--- Header frequency ---*/ - + bool Unsteady = ((config[val_iZone]->GetTime_Marching() == DT_STEPPING_1ST) || (config[val_iZone]->GetTime_Marching() == DT_STEPPING_2ND)); bool In_NoDualTime = (!DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0)); @@ -5215,7 +5215,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, bool In_DualTime_1 = (!DualTime_Iteration && Unsteady); bool In_DualTime_2 = (Unsteady && DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0)); bool In_DualTime_3 = (Unsteady && !DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0)); - + /*--- Header frequency: analogy for dynamic structural analysis ---*/ /*--- DualTime_Iteration is a bool we receive, which is true if it comes from FEM_StructuralIteration and false from SU2_CFD ---*/ /*--- We maintain the name, as it is an input of the function ---*/ @@ -5227,13 +5227,13 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, bool In_Dynamic_1 = (!DualTime_Iteration && nonlinear_analysis); bool In_Dynamic_2 = (nonlinear_analysis && DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0)); bool In_Dynamic_3 = (nonlinear_analysis && !DualTime_Iteration && (iExtIter % config[val_iZone]->GetWrt_Con_Freq() == 0)); - + bool write_heads; if (Unsteady) write_heads = (iIntIter == 0); else write_heads = (((iExtIter % (config[val_iZone]->GetWrt_Con_Freq()*40)) == 0)); - + bool write_turbo = (((iExtIter % (config[val_iZone]->GetWrt_Con_Freq()*40)) == 0) || (iExtIter == (config[val_iZone]->GetnInner_Iter() -1))); - + /*--- Analogous for dynamic problems (as of now I separate the problems, it may be worthy to do all together later on ---*/ bool write_heads_FEM; if (nonlinear_analysis) write_heads_FEM = (iIntIter == 0); @@ -5242,28 +5242,28 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, if ( (!fem && ((In_NoDualTime || In_DualTime_0 || In_DualTime_1) && (In_NoDualTime || In_DualTime_2 || In_DualTime_3))) || (fem && ( (In_NoDynamic || In_Dynamic_0 || In_Dynamic_1) && (In_NoDynamic || In_Dynamic_2 || In_Dynamic_3))) ) { - - + + /*--- Prepare the history file output, note that the dual time output don't write to the history file ---*/ if (!DualTime_Iteration) { - + /*--- Write the begining of the history file ---*/ SPRINTF(begin, "%12d", SU2_TYPE::Int(iExtIter+ExtIter_OffSet)); - + /*--- Write the end of the history file ---*/ SPRINTF (end, ", %12.10f, %12.10f, %12.10f\n", su2double(LinSolvIter), config[val_iZone]->GetCFL(MESH_0), timeused/60.0); - + /*--- Write the solution and residual of the history file ---*/ switch (config[val_iZone]->GetKind_Solver()) { - + case EULER : case NAVIER_STOKES: case RANS: - case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS: + case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS: case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES: case ADJ_EULER: case ADJ_NAVIER_STOKES: case ADJ_RANS: case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS: case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: - + /*--- Direct coefficients ---*/ SPRINTF (direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", Total_CL, Total_CD, Total_CSF, Total_CMx, Total_CMy, Total_CMz, Total_CFx, Total_CFy, @@ -5277,7 +5277,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, SPRINTF (Cp_inverse_design, ", %14.8e", solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_CpDiff()); if (thermal && !turbo) SPRINTF (Heat_inverse_design, ", %14.8e", solver_container[val_iZone][val_iInst][FinestMesh][FLOW_SOL]->GetTotal_HeatFluxDiff()); } - + if (direct_diff != NO_DERIVATIVE) { if (!turbo) SPRINTF (d_direct_coeff, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", @@ -5310,7 +5310,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, strcat(aeroelastic_coeff, surface_coeff); } } - + if (output_per_surface) { for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) { //Append one by one the surface coeff to monitoring coeff. (Think better way do this, maybe use string) @@ -5339,7 +5339,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, strcat(monitoring_coeff, surface_coeff); SPRINTF(surface_coeff, ", %12.10f", Surface_CMz[iMarker_Monitoring]); strcat(monitoring_coeff, surface_coeff); - + if(buffet){ SPRINTF(surface_coeff, ", %12.10f", Surface_Buffet_Metric[iMarker_Monitoring]); strcat(monitoring_coeff, surface_coeff); @@ -5387,8 +5387,8 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } } - - + + /*--- Flow residual ---*/ if (nDim == 2) { if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), dummy); @@ -5398,7 +5398,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, if (compressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), log10 (residual_flow[4]) ); if (incompressible) SPRINTF (flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_flow[0]), log10 (residual_flow[1]), log10 (residual_flow[2]), log10 (residual_flow[3]), log10 (residual_flow[4])); } - + /*--- Turbulent residual ---*/ if (turbulent) { switch(nVar_Turb) { @@ -5406,18 +5406,18 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, case 2: SPRINTF (turb_resid, ", %12.10f, %12.10f", log10(residual_turbulent[0]), log10(residual_turbulent[1])); break; } } - + /*---- Averaged stagnation pressure at an exit ----*/ - + if (output_surface) { SPRINTF( surface_outputs, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", Surface_MassFlow, Surface_Mach, Surface_Temperature, Surface_Pressure, Surface_Density, Surface_Enthalpy, Surface_NormalVelocity, Surface_Uniformity, Surface_SecondaryStrength, Surface_MomentumDistortion, Surface_SecondOverUniform, Surface_TotalTemperature, Surface_TotalPressure, Surface_PressureDrop); if (direct_diff != NO_DERIVATIVE) { - SPRINTF( d_surface_outputs, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", + SPRINTF( d_surface_outputs, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", D_Surface_Uniformity, D_Surface_SecondaryStrength, D_Surface_MomentumDistortion, D_Surface_SecondOverUniform, D_Surface_PressureDrop); } } - + /*--- Transition residual ---*/ if (transition) { SPRINTF (trans_resid, ", %12.10f, %12.10f", log10(residual_transition[0]), log10(residual_transition[1])); @@ -5435,7 +5435,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, // } if (adjoint) { - + /*--- Adjoint coefficients ---*/ if (!turbo) { if (compressible) { @@ -5456,7 +5456,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, if (compressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]), log10 (residual_adjflow[4]) ); if (incompressible) SPRINTF (adj_flow_resid, ", %14.8e, %14.8e, %14.8e, %14.8e, %14.8e", log10 (residual_adjflow[0]), log10 (residual_adjflow[1]), log10 (residual_adjflow[2]), log10 (residual_adjflow[3]), log10 (residual_adjflow[4])); } - + /*--- Adjoint turbulent residuals ---*/ if (turbulent) if (!frozen_visc) { @@ -5472,7 +5472,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, if (weakly_coupled_heat) { SPRINTF (heat_resid, ", %14.8e", log10 (residual_heat[0])); } - + break; case HEAT_EQUATION: @@ -5481,9 +5481,9 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, SPRINTF (heat_resid, ", %14.8e", log10 (residual_heat[0])); break; - + case FEM_ELASTICITY: - + SPRINTF (begin_fem, ", %14.8e", 0.0); if (incload) SPRINTF (fem_coeff, ", %14.8e, %14.8e, %14.8e", Total_VMStress, Total_ForceCoeff, Total_IncLoad); @@ -5524,7 +5524,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, if (!Unsteady && (config[val_iZone]->GetTime_Marching() != TIME_STEPPING)) { switch (config[val_iZone]->GetKind_Solver()) { case EULER : case NAVIER_STOKES: case RANS: - case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS: + case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS: case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_RANS: case FEM_LES: case ADJ_EULER : case ADJ_NAVIER_STOKES: case ADJ_RANS: @@ -5593,7 +5593,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS: case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: - + cout << endl; cout << "------------------------ Discrete Adjoint Summary -----------------------" << endl; cout << "Total Geometry Sensitivity (updated every " << config[val_iZone]->GetWrt_Sol_Freq() << " iterations): "; @@ -5628,7 +5628,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, switch (config[val_iZone]->GetKind_Solver()) { case EULER : case NAVIER_STOKES: - case INC_EULER : case INC_NAVIER_STOKES: + case INC_EULER : case INC_NAVIER_STOKES: case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES: /*--- Visualize the maximum residual ---*/ @@ -5671,7 +5671,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, else if (rotating_frame && nDim == 3 && !turbo) cout << " Res[Rho]" << " Res[RhoE]" << " CThrust(Total)" << " CTorque(Total)" << endl; else if (aeroelastic) cout << " Res[Rho]" << " Res[RhoE]" << " CLift(Total)" << " CDrag(Total)" << " plunge" << " pitch" << endl; else if (equiv_area) cout << " Res[Rho]" << " CLift(Total)" << " CDrag(Total)" << " CPress(N-F)" << endl; - + else if (turbo){ if(nZone < 2){ @@ -5683,7 +5683,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, cout << " Res[Rho]" << " Res[RhoE]" << " TTEfficiency(%)" << " Entropy Gen.(%)"; } } - + else if (actuator_disk) cout << " Res[Rho]" << " Res[RhoE]" << " CL(Total)" << " CD-CT(Total)"; else if (engine) cout << " Res[Rho]" << " Res[RhoE]" << " CL(Total)" << " CD-CT(Total)"; else cout << " Res[Rho]" << " Res[RhoE]" << " CL(Total)" << " CD(Total)"; @@ -5914,7 +5914,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } /*--- Write the solution on the screen ---*/ - + if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){ cout.precision(6); cout.setf(ios::fixed, ios::floatfield); @@ -5945,14 +5945,14 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } } } - + switch (config[val_iZone]->GetKind_Solver()) { case EULER : case NAVIER_STOKES: - case INC_EULER : case INC_NAVIER_STOKES: + case INC_EULER : case INC_NAVIER_STOKES: case FEM_EULER : case FEM_NAVIER_STOKES: case FEM_LES: - + /*--- Write history file ---*/ - + if ((!DualTime_Iteration) && (output_files)) { if (!turbo) { config[val_iZone]->GetHistFile()[0] << begin << direct_coeff; @@ -5971,7 +5971,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, else { config[val_iZone]->GetHistFile()[0] << begin << turbo_coeff << flow_resid; } - + if (aeroelastic) config[val_iZone]->GetHistFile()[0] << aeroelastic_coeff; if (output_per_surface) config[val_iZone]->GetHistFile()[0] << monitoring_coeff; if (output_surface) config[val_iZone]->GetHistFile()[0] << surface_outputs; @@ -6015,7 +6015,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, cout << Total_CNearFieldOF; } else if (turbo) { cout.setf(ios::scientific, ios::floatfield); - + if (nZone < 2) { cout.width(15); cout << TotalPressureLoss[0][nSpanWiseSections]*100.0; cout.width(15); cout << EntropyGen[0][nSpanWiseSections]*100.0; @@ -6024,9 +6024,9 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, cout.width(15); cout << TotalTotalEfficiency[nTurboPerf -1][nSpanWiseSections]*100.0; cout.width(15); cout << EntropyGen[nTurboPerf -1][nSpanWiseSections]*100.0; } - + cout.unsetf(ios_base::floatfield); - + } else if (weakly_coupled_heat) { cout.width(14); cout << log10(Total_Heat); } else { cout.width(15); cout << min(10000.0, max(-10000.0, Total_CL)); cout.width(15); cout << min(10000.0, max(-10000.0, Total_CD)); } @@ -6039,15 +6039,15 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, if (extra_heat_output) { cout.width(15); cout << Extra_Heat_Residual; cout.width(15); cout << Extra_Total_Heat; } cout << endl; - + } } break; - + case RANS : case INC_RANS: - + /*--- Write history file ---*/ - + if ((!DualTime_Iteration) && (output_files)) { if (!turbo) { @@ -6067,7 +6067,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, else { config[val_iZone]->GetHistFile()[0] << begin << turbo_coeff << flow_resid << turb_resid; } - + if (aeroelastic) config[val_iZone]->GetHistFile()[0] << aeroelastic_coeff; if (output_per_surface) config[val_iZone]->GetHistFile()[0] << monitoring_coeff; if (output_surface) config[val_iZone]->GetHistFile()[0] << surface_outputs; @@ -6079,7 +6079,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, config[val_iZone]->GetHistFile()[0] << end; config[val_iZone]->GetHistFile()[0].flush(); } - + /*--- Write screen output ---*/ if ((val_iZone == 0 && val_iInst == 0)|| fluid_structure){ @@ -6140,11 +6140,11 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } if (extra_heat_output) { cout.width(15); cout << Extra_Heat_Residual; cout.width(15); cout << Extra_Total_Heat; } - cout << endl; + cout << endl; } } break; - + case HEAT_EQUATION: @@ -6155,11 +6155,11 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, break; case FEM_ELASTICITY: - + if (!DualTime_Iteration) { config[val_iZone]->GetHistFile()[0] << begin << fem_coeff << fem_resid << end_fem; config[val_iZone]->GetHistFile()[0].flush(); - + cout.precision(6); cout.setf(ios::fixed, ios::floatfield); if (linear_analysis) { @@ -6172,14 +6172,14 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, cout.width(14); cout << log10(residual_fem[1]); cout.width(14); cout << log10(residual_fem[2]); } - + cout.precision(4); cout.setf(ios::scientific, ios::floatfield); cout.width(14); cout << Total_VMStress; cout << endl; } break; - + case DISC_ADJ_FEM: cout.precision(6); @@ -6217,7 +6217,7 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, case ADJ_EULER : case ADJ_NAVIER_STOKES : case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: - + if (!DualTime_Iteration) { config[val_iZone]->GetHistFile()[0] << begin << adjoint_coeff << adj_flow_resid << end; config[val_iZone]->GetHistFile()[0].flush(); @@ -6267,9 +6267,9 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } } break; - + case ADJ_RANS : case DISC_ADJ_RANS: case DISC_ADJ_INC_RANS: - + if (!DualTime_Iteration) { config[val_iZone]->GetHistFile()[0] << begin << adjoint_coeff << adj_flow_resid; if (!frozen_visc) @@ -6326,12 +6326,12 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, } } break; - + } cout.unsetf(ios::fixed); } - + delete [] residual_flow; delete [] residual_turbulent; @@ -6355,16 +6355,16 @@ void COutputLegacy::SetConvHistory_Body(ofstream *ConvHist_file, delete [] Surface_CMz; delete [] aeroelastic_pitch; delete [] aeroelastic_plunge; - + } } void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short val_iZone, bool output) { - + char cstr[200]; unsigned short iDim, iMarker_Monitoring; ofstream Breakdown_file; - + bool compressible = (config[val_iZone]->GetKind_Regime() == COMPRESSIBLE); bool incompressible = (config[val_iZone]->GetKind_Regime() == INCOMPRESSIBLE); bool unsteady = (config[val_iZone]->GetTime_Marching() != NO); @@ -6385,15 +6385,15 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry (config[val_iZone]->GetKind_Solver() == INC_EULER) || (config[val_iZone]->GetKind_Solver() == INC_NAVIER_STOKES) || (config[val_iZone]->GetKind_Solver() == INC_RANS)); - + /*--- Output the mean flow solution using only the master node ---*/ - + if ((rank == MASTER_NODE) && (flow) && (output)) { - + cout << endl << "Writing the forces breakdown file ("<< config[val_iZone]->GetBreakdown_FileName() << ")." << endl; - + /*--- Initialize variables to store information from all domains (direct solution) ---*/ - + su2double Total_CL = 0.0, Total_CD = 0.0, Total_CSF = 0.0, Total_CMx = 0.0, Total_CMy = 0.0, Total_CMz = 0.0, Total_CEff = 0.0, Total_CoPx = 0.0, Total_CoPy = 0.0, Total_CoPz = 0.0, @@ -6425,14 +6425,14 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry *Surface_CEff_Mnt = NULL, *Surface_CFx_Mnt = NULL, *Surface_CFy_Mnt = NULL, *Surface_CFz_Mnt = NULL, *Surface_CMx_Mnt = NULL, *Surface_CMy_Mnt = NULL, *Surface_CMz_Mnt = NULL; - + /*--- WARNING: when compiling on Windows, ctime() is not available. Comment out the two lines below that use the dt variable. ---*/ //time_t now = time(0); //string dt = ctime(&now); dt[24] = '.'; - + /*--- Allocate memory for the coefficients being monitored ---*/ - + Surface_CL = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CD = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CSF = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; @@ -6443,7 +6443,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Surface_CMx = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CMy = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CMz = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; - + Surface_CL_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CD_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CSF_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; @@ -6454,7 +6454,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Surface_CMx_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CMy_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CMz_Inv = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; - + Surface_CL_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CD_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CSF_Visc = @@ -6466,8 +6466,8 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Surface_CMx_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CMy_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CMz_Visc = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; - - + + Surface_CL_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CD_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; Surface_CSF_Mnt = @@ -6481,7 +6481,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Surface_CMz_Mnt = new su2double[config[ZONE_0]->GetnMarker_Monitoring()]; /*--- Flow solution coefficients ---*/ - + Total_CL = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CL(); Total_CD = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CD(); Total_CSF = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CSF(); @@ -6492,7 +6492,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Total_CFx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx(); Total_CFy = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFy(); Total_CFz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFz(); - + if (nDim == 2) { Total_CoPx = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPx() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFy(); Total_CoPy = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPy() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx(); @@ -6503,11 +6503,11 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Total_CoPy = 0.0; Total_CoPz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CoPz() / solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx(); } - + if (config[ZONE_0]->GetSystemMeasurements() == US) { Total_CoPx *= 12.0; Total_CoPy *= 12.0; Total_CoPz *= 12.0; } - + /*--- Flow inviscid solution coefficients ---*/ - + Inv_CL = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CL_Inv(); Inv_CD = @@ -6528,9 +6528,9 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFy_Inv(); Inv_CFz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFz_Inv(); - + /*--- Flow viscous solution coefficients ---*/ - + Visc_CL = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CL_Visc(); Visc_CD = @@ -6551,9 +6551,9 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFy_Visc(); Visc_CFz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFz_Visc(); - + /*--- Flow momentum solution coefficients ---*/ - + Mnt_CL = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CL_Mnt(); Mnt_CD = @@ -6574,10 +6574,10 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFy_Mnt(); Mnt_CFz = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetAllBound_CFz_Mnt(); - - + + /*--- Look over the markers being monitored and get the desired values ---*/ - + for (iMarker_Monitoring = 0; iMarker_Monitoring < config[ZONE_0]->GetnMarker_Monitoring(); iMarker_Monitoring++) { @@ -6611,7 +6611,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Surface_CFz[iMarker_Monitoring] = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz( iMarker_Monitoring); - + Surface_CL_Inv[iMarker_Monitoring] = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL_Inv( iMarker_Monitoring); @@ -6672,7 +6672,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Surface_CFz_Visc[iMarker_Monitoring] = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz_Visc( iMarker_Monitoring); - + Surface_CL_Mnt[iMarker_Monitoring] = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CL_Mnt( iMarker_Monitoring); @@ -6703,17 +6703,17 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Surface_CFz_Mnt[iMarker_Monitoring] = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetSurface_CFz_Mnt( iMarker_Monitoring); - + } - - + + /*--- Write file name with extension ---*/ - + string filename = config[val_iZone]->GetBreakdown_FileName(); strcpy (cstr, filename.data()); - + Breakdown_file.open(cstr, ios::out); - + Breakdown_file << "\n" <<"-------------------------------------------------------------------------" << "\n"; Breakdown_file <<"| ___ _ _ ___ |" << "\n"; Breakdown_file <<"| / __| | | |_ ) Release 6.1.0 \"Falcon\" |" << "\n"; @@ -6752,11 +6752,11 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "| You should have received a copy of the GNU Lesser General Public |" << "\n"; Breakdown_file << "| License along with SU2. If not, see . |" << "\n"; Breakdown_file <<"-------------------------------------------------------------------------" << "\n"; - + Breakdown_file.precision(6); Breakdown_file << "\n" << "\n" << "Problem definition:" << "\n" << "\n"; - + switch (Kind_Solver) { case EULER: case INC_EULER: if (compressible) Breakdown_file << "Compressible Euler equations." << "\n"; @@ -6795,7 +6795,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry (Kind_Solver == RANS) || (Kind_Solver == ADJ_RANS)) Breakdown_file << "Reynolds number: " << config[val_iZone]->GetReynolds() <<"."<< "\n"; } - + if (fixed_cl) { Breakdown_file << "Simulation at a cte. CL: " << config[val_iZone]->GetTarget_CL() << ".\n"; Breakdown_file << "Approx. Delta CL / Delta AoA: " << config[val_iZone]->GetdCL_dAlpha() << " (1/deg).\n"; @@ -6806,17 +6806,17 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry } Breakdown_file << "Approx. Delta CMz / Delta CL: " << config[val_iZone]->GetdCMz_dCL() << ".\n"; } - + if (Ref_NonDim == DIMENSIONAL) { Breakdown_file << "Dimensional simulation." << "\n"; } else if (Ref_NonDim == FREESTREAM_PRESS_EQ_ONE) { Breakdown_file << "Non-Dimensional simulation (P=1.0, Rho=1.0, T=1.0 at the farfield)." << "\n"; } else if (Ref_NonDim == FREESTREAM_VEL_EQ_MACH) { Breakdown_file << "Non-Dimensional simulation (V=Mach, Rho=1.0, T=1.0 at the farfield)." << "\n"; } else if (Ref_NonDim == FREESTREAM_VEL_EQ_ONE) { Breakdown_file << "Non-Dimensional simulation (V=1.0, Rho=1.0, T=1.0 at the farfield)." << "\n"; } - + if (config[val_iZone]->GetSystemMeasurements() == SI) { Breakdown_file << "The reference area is " << config[val_iZone]->GetRefArea() << " m^2." << "\n"; Breakdown_file << "The reference length is " << config[val_iZone]->GetRefLength() << " m." << "\n"; } - + if (config[val_iZone]->GetSystemMeasurements() == US) { Breakdown_file << "The reference area is " << config[val_iZone]->GetRefArea()*12.0*12.0 << " in^2." << "\n"; Breakdown_file << "The reference length is " << config[val_iZone]->GetRefLength()*12.0 << " in." << "\n"; @@ -6832,10 +6832,10 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "temperature and pressure using the ideal gas law." << "\n"; } } - + if (dynamic_grid) Breakdown_file << "Force coefficients computed using MACH_MOTION." << "\n"; else Breakdown_file << "Force coefficients computed using free-stream values." << "\n"; - + if (incompressible) { Breakdown_file << "Viscous and Inviscid flow: rho_ref, and vel_ref" << "\n"; Breakdown_file << "are based on the free-stream values, p_ref = rho_ref*vel_ref^2." << "\n"; @@ -6846,12 +6846,12 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry if (viscous) Breakdown_file << "Reynolds number: " << config[val_iZone]->GetReynolds() << ", computed using free-stream values."<< "\n"; Breakdown_file << "Only dimensional computation, the grid should be dimensional." << "\n"; } - + Breakdown_file <<"-- Input conditions:"<< "\n"; - + if (compressible) { switch (config[val_iZone]->GetKind_FluidModel()) { - + case STANDARD_AIR: Breakdown_file << "Fluid Model: STANDARD_AIR "<< "\n"; Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant(); @@ -6860,14 +6860,14 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n"; Breakdown_file << "Specific Heat Ratio: 1.4000 "<< "\n"; break; - + case IDEAL_GAS: Breakdown_file << "Fluid Model: IDEAL_GAS "<< "\n"; Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << "\n"; Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND()<< "\n"; Breakdown_file << "Specific Heat Ratio: "<< config[val_iZone]->GetGamma() << "\n"; break; - + case VW_GAS: Breakdown_file << "Fluid Model: Van der Waals "<< "\n"; Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << "\n"; @@ -6878,7 +6878,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "Critical Pressure (non-dim): " << config[val_iZone]->GetPressure_Critical() /config[val_iZone]->GetPressure_Ref() << "\n"; Breakdown_file << "Critical Temperature (non-dim) : " << config[val_iZone]->GetTemperature_Critical() /config[val_iZone]->GetTemperature_Ref() << "\n"; break; - + case PR_GAS: Breakdown_file << "Fluid Model: Peng-Robinson "<< "\n"; Breakdown_file << "Specific gas constant: " << config[val_iZone]->GetGas_Constant() << " N.m/kg.K." << "\n"; @@ -6890,11 +6890,11 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "Critical Temperature (non-dim) : " << config[val_iZone]->GetTemperature_Critical() /config[val_iZone]->GetTemperature_Ref() << "\n"; break; } - + if (viscous) { - + switch (config[val_iZone]->GetKind_ViscosityModel()) { - + case CONSTANT_VISCOSITY: Breakdown_file << "Viscosity Model: CONSTANT_VISCOSITY "<< "\n"; Breakdown_file << "Laminar Viscosity: " << config[val_iZone]->GetMu_Constant(); @@ -6902,7 +6902,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.s/ft^2." << "\n"; Breakdown_file << "Laminar Viscosity (non-dim): " << config[val_iZone]->GetMu_ConstantND()<< "\n"; break; - + case SUTHERLAND: Breakdown_file << "Viscosity Model: SUTHERLAND "<< "\n"; Breakdown_file << "Ref. Laminar Viscosity: " << config[val_iZone]->GetMu_Ref(); @@ -6918,23 +6918,23 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "Ref. Temperature (non-dim): " << config[val_iZone]->GetMu_Temperature_RefND()<< "\n"; Breakdown_file << "Sutherland constant (non-dim): "<< config[val_iZone]->GetMu_SND()<< "\n"; break; - + } switch (config[val_iZone]->GetKind_ConductivityModel()) { - + case CONSTANT_PRANDTL: Breakdown_file << "Conductivity Model: CONSTANT_PRANDTL "<< "\n"; Breakdown_file << "Prandtl: " << config[val_iZone]->GetPrandtl_Lam()<< "\n"; break; - + case CONSTANT_CONDUCTIVITY: Breakdown_file << "Conductivity Model: CONSTANT_CONDUCTIVITY "<< "\n"; Breakdown_file << "Molecular Conductivity: " << config[val_iZone]->GetKt_Constant()<< " W/m^2.K." << "\n"; Breakdown_file << "Molecular Conductivity (non-dim): " << config[val_iZone]->GetKt_ConstantND()<< "\n"; break; - + } - + if ((Kind_Solver == RANS) || (Kind_Solver == ADJ_RANS) || (Kind_Solver == DISC_ADJ_RANS)) { switch (config[val_iZone]->GetKind_ConductivityModel_Turb()) { case CONSTANT_PRANDTL_TURB: @@ -6947,10 +6947,10 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry break; } } - + } } - + if (incompressible) { Breakdown_file << "Bulk modulus: " << config[val_iZone]->GetBulk_Modulus(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n"; @@ -6959,29 +6959,29 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n"; } - + Breakdown_file << "Free-stream static pressure: " << config[val_iZone]->GetPressure_FreeStream(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n"; - + Breakdown_file << "Free-stream total pressure: " << config[val_iZone]->GetPressure_FreeStream() * pow( 1.0+config[val_iZone]->GetMach()*config[val_iZone]->GetMach()*0.5*(config[val_iZone]->GetGamma()-1.0), config[val_iZone]->GetGamma()/(config[val_iZone]->GetGamma()-1.0) ); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n"; - + if (compressible) { Breakdown_file << "Free-stream temperature: " << config[val_iZone]->GetTemperature_FreeStream(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n"; - + Breakdown_file << "Free-stream total temperature: " << config[val_iZone]->GetTemperature_FreeStream() * (1.0 + config[val_iZone]->GetMach() * config[val_iZone]->GetMach() * 0.5 * (config[val_iZone]->GetGamma() - 1.0)); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n"; } - + Breakdown_file << "Free-stream density: " << config[val_iZone]->GetDensity_FreeStream(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n"; - + if (nDim == 2) { Breakdown_file << "Free-stream velocity: (" << config[val_iZone]->GetVelocity_FreeStream()[0] << ", "; Breakdown_file << config[val_iZone]->GetVelocity_FreeStream()[1] << ")"; @@ -6992,17 +6992,17 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry } if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s. "; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s. "; - + Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStream(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n"; - + if (compressible) { Breakdown_file << "Free-stream total energy per unit mass: " << config[val_iZone]->GetEnergy_FreeStream(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n"; } - + if (viscous) { Breakdown_file << "Free-stream viscosity: " << config[val_iZone]->GetViscosity_FreeStream(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n"; @@ -7016,49 +7016,49 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " 1/s." << "\n"; } } - + if (unsteady) { Breakdown_file << "Total time: " << config[val_iZone]->GetTotal_UnstTime() << " s. Time step: " << config[val_iZone]->GetDelta_UnstTime() << " s." << "\n"; } - + /*--- Print out reference values. ---*/ - + Breakdown_file <<"-- Reference values:"<< "\n"; - + if (compressible) { Breakdown_file << "Reference specific gas constant: " << config[val_iZone]->GetGas_Constant_Ref(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.m/kg.K." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf.ft/slug.R." << "\n"; } - + Breakdown_file << "Reference pressure: " << config[val_iZone]->GetPressure_Ref(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << "\n"; - + if (compressible) { Breakdown_file << "Reference temperature: " << config[val_iZone]->GetTemperature_Ref(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " K." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " R." << "\n"; } - + Breakdown_file << "Reference density: " << config[val_iZone]->GetDensity_Ref(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " kg/m^3." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " slug/ft^3." << "\n"; - + Breakdown_file << "Reference velocity: " << config[val_iZone]->GetVelocity_Ref(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m/s." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft/s." << "\n"; - + if (compressible) { Breakdown_file << "Reference energy per unit mass: " << config[val_iZone]->GetEnergy_Ref(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m^2/s^2." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " ft^2/s^2." << "\n"; } - + if (incompressible) { Breakdown_file << "Reference length: " << config[val_iZone]->GetLength_Ref(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n"; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " in." << "\n"; } - + if (viscous) { Breakdown_file << "Reference viscosity: " << config[val_iZone]->GetViscosity_Ref(); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " N.s/m^2." << "\n"; @@ -7069,12 +7069,12 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " lbf/ft.s.R." << "\n"; } } - - + + if (unsteady) Breakdown_file << "Reference time: " << config[val_iZone]->GetTime_Ref() <<" s." << "\n"; - + /*--- Print out resulting non-dim values here. ---*/ - + Breakdown_file << "-- Resulting non-dimensional state:" << "\n"; Breakdown_file << "Mach number (non-dim): " << config[val_iZone]->GetMach() << "\n"; if (viscous) { @@ -7086,16 +7086,16 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "Froude number (non-dim): " << config[val_iZone]->GetFroude() << "\n"; Breakdown_file << "Lenght of the baseline wave (non-dim): " << 2.0*PI_NUMBER*config[val_iZone]->GetFroude()*config[val_iZone]->GetFroude() << "\n"; } - + if (compressible) { Breakdown_file << "Specific gas constant (non-dim): " << config[val_iZone]->GetGas_ConstantND() << "\n"; Breakdown_file << "Free-stream temperature (non-dim): " << config[val_iZone]->GetTemperature_FreeStreamND() << "\n"; } - + Breakdown_file << "Free-stream pressure (non-dim): " << config[val_iZone]->GetPressure_FreeStreamND() << "\n"; - + Breakdown_file << "Free-stream density (non-dim): " << config[val_iZone]->GetDensity_FreeStreamND() << "\n"; - + if (nDim == 2) { Breakdown_file << "Free-stream velocity (non-dim): (" << config[val_iZone]->GetVelocity_FreeStreamND()[0] << ", "; Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << "). "; @@ -7104,10 +7104,10 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << ", " << config[val_iZone]->GetVelocity_FreeStreamND()[2] << "). "; } Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStreamND() << "\n"; - + if (compressible) Breakdown_file << "Free-stream total energy per unit mass (non-dim): " << config[val_iZone]->GetEnergy_FreeStreamND() << "\n"; - + if (viscous) { Breakdown_file << "Free-stream viscosity (non-dim): " << config[val_iZone]->GetViscosity_FreeStreamND() << "\n"; if (turbulent) { @@ -7115,7 +7115,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "Free-stream specific dissipation (non-dim): " << config[val_iZone]->GetOmega_FreeStreamND() << "\n"; } } - + if (unsteady) { Breakdown_file << "Total time (non-dim): " << config[val_iZone]->GetTotal_UnstTimeND() << "\n"; Breakdown_file << "Time step (non-dim): " << config[val_iZone]->GetDelta_UnstTimeND() << "\n"; @@ -7210,7 +7210,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " Pa." << endl; else if (config[val_iZone]->GetSystemMeasurements() == US) Breakdown_file << " psf." << endl; break; - + case INC_IDEAL_GAS_POLY: Breakdown_file << "Fluid Model: INC_IDEAL_GAS_POLY "<< endl; Breakdown_file << "Variable density incompressible flow using ideal gas law." << endl; @@ -7262,7 +7262,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "Ref. Temperature (non-dim): " << config[val_iZone]->GetMu_Temperature_RefND()<< "\n"; Breakdown_file << "Sutherland constant (non-dim): "<< config[val_iZone]->GetMu_SND()<< "\n"; break; - + case POLYNOMIAL_VISCOSITY: Breakdown_file << "Viscosity Model: POLYNOMIAL_VISCOSITY "<< endl; Breakdown_file << "Mu(T) polynomial coefficients: \n ("; @@ -7310,9 +7310,9 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry } Breakdown_file << ")." << endl; break; - + } - + if ((Kind_Solver == RANS) || (Kind_Solver == ADJ_RANS) || (Kind_Solver == DISC_ADJ_RANS)) { switch (config[val_iZone]->GetKind_ConductivityModel_Turb()) { case CONSTANT_PRANDTL_TURB: @@ -7325,7 +7325,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry break; } } - + } } @@ -7461,7 +7461,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << config[val_iZone]->GetVelocity_FreeStreamND()[1] << ", " << config[val_iZone]->GetVelocity_FreeStreamND()[2] << "). "; } Breakdown_file << "Magnitude: " << config[val_iZone]->GetModVel_FreeStreamND() << "\n"; - + if (viscous) { Breakdown_file << "Initial viscosity (non-dim): " << config[val_iZone]->GetViscosity_FreeStreamND() << "\n"; if (turbulent) { @@ -7469,7 +7469,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "Initial specific dissipation (non-dim): " << config[val_iZone]->GetOmega_FreeStreamND() << "\n"; } } - + if (unsteady) { Breakdown_file << "Total time (non-dim): " << config[val_iZone]->GetTotal_UnstTimeND() << "\n"; Breakdown_file << "Time step (non-dim): " << config[val_iZone]->GetDelta_UnstTimeND() << "\n"; @@ -7478,14 +7478,14 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry } /*--- Begin forces breakdown info. ---*/ - + Breakdown_file << fixed; Breakdown_file << "\n" << "\n" <<"Forces breakdown:" << "\n" << "\n"; if (nDim == 3) { su2double m = solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFz()/solver[val_iZone][INST_0][FinestMesh][FLOW_SOL]->GetTotal_CFx(); su2double term = (Total_CoPz/m)-Total_CoPx; - + if (term > 0) Breakdown_file << "Center of Pressure: X=" << 1/m <<"Z-"<< term << "." << "\n\n"; else Breakdown_file << "Center of Pressure: X=" << 1/m <<"Z+"<< fabs(term); if (config[val_iZone]->GetSystemMeasurements() == SI) Breakdown_file << " m." << "\n\n"; @@ -7547,7 +7547,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "%): "; Breakdown_file.width(11); Breakdown_file << Mnt_CL << "\n"; - + Breakdown_file << "Total CD: "; Breakdown_file.width(11); Breakdown_file << Total_CD; @@ -7566,7 +7566,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << SU2_TYPE::Int((Mnt_CD * 100.0) / (Total_CD + EPS)) << "%): "; Breakdown_file.width(11); Breakdown_file << Mnt_CD << "\n"; - + if (nDim == 3) { Breakdown_file << "Total CSF: "; Breakdown_file.width(11); @@ -7590,7 +7590,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file.width(11); Breakdown_file << Mnt_CSF << "\n"; } - + Breakdown_file << "Total CL/CD: "; Breakdown_file.width(11); Breakdown_file << Total_CEff; @@ -7612,7 +7612,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "%): "; Breakdown_file.width(11); Breakdown_file << Mnt_CEff << "\n"; - + if (nDim == 3) { Breakdown_file << "Total CMx: "; Breakdown_file.width(11); @@ -7635,7 +7635,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "%): "; Breakdown_file.width(11); Breakdown_file << Mnt_CMx << "\n"; - + Breakdown_file << "Total CMy: "; Breakdown_file.width(11); Breakdown_file << Total_CMy; @@ -7658,7 +7658,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file.width(11); Breakdown_file << Mnt_CMy << "\n"; } - + Breakdown_file << "Total CMz: "; Breakdown_file.width(11); Breakdown_file << Total_CMz; @@ -7680,7 +7680,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "%): "; Breakdown_file.width(11); Breakdown_file << Mnt_CMz << "\n"; - + Breakdown_file << "Total CFx: "; Breakdown_file.width(11); Breakdown_file << Total_CFx; @@ -7702,7 +7702,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "%): "; Breakdown_file.width(11); Breakdown_file << Mnt_CFx << "\n"; - + Breakdown_file << "Total CFy: "; Breakdown_file.width(11); Breakdown_file << Total_CFy; @@ -7724,7 +7724,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "%): "; Breakdown_file.width(11); Breakdown_file << Mnt_CFy << "\n"; - + if (nDim == 3) { Breakdown_file << "Total CFz: "; Breakdown_file.width(11); @@ -7748,17 +7748,17 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file.width(11); Breakdown_file << Mnt_CFz << "\n"; } - + Breakdown_file << "\n" << "\n"; - + for (iMarker_Monitoring = 0; iMarker_Monitoring < config[val_iZone]->GetnMarker_Monitoring(); iMarker_Monitoring++) { - + Breakdown_file << "Surface name: " << config[val_iZone]->GetMarker_Monitoring_TagBound( iMarker_Monitoring) << "\n" << "\n"; - + Breakdown_file << "Total CL ("; Breakdown_file.width(5); Breakdown_file @@ -7795,7 +7795,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "%): "; Breakdown_file.width(11); Breakdown_file << Surface_CL_Mnt[iMarker_Monitoring] << "\n"; - + Breakdown_file << "Total CD ("; Breakdown_file.width(5); Breakdown_file @@ -7832,7 +7832,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << "%): "; Breakdown_file.width(11); Breakdown_file << Surface_CD_Mnt[iMarker_Monitoring] << "\n"; - + if (nDim == 3) { Breakdown_file << "Total CSF ("; Breakdown_file.width(5); @@ -7873,7 +7873,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << Surface_CSF_Mnt[iMarker_Monitoring] << "\n"; } - + Breakdown_file << "Total CL/CD ("; Breakdown_file.width(5); Breakdown_file @@ -7911,9 +7911,9 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file.width(11); Breakdown_file << Surface_CEff_Mnt[iMarker_Monitoring] << "\n"; - + if (nDim == 3) { - + Breakdown_file << "Total CMx ("; Breakdown_file.width(5); Breakdown_file @@ -7951,7 +7951,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file.width(11); Breakdown_file << Surface_CMx_Mnt[iMarker_Monitoring] << "\n"; - + Breakdown_file << "Total CMy ("; Breakdown_file.width(5); Breakdown_file @@ -7990,7 +7990,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file << Surface_CMy_Mnt[iMarker_Monitoring] << "\n"; } - + Breakdown_file << "Total CMz ("; Breakdown_file.width(5); Breakdown_file @@ -8027,7 +8027,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file.width(11); Breakdown_file << Surface_CMz_Mnt[iMarker_Monitoring] << "\n"; - + Breakdown_file << "Total CFx ("; Breakdown_file.width(5); Breakdown_file @@ -8064,7 +8064,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file.width(11); Breakdown_file << Surface_CFx_Mnt[iMarker_Monitoring] << "\n"; - + Breakdown_file << "Total CFy ("; Breakdown_file.width(5); Breakdown_file @@ -8101,7 +8101,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file.width(11); Breakdown_file << Surface_CFy_Mnt[iMarker_Monitoring] << "\n"; - + if (nDim == 3) { Breakdown_file << "Total CFz ("; Breakdown_file.width(5); @@ -8140,14 +8140,14 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry Breakdown_file.width(11); Breakdown_file << Surface_CFz_Mnt[iMarker_Monitoring] << "\n"; - + } - + Breakdown_file << "\n"; - - + + } - + delete [] Surface_CL; delete [] Surface_CD; delete [] Surface_CSF; @@ -8158,7 +8158,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry delete [] Surface_CMx; delete [] Surface_CMy; delete [] Surface_CMz; - + delete [] Surface_CL_Inv; delete [] Surface_CD_Inv; delete [] Surface_CSF_Inv; @@ -8169,7 +8169,7 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry delete [] Surface_CMx_Inv; delete [] Surface_CMy_Inv; delete [] Surface_CMz_Inv; - + delete [] Surface_CL_Visc; delete [] Surface_CD_Visc; delete [] Surface_CSF_Visc; @@ -8193,20 +8193,20 @@ void COutputLegacy::SpecialOutput_ForcesBreakdown(CSolver *****solver, CGeometry delete [] Surface_CMz_Mnt; Breakdown_file.close(); - + } - + } void COutputLegacy::SetResult_Files(CSolver *****solver_container, CGeometry ****geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone) { - + unsigned short iZone; - + for (iZone = 0; iZone < val_nZone; iZone++) { - + /*--- Flags identifying the types of files to be written. ---*/ - + bool Wrt_Vol = config[iZone]->GetWrt_Vol_Sol(); bool Wrt_Srf = config[iZone]->GetWrt_Srf_Sol(); bool Wrt_Csv = config[iZone]->GetWrt_Csv_Sol(); @@ -8214,53 +8214,53 @@ void COutputLegacy::SetResult_Files(CSolver *****solver_container, CGeometry *** #ifdef HAVE_MPI /*--- Do not merge the volume solutions if we are running in parallel. Force the use of SU2_SOL to merge the volume sols in this case. ---*/ - + SU2_MPI::Comm_size(MPI_COMM_WORLD, &size); if (size > SINGLE_NODE) { Wrt_Vol = false; Wrt_Srf = false; } #endif - + if (rank == MASTER_NODE) cout << endl << "Writing comma-separated values (CSV) surface files." << endl; - + switch (config[iZone]->GetKind_Solver()) { - + case EULER : case NAVIER_STOKES : case RANS : - case INC_EULER : case INC_NAVIER_STOKES : case INC_RANS : + case INC_EULER : case INC_NAVIER_STOKES : case INC_RANS : case FEM_EULER : case FEM_NAVIER_STOKES : case FEM_RANS : case FEM_LES : - + if (Wrt_Csv) SetSurfaceCSV_Flow(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0][FLOW_SOL], iExtIter, iZone, INST_0); break; - + case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS : case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: case DISC_ADJ_INC_EULER: if (Wrt_Csv) SetSurfaceCSV_Adjoint(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0][ADJFLOW_SOL], solver_container[iZone][INST_0][MESH_0][FLOW_SOL], iExtIter, iZone, INST_0); break; - + } - + /*--- Get the file output format ---*/ - + unsigned short FileFormat = config[iZone]->GetTabular_FileFormat(); - + /*--- Merge the node coordinates and connectivity, if necessary. This is only performed if a volume solution file is requested, and it is active by default. ---*/ - + if (Wrt_Vol || Wrt_Srf) { if (rank == MASTER_NODE) cout << "Merging connectivities in the Master node." << endl; MergeConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], iZone); } - + /*--- Merge coordinates of all grid nodes (excluding ghost points). The grid coordinates are always merged and included first in the restart files. ---*/ - + if (rank == MASTER_NODE) cout << "Merging coordinates in the Master node." << endl; MergeCoordinates(config[iZone], geometry[iZone][INST_0][MESH_0]); - + if ((rank == MASTER_NODE) && (Wrt_Vol || Wrt_Srf)) { if (FileFormat == TECPLOT_BINARY) { if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume and surface mesh files." << endl; @@ -8272,143 +8272,143 @@ void COutputLegacy::SetResult_Files(CSolver *****solver_container, CGeometry *** DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], wrote_surf_file); } } - + /*--- Merge the solution data needed for volume solutions and restarts ---*/ - + if (rank == MASTER_NODE) cout << "Merging solution in the Master node." << endl; MergeSolution(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0], iZone); - + /*--- Write restart, or Tecplot files using the merged data. This data lives only on the master, and these routines are currently executed by the master proc alone (as if in serial). ---*/ - + if (rank == MASTER_NODE) { - + /*--- Write a native restart file ---*/ - + if (rank == MASTER_NODE) cout << "Writing SU2 native restart file." << endl; SetRestart(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0] , iZone); - + if (Wrt_Vol) { - + switch (FileFormat) { - + case TECPLOT: - + /*--- Write a Tecplot ASCII file ---*/ - + if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII file volume solution file." << endl; // SetTecplotASCII(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0], iZone, val_nZone, false); DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false); break; - - - + + + case TECPLOT_BINARY: - + /*--- Write a Tecplot binary solution file ---*/ - + if (rank == MASTER_NODE) cout << "Writing Tecplot binary volume solution file." << endl; // SetTecplotBinary_DomainSolution(config[iZone], geometry[iZone][INST_0][MESH_0], iZone); break; - - + + case PARAVIEW: - + /*--- Write a Paraview ASCII file ---*/ - + if (rank == MASTER_NODE) cout << "Writing Paraview ASCII volume solution file." << endl; // SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, false); DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false); break; - + case PARAVIEW_BINARY: - + /*--- Write a ParaView ASCII file instead for now in serial. ---*/ - + if (rank == MASTER_NODE) cout << "ParaView binary volume files not available in this mode." << endl; if (rank == MASTER_NODE) cout << " Writing ParaView ASCII volume solution file instead." << endl; // SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, false); DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], false); break; - + default: break; } - + } - + if (Wrt_Srf) { - + switch (FileFormat) { - + case TECPLOT: - + /*--- Write a Tecplot ASCII file ---*/ - + if (rank == MASTER_NODE) cout << "Writing Tecplot ASCII surface solution file." << endl; // SetTecplotASCII(config[iZone], geometry[iZone][INST_0][MESH_0], solver_container[iZone][INST_0][MESH_0] , iZone, val_nZone, true); DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], true); break; - + case TECPLOT_BINARY: - + /*--- Write a Tecplot binary solution file ---*/ - + if (rank == MASTER_NODE) cout << "Writing Tecplot binary surface solution file." << endl; // SetTecplotBinary_SurfaceSolution(config[iZone], geometry[iZone][INST_0][MESH_0], iZone); break; - + case PARAVIEW: - + /*--- Write a Paraview ASCII file ---*/ - + if (rank == MASTER_NODE) cout << "Writing Paraview ASCII surface solution file." << endl; // SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, true); DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], true); break; - + case PARAVIEW_BINARY: - + /*--- Write a ParaView ASCII file instead for now in serial. ---*/ - + if (rank == MASTER_NODE) cout << "ParaView binary surface files not available in this mode." << endl; if (rank == MASTER_NODE) cout << " Writing ParaView ASCII surface solution file instead." << endl; // SetParaview_ASCII(config[iZone], geometry[iZone][INST_0][MESH_0], iZone, val_nZone, true); DeallocateConnectivity(config[iZone], geometry[iZone][INST_0][MESH_0], true); break; - + default: break; } - + } - + /*--- Release memory needed for merging the solution data. ---*/ - + DeallocateCoordinates(config[iZone], geometry[iZone][INST_0][MESH_0]); DeallocateSolution(config[iZone], geometry[iZone][INST_0][MESH_0]); - + } - + /*--- Final broadcast (informing other procs that the base output file was written). ---*/ - + #ifdef HAVE_MPI SU2_MPI::Bcast(&wrote_base_file, 1, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Bcast(&wrote_surf_file, 1, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD); #endif - + } } void COutputLegacy::SetBaselineResult_Files(CSolver ***solver, CGeometry ***geometry, CConfig **config, unsigned long iExtIter, unsigned short val_nZone) { - + unsigned short iZone, iInst, nInst; - + for (iZone = 0; iZone < val_nZone; iZone++) { - + nInst = config[iZone]->GetnTimeInstances(); for (iInst = 0; iInst < nInst; iInst++) { @@ -8479,11 +8479,11 @@ void COutputLegacy::SetBaselineResult_Files(CSolver ***solver, CGeometry ***geom // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, false); DeallocateConnectivity(config[iZone], geometry[iZone][iInst], false); break; - + case PARAVIEW_BINARY: - + /*--- Write a ParaView ASCII file instead for now in serial. ---*/ - + if (rank == MASTER_NODE) cout << "ParaView binary volume files not available in this mode." << endl; if (rank == MASTER_NODE) cout << " Writing ParaView ASCII volume solution file instead." << endl; // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, false); @@ -8528,15 +8528,15 @@ void COutputLegacy::SetBaselineResult_Files(CSolver ***solver, CGeometry ***geom break; case PARAVIEW_BINARY: - + /*--- Write a ParaView ASCII file instead for now in serial. ---*/ - + if (rank == MASTER_NODE) cout << "ParaView binary surface files not available in this mode." << endl; if (rank == MASTER_NODE) cout << " Writing ParaView ASCII surface solution file instead." << endl; // SetParaview_ASCII(config[iZone], geometry[iZone][iInst], iZone, val_nZone, true); DeallocateConnectivity(config[iZone], geometry[iZone][iInst], true); break; - + default: break; } @@ -8590,35 +8590,35 @@ void COutputLegacy::SetMesh_Files(CGeometry **geometry, CConfig **config, unsign } for (iZone = 0; iZone < val_nZone; iZone++) { - + /*--- Flags identifying the types of files to be written. ---*/ - + bool Wrt_Vol = config[iZone]->GetVisualize_Volume_Def(); bool Wrt_Srf = config[iZone]->GetVisualize_Surface_Def(); //bool Wrt_Crd = config[iZone]->GetWrt_Crd_Sol(); - + /*--- Merge the node coordinates and connectivity if necessary. This is only performed if a volume solution file is requested, and it is active by default. ---*/ - + if (rank == MASTER_NODE) cout <<"Merging grid connectivity." << endl; MergeConnectivity(config[iZone], geometry[iZone], iZone); - + /*--- Merge coordinates of all grid nodes (excluding ghost points). The grid coordinates are always merged and included first in the restart files. ---*/ - + if (rank == MASTER_NODE) cout <<"Merging grid coordinates." << endl; MergeCoordinates(config[iZone], geometry[iZone]); - + /*--- Write restart, Tecplot or Paraview files using the merged data. This data lives only on the master, and these routines are currently executed by the master proc alone (as if in serial). ---*/ - + if (rank == MASTER_NODE) { - + if (Wrt_Vol) { - + if (rank == MASTER_NODE) cout <<"Writing volume mesh file." << endl; // /*--- Write a Tecplot ASCII file ---*/ @@ -8633,15 +8633,15 @@ void COutputLegacy::SetMesh_Files(CGeometry **geometry, CConfig **config, unsign // if (rank == MASTER_NODE) cout <<"Writing ASCII tecplot volume mesh file by default." << endl; //// SetTecplotASCII_Mesh(config[iZone], geometry[iZone], iZone, false, new_file); // } - + } - + if (Wrt_Srf) { - + if (rank == MASTER_NODE) cout <<"Writing surface mesh file." << endl; - + /*--- Write a Tecplot ASCII file ---*/ - + // if (config[iZone]->GetOutput_FileFormat() == PARAVIEW) SetParaview_MeshASCII(config[iZone], geometry[iZone], iZone, val_nZone, true, new_file); // else if (config[iZone]->GetOutput_FileFormat() == PARAVIEW_BINARY) { // if (rank == MASTER_NODE) cout <<"Writing ASCII paraview surface mesh file by default." << endl; @@ -8652,48 +8652,48 @@ void COutputLegacy::SetMesh_Files(CGeometry **geometry, CConfig **config, unsign // if (rank == MASTER_NODE) cout <<"Writing ASCII tecplot surface mesh file by default." << endl; // SetTecplotASCII_Mesh(config[iZone], geometry[iZone], iZone, true, new_file); // } - + } - + /*--- Write a .su2 ASCII file ---*/ if (su2_file) { - + if (rank == MASTER_NODE) cout <<"Writing .su2 file." << endl; - + // SetSU2_MeshASCII(config[iZone], geometry[iZone], iZone, output_file); - + /*--- Write an stl surface file ---*/ - + if (rank == MASTER_NODE) cout <<"Writing .stl surface file." << endl; - + // SetSTL_MeshASCII(config[iZone], geometry[iZone]); - + } - + /*--- Write a binary file with the grid coordinates alone. ---*/ - + // if (Wrt_Crd) { // if (rank == MASTER_NODE) cout <<"Writing .dat binary coordinates file." << endl; // WriteCoordinates_Binary(config[iZone], geometry[iZone], iZone); // } - + /*--- Deallocate connectivity ---*/ - + DeallocateConnectivity(config[iZone], geometry[iZone], true); DeallocateConnectivity(config[iZone], geometry[iZone], false); DeallocateCoordinates(config[iZone], geometry[iZone]); - + } /*--- Final broadcast (informing other procs that the base output file was written). ---*/ - + #ifdef HAVE_MPI SU2_MPI::Bcast(&wrote_base_file, 1, MPI_UNSIGNED_SHORT, MASTER_NODE, MPI_COMM_WORLD); #endif - + /*--- Write an csv surface file, done in parallel ---*/ if (rank == MASTER_NODE) cout <<"Writing .csv surface file." << endl; @@ -8710,7 +8710,7 @@ void COutputLegacy::SetMesh_Files(CGeometry **geometry, CConfig **config, unsign } void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) { - + short iSection, nSection; unsigned long iVertex, iPoint, Trailing_Point; su2double *Plane_P0, *Plane_P0_, *Plane_Normal, *Plane_Normal_, *CPressure, @@ -8721,12 +8721,12 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, 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, - Xcoord_LeadingEdge_ = 0.0, + Xcoord_LeadingEdge_ = 0.0, Xcoord_TrailingEdge_ = 0.0, Ycoord_TrailingEdge_ = 0.0, Zcoord_TrailingEdge_ = 0.0, MaxDistance, Distance, Chord, Aux, Dihedral_Trailing; - + su2double B, Y, C_L, C_L0, Elliptic_Spanload; - + vector Xcoord_Airfoil, Ycoord_Airfoil, Zcoord_Airfoil, CPressure_Airfoil; vector Xcoord_Airfoil_, Ycoord_Airfoil_, Zcoord_Airfoil_, @@ -8734,21 +8734,21 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, string Marker_Tag, Slice_Filename, Slice_Ext; ofstream Cp_File; unsigned short iDim; - + bool dynamic_grid = config->GetDynamic_Grid(); - + Plane_P0 = new su2double[3]; Plane_P0_ = new su2double[3]; Plane_Normal = new su2double[3]; Plane_Normal_ = new su2double[3]; CPressure = new su2double[geometry->GetnPoint()]; - + if ((rank == MASTER_NODE) && (output)) { cout << endl << "Writing the spanload file (load_distribution.dat)."; } - + /*--- Compute some reference quantities and necessary values ---*/ - + RefDensity = solver->GetDensity_Inf(); RefPressure = solver->GetPressure_Inf(); RefArea = config->GetRefArea(); @@ -8757,7 +8757,7 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, Origin = config->GetRefOriginMoment(0); RefLength = config->GetRefLength(); Alpha = config->GetAoA() * PI_NUMBER / 180.0; - + if (dynamic_grid) { Gas_Constant = config->GetGas_ConstantND(); Mach2Vel = sqrt( @@ -8770,26 +8770,26 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, RefVel2 += Velocity_Inf[iDim] * Velocity_Inf[iDim]; } factor = 1.0 / (0.5 * RefDensity * RefArea * RefVel2); - + if (geometry->GetnDim() == 3) { - + /*--- Copy the pressure to an auxiliar structure ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { CPressure[iPoint] = (solver->GetNodes()->GetPressure(iPoint) - RefPressure) * factor * RefArea; } - + nSection = config->GetnLocationStations(); - + for (iSection = 0; iSection < nSection; iSection++) { - + /*--- Read the values from the config file ---*/ - + Plane_Normal[0] = 0.0; Plane_P0[0] = 0.0; Plane_Normal[1] = 0.0; Plane_P0[1] = 0.0; Plane_Normal[2] = 0.0; Plane_P0[2] = 0.0; - + if (config->GetGeo_Description() == FUSELAGE) { Plane_Normal[0] = 1.0; Plane_P0[0] = config->GetLocationStations(iSection); @@ -8798,27 +8798,27 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, Plane_Normal[0] = 0.0; Plane_Normal[1] = -sin(config->GetLocationStations(iSection)*PI_NUMBER/180.0); Plane_Normal[2] = cos(config->GetLocationStations(iSection)*PI_NUMBER/180.0); - + /*--- Apply tilt angle to the plane ---*/ - + su2double Tilt_Angle = config->GetNacelleLocation(3)*PI_NUMBER/180; su2double Plane_NormalX_Tilt = Plane_Normal[0]*cos(Tilt_Angle) + Plane_Normal[2]*sin(Tilt_Angle); su2double Plane_NormalY_Tilt = Plane_Normal[1]; su2double Plane_NormalZ_Tilt = Plane_Normal[2]*cos(Tilt_Angle) - Plane_Normal[0]*sin(Tilt_Angle); - + /*--- Apply toe angle to the plane ---*/ - + su2double Toe_Angle = config->GetNacelleLocation(4)*PI_NUMBER/180; su2double Plane_NormalX_Tilt_Toe = Plane_NormalX_Tilt*cos(Toe_Angle) - Plane_NormalY_Tilt*sin(Toe_Angle); su2double Plane_NormalY_Tilt_Toe = Plane_NormalX_Tilt*sin(Toe_Angle) + Plane_NormalY_Tilt*cos(Toe_Angle); su2double Plane_NormalZ_Tilt_Toe = Plane_NormalZ_Tilt; - + /*--- Update normal vector ---*/ - + Plane_Normal[0] = Plane_NormalX_Tilt_Toe; Plane_Normal[1] = Plane_NormalY_Tilt_Toe; Plane_Normal[2] = Plane_NormalZ_Tilt_Toe; - + } else { Plane_Normal[1] = 1.0; @@ -8826,21 +8826,21 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, } /*--- Compute the airfoil sections (note that we feed in the Cp) ---*/ - + geometry->ComputeAirfoil_Section(Plane_P0, Plane_Normal, -1E6, 1E6, -1E6, 1E6, -1E6, 1E6, CPressure, Xcoord_Airfoil, Ycoord_Airfoil, Zcoord_Airfoil, CPressure_Airfoil, true, config); - + if ((rank == MASTER_NODE) && (Xcoord_Airfoil.size() == 0)) { if ((config->GetGeo_Description() == FUSELAGE) || (config->GetGeo_Description() == WING)) cout << endl << "Please check the config file, the section (" << Plane_P0[0] <<", " << Plane_P0[1] <<", " << Plane_P0[2] << ") has not been detected." << endl; if (config->GetGeo_Description() == NACELLE) cout << endl << "Please check the config file, the section (" << Plane_Normal[0] <<", " << Plane_Normal[1] <<", " << Plane_Normal[2] << ") has not been detected." << endl; } - - + + /*--- Compute dihedral using a step in the station value ---*/ - + Plane_P0_[0] = 0.0; Plane_Normal_[0] = 0.0; Plane_P0_[1] = 0.0; Plane_Normal_[1] = 0.0; Plane_P0_[2] = 0.0; Plane_Normal_[2] = 0.0; @@ -8855,53 +8855,53 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, Plane_Normal_[0] = 0.0; Plane_Normal_[1] = -sin((config->GetLocationStations(iSection) + 0.01)*PI_NUMBER/180.0); Plane_Normal_[2] = cos((config->GetLocationStations(iSection) + 0.01)*PI_NUMBER/180.0); - + /*--- Apply tilt angle to the plane ---*/ - + su2double Tilt_Angle = config->GetNacelleLocation(3)*PI_NUMBER/180; su2double Plane_NormalX_Tilt = Plane_Normal[0]*cos(Tilt_Angle) + Plane_Normal[2]*sin(Tilt_Angle); su2double Plane_NormalY_Tilt = Plane_Normal[1]; su2double Plane_NormalZ_Tilt = Plane_Normal[2]*cos(Tilt_Angle) - Plane_Normal[0]*sin(Tilt_Angle); - + /*--- Apply toe angle to the plane ---*/ - + su2double Toe_Angle = config->GetNacelleLocation(4)*PI_NUMBER/180; su2double Plane_NormalX_Tilt_Toe = Plane_NormalX_Tilt*cos(Toe_Angle) - Plane_NormalY_Tilt*sin(Toe_Angle); su2double Plane_NormalY_Tilt_Toe = Plane_NormalX_Tilt*sin(Toe_Angle) + Plane_NormalY_Tilt*cos(Toe_Angle); su2double Plane_NormalZ_Tilt_Toe = Plane_NormalZ_Tilt; - + /*--- Update normal vector ---*/ - + Plane_Normal[0] = Plane_NormalX_Tilt_Toe; Plane_Normal[1] = Plane_NormalY_Tilt_Toe; Plane_Normal[2] = Plane_NormalZ_Tilt_Toe; - + } else { Plane_Normal_[0] = 0.0; Plane_Normal_[1] = -sin((config->GetLocationStations(iSection) - 0.01)*PI_NUMBER/180.0); Plane_Normal_[2] = cos((config->GetLocationStations(iSection) - 0.01)*PI_NUMBER/180.0); - + /*--- Apply tilt angle to the plane ---*/ - + su2double Tilt_Angle = config->GetNacelleLocation(3)*PI_NUMBER/180; su2double Plane_NormalX_Tilt = Plane_Normal[0]*cos(Tilt_Angle) + Plane_Normal[2]*sin(Tilt_Angle); su2double Plane_NormalY_Tilt = Plane_Normal[1]; su2double Plane_NormalZ_Tilt = Plane_Normal[2]*cos(Tilt_Angle) - Plane_Normal[0]*sin(Tilt_Angle); - + /*--- Apply toe angle to the plane ---*/ - + su2double Toe_Angle = config->GetNacelleLocation(4)*PI_NUMBER/180; su2double Plane_NormalX_Tilt_Toe = Plane_NormalX_Tilt*cos(Toe_Angle) - Plane_NormalY_Tilt*sin(Toe_Angle); su2double Plane_NormalY_Tilt_Toe = Plane_NormalX_Tilt*sin(Toe_Angle) + Plane_NormalY_Tilt*cos(Toe_Angle); su2double Plane_NormalZ_Tilt_Toe = Plane_NormalZ_Tilt; - + /*--- Update normal vector ---*/ - + Plane_Normal[0] = Plane_NormalX_Tilt_Toe; Plane_Normal[1] = Plane_NormalY_Tilt_Toe; Plane_Normal[2] = Plane_NormalZ_Tilt_Toe; - + } } else { @@ -8909,17 +8909,17 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, if (iSection == 0) Plane_P0_[1] = config->GetLocationStations(iSection) + 0.01; else Plane_P0_[1] = config->GetLocationStations(iSection) - 0.01; } - + geometry->ComputeAirfoil_Section(Plane_P0_, Plane_Normal_, -1E6, 1E6, -1E6, 1E6, -1E6, 1E6, CPressure, Xcoord_Airfoil_, Ycoord_Airfoil_, Zcoord_Airfoil_, CPressure_Airfoil_, true, config); - + /*--- Output the pressure on each section (tecplot format) ---*/ - + if ((rank == MASTER_NODE) && (Xcoord_Airfoil.size() != 0)) { - + /*--- Find leading and trailing edge ---*/ - + Xcoord_LeadingEdge = 1E6; Xcoord_TrailingEdge = -1E6; for (iVertex = 0; iVertex < Xcoord_Airfoil.size(); iVertex++) { if (Xcoord_Airfoil[iVertex] < Xcoord_LeadingEdge) { @@ -8933,11 +8933,11 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, Zcoord_TrailingEdge = Zcoord_Airfoil[iVertex]; } } - + Chord = (Xcoord_TrailingEdge-Xcoord_LeadingEdge); - + /*--- Compute dihedral ---*/ - + Xcoord_LeadingEdge_ = 1E6; Xcoord_TrailingEdge_ = -1E6; for (iVertex = 0; iVertex < Xcoord_Airfoil_.size(); iVertex++) { if (Xcoord_Airfoil_[iVertex] < Xcoord_LeadingEdge_) { @@ -8949,27 +8949,27 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, Zcoord_TrailingEdge_ = Zcoord_Airfoil_[iVertex]; } } - + if (iSection == 0) { Dihedral_Trailing = atan((Zcoord_TrailingEdge_ - Zcoord_TrailingEdge) / (Ycoord_TrailingEdge_ - Ycoord_TrailingEdge))*180/PI_NUMBER; } else { Dihedral_Trailing = atan((Zcoord_TrailingEdge - Zcoord_TrailingEdge_) / (Ycoord_TrailingEdge - Ycoord_TrailingEdge_))*180/PI_NUMBER; } - + /*--- Write Cp at each section (tecplot format) ---*/ - + if (output) { - + ofstream Cp_File; - + if (iSection == 0) { Cp_File.open("cp_sections.dat", ios::out); Cp_File << "TITLE = \"Airfoil sections\"" << endl; Cp_File << "VARIABLES = \"x/c\",\"Cp\",\"x\",\"y\",\"z\",\"y/c\",\"z/c\"" << endl; } else Cp_File.open("cp_sections.dat", ios::app); - + if (config->GetGeo_Description() == NACELLE) { su2double theta_deg = atan2(Plane_Normal[1], -Plane_Normal[2])/PI_NUMBER*180 + 180; Cp_File << "ZONE T=\"Theta = " << theta_deg << " deg\", I= " << Xcoord_Airfoil.size() << ", F=POINT" << "\n"; @@ -8977,33 +8977,33 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, else { if (config->GetSystemMeasurements() == SI) Cp_File << "ZONE T=\"y = " << Plane_P0[1] << " m\", I= " << Xcoord_Airfoil.size() << ", F=POINT" << "\n"; - + if (config->GetSystemMeasurements() == US) Cp_File << "ZONE T=\"y = " << Plane_P0[1]*12.0 << " in\", I= " << Xcoord_Airfoil.size() << ", F=POINT" << "\n"; } - - + + /*--- Coordinates and pressure value ---*/ - + for (iVertex = 0; iVertex < Xcoord_Airfoil.size(); iVertex++) { - + su2double XCoord = Xcoord_Airfoil[iVertex]; su2double YCoord = Ycoord_Airfoil[iVertex]; su2double ZCoord = Zcoord_Airfoil[iVertex]; - + /*--- Undo the transformation based on the Theta angle ---*/ - + if (config->GetGeo_Description() == NACELLE) { su2double theta_deg = atan2(Plane_Normal[1],-Plane_Normal[2])/PI_NUMBER*180 + 180; su2double Angle = theta_deg*PI_NUMBER/180 - 0.5*PI_NUMBER; - + XCoord = Xcoord_Airfoil[iVertex] + config->GetNacelleLocation(0); YCoord = (Ycoord_Airfoil[iVertex]*cos(Angle) - Zcoord_Airfoil[iVertex]*sin(Angle)) + config->GetNacelleLocation(1); ZCoord = (Zcoord_Airfoil[iVertex]*cos(Angle) + Ycoord_Airfoil[iVertex]*sin(Angle)) + config->GetNacelleLocation(2); - + } - + if (config->GetSystemMeasurements() == US) { Cp_File << (Xcoord_Airfoil[iVertex] - Xcoord_LeadingEdge) / Chord << " " << CPressure_Airfoil[iVertex] << " " << XCoord * 12.0 << " " << YCoord * 12.0 << " " << ZCoord * 12.0 @@ -9014,57 +9014,57 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, << " " << XCoord << " " << YCoord << " " << ZCoord << " " << (Ycoord_Airfoil[iVertex] - Ycoord_LeadingEdge) / Chord << " " << (Zcoord_Airfoil[iVertex] - Zcoord_LeadingEdge) / Chord << "\n"; } - + } - + Cp_File.close(); - + } - + /*--- Compute load distribution ---*/ - + ForceInviscid[0] = 0.0; ForceInviscid[1] = 0.0; ForceInviscid[2] = 0.0; MomentInviscid[1] = 0.0; - + for (iVertex = 0; iVertex < Xcoord_Airfoil.size() - 1; iVertex++) { - + NDPressure = 0.5 * (CPressure_Airfoil[iVertex] + CPressure_Airfoil[iVertex + 1]); - + Force[0] = -(Zcoord_Airfoil[iVertex + 1] - Zcoord_Airfoil[iVertex]) * NDPressure; Force[1] = 0.0; Force[2] = (Xcoord_Airfoil[iVertex + 1] - Xcoord_Airfoil[iVertex]) * NDPressure; - + ForceInviscid[0] += Force[0]; ForceInviscid[1] += Force[1]; ForceInviscid[2] += Force[2]; - + MomentDist[0] = 0.5 * (Xcoord_Airfoil[iVertex] + Xcoord_Airfoil[iVertex + 1]) - Origin[0]; MomentDist[1] = 0.5 * (Ycoord_Airfoil[iVertex] + Ycoord_Airfoil[iVertex + 1]) - Origin[1]; MomentDist[2] = 0.5 * (Zcoord_Airfoil[iVertex] + Zcoord_Airfoil[iVertex + 1]) - Origin[3]; - + MomentInviscid[1] += (Force[0] * MomentDist[2] - Force[2] * MomentDist[0]) / RefLength; - + } - + /*--- Compute local chord, for the nondimensionalization ---*/ - + MaxDistance = 0.0; Trailing_Point = 0; - + for (iVertex = 1; iVertex < Xcoord_Airfoil.size(); iVertex++) { - + Distance = sqrt(pow(Xcoord_Airfoil[iVertex] - Xcoord_Airfoil[Trailing_Point], 2.0) + pow(Ycoord_Airfoil[iVertex] - Ycoord_Airfoil[Trailing_Point], 2.0) + pow(Zcoord_Airfoil[iVertex] - Zcoord_Airfoil[Trailing_Point], 2.0)); - + if (MaxDistance < Distance) { MaxDistance = Distance; } - + } - + Chord = MaxDistance; - + CL_Inv = cos(Dihedral_Trailing * PI_NUMBER / 180.0) * fabs( -ForceInviscid[0] * sin(Alpha) + ForceInviscid[2] * cos(Alpha) )/ Chord; - + /*--- Compute sectional lift at the root ---*/ - + B = 2.0*config->GetSemiSpan(); RefArea = config->GetRefArea(); C_L = solver->GetTotal_CL(); @@ -9072,15 +9072,15 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, Y = Ycoord_Airfoil[0]; Aux = Y/(0.5*B); Elliptic_Spanload = (C_L0 / RefLength) * sqrt(fabs(1.0-Aux*Aux)); - - + + /*--- Write load distribution ---*/ - + if (output) { - + ofstream Load_File; if (iSection == 0) { - + if ((config->GetTabular_FileFormat() == TAB_CSV)) { Load_File.open("load_distribution.csv", ios::out); Load_File << "\"Percent Semispan\",\"Sectional C_L\",\"Spanload (c C_L / c_ref) \",\"Elliptic Spanload\"" << endl; @@ -9095,38 +9095,38 @@ void COutputLegacy::SpecialOutput_SpanLoad(CSolver *solver, CGeometry *geometry, if ((config->GetTabular_FileFormat() == TAB_CSV)) Load_File.open("load_distribution.csv", ios::app); else Load_File.open("load_distribution.dat", ios::app); } - - + + /*--- CL and spanload ---*/ - + if ((config->GetTabular_FileFormat() == TAB_CSV)) Load_File << 100.0*Ycoord_Airfoil[0]/(0.5*B) << ", " << CL_Inv << ", " << Chord*CL_Inv / RefLength <<", " << Elliptic_Spanload << endl; else Load_File << 100.0*Ycoord_Airfoil[0]/(0.5*B) << " " << CL_Inv << " " << Chord*CL_Inv / RefLength <<" " << Elliptic_Spanload << endl; - + Load_File.close(); - + } - + } - + } - + } - + /*--- Delete dynamically allocated memory ---*/ - + delete[] Plane_P0; delete[] Plane_P0_; delete[] Plane_Normal; delete[] Plane_Normal_; delete[] CPressure; - + } void COutputLegacy::SetCp_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter) { - + unsigned short iMarker, icommas, Boundary, iDim; unsigned long iVertex, iPoint, (*Point2Vertex)[2], nPointLocal = 0, nPointGlobal = 0; su2double XCoord, YCoord, ZCoord, Pressure, PressureCoeff = 0, Cp, CpTarget, *Normal = NULL, Area, PressDiff; @@ -9134,56 +9134,56 @@ void COutputLegacy::SetCp_InverseDesign(CSolver *solver_container, CGeometry *ge string text_line, surfCp_filename; ifstream Surface_file; char buffer[50], cstr[200]; - - + + nPointLocal = geometry->GetnPoint(); #ifdef HAVE_MPI SU2_MPI::Allreduce(&nPointLocal, &nPointGlobal, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); #else nPointGlobal = nPointLocal; #endif - + Point2Vertex = new unsigned long[nPointGlobal][2]; PointInDomain = new bool[nPointGlobal]; - + for (iPoint = 0; iPoint < nPointGlobal; iPoint ++) PointInDomain[iPoint] = false; - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { Boundary = config->GetMarker_All_KindBC(iMarker); - + if ((Boundary == EULER_WALL ) || (Boundary == HEAT_FLUX ) || (Boundary == ISOTHERMAL ) || (Boundary == NEARFIELD_BOUNDARY)) { for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - + /*--- The Pressure file uses the global numbering ---*/ - + #ifndef HAVE_MPI iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); #else iPoint = geometry->node[geometry->vertex[iMarker][iVertex]->GetNode()]->GetGlobalIndex(); #endif - + if (geometry->vertex[iMarker][iVertex]->GetNode() < geometry->GetnPointDomain()) { Point2Vertex[iPoint][0] = iMarker; Point2Vertex[iPoint][1] = iVertex; PointInDomain[iPoint] = true; solver_container->SetCPressureTarget(iMarker, iVertex, 0.0); } - + } } } - + /*--- Prepare to read the surface pressure files (CSV) ---*/ - + surfCp_filename = "TargetCp"; strcpy (cstr, surfCp_filename.c_str()); - + /*--- Write file name with extension if unsteady or steady ---*/ - + if ((config->GetTime_Marching() && config->GetTime_Domain()) || (config->GetTime_Marching() == HARMONIC_BALANCE)) { if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(iExtIter)); @@ -9194,90 +9194,90 @@ void COutputLegacy::SetCp_InverseDesign(CSolver *solver_container, CGeometry *ge } else SPRINTF (buffer, ".dat"); - + strcat (cstr, buffer); - + /*--- Read the surface pressure file ---*/ - + string::size_type position; - + Surface_file.open(cstr, ios::in); - + if (!(Surface_file.fail())) { - + getline(Surface_file, text_line); - + while (getline(Surface_file, text_line)) { for (icommas = 0; icommas < 50; icommas++) { position = text_line.find( ",", 0 ); if (position!=string::npos) text_line.erase (position,1); } stringstream point_line(text_line); - + if (geometry->GetnDim() == 2) point_line >> iPoint >> XCoord >> YCoord >> Pressure >> PressureCoeff; if (geometry->GetnDim() == 3) point_line >> iPoint >> XCoord >> YCoord >> ZCoord >> Pressure >> PressureCoeff; - + if (PointInDomain[iPoint]) { - + /*--- Find the vertex for the Point and Marker ---*/ - + iMarker = Point2Vertex[iPoint][0]; iVertex = Point2Vertex[iPoint][1]; - + solver_container->SetCPressureTarget(iMarker, iVertex, PressureCoeff); - + } - + } - + Surface_file.close(); - + } - + /*--- Compute the pressure difference ---*/ - + PressDiff = 0.0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { Boundary = config->GetMarker_All_KindBC(iMarker); - + if ((Boundary == EULER_WALL ) || (Boundary == HEAT_FLUX ) || (Boundary == ISOTHERMAL ) || (Boundary == NEARFIELD_BOUNDARY)) { for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - + Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - + Cp = solver_container->GetCPressure(iMarker, iVertex); CpTarget = solver_container->GetCPressureTarget(iMarker, iVertex); - + Area = 0.0; for (iDim = 0; iDim < geometry->GetnDim(); iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); - + PressDiff += Area * (CpTarget - Cp) * (CpTarget - Cp); } - + } } - + #ifdef HAVE_MPI su2double MyPressDiff = PressDiff; PressDiff = 0.0; SU2_MPI::Allreduce(&MyPressDiff, &PressDiff, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #endif - + /*--- Update the total Cp difference coeffient ---*/ - + solver_container->SetTotal_CpDiff(PressDiff); - + delete [] Point2Vertex; delete [] PointInDomain; - + } void COutputLegacy::SetHeatFlux_InverseDesign(CSolver *solver_container, CGeometry *geometry, CConfig *config, unsigned long iExtIter) { - + unsigned short iMarker, icommas, Boundary, iDim; unsigned long iVertex, iPoint, (*Point2Vertex)[2], nPointLocal = 0, nPointGlobal = 0; su2double XCoord, YCoord, ZCoord, PressureCoeff, HeatFlux = 0.0, HeatFluxDiff, HeatFluxTarget, *Normal = NULL, Area, @@ -9286,38 +9286,38 @@ void COutputLegacy::SetHeatFlux_InverseDesign(CSolver *solver_container, CGeomet string text_line, surfHeatFlux_filename; ifstream Surface_file; char buffer[50], cstr[200]; - - + + nPointLocal = geometry->GetnPoint(); #ifdef HAVE_MPI SU2_MPI::Allreduce(&nPointLocal, &nPointGlobal, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); #else nPointGlobal = nPointLocal; #endif - + Point2Vertex = new unsigned long[nPointGlobal][2]; PointInDomain = new bool[nPointGlobal]; - + for (iPoint = 0; iPoint < nPointGlobal; iPoint ++) PointInDomain[iPoint] = false; - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { Boundary = config->GetMarker_All_KindBC(iMarker); - + if ((Boundary == EULER_WALL ) || (Boundary == HEAT_FLUX ) || (Boundary == ISOTHERMAL ) || (Boundary == NEARFIELD_BOUNDARY)) { for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - + /*--- The Pressure file uses the global numbering ---*/ - + #ifndef HAVE_MPI iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); #else iPoint = geometry->node[geometry->vertex[iMarker][iVertex]->GetNode()]->GetGlobalIndex(); #endif - + if (geometry->vertex[iMarker][iVertex]->GetNode() < geometry->GetnPointDomain()) { Point2Vertex[iPoint][0] = iMarker; Point2Vertex[iPoint][1] = iVertex; @@ -9327,14 +9327,14 @@ void COutputLegacy::SetHeatFlux_InverseDesign(CSolver *solver_container, CGeomet } } } - + /*--- Prepare to read the surface pressure files (CSV) ---*/ - + surfHeatFlux_filename = "TargetHeatFlux"; strcpy (cstr, surfHeatFlux_filename.c_str()); - + /*--- Write file name with extension if unsteady or steady ---*/ - + if ((config->GetTime_Marching() && config->GetTime_Domain()) || (config->GetTime_Marching() == HARMONIC_BALANCE)) { if ((SU2_TYPE::Int(iExtIter) >= 0) && (SU2_TYPE::Int(iExtIter) < 10)) SPRINTF (buffer, "_0000%d.dat", SU2_TYPE::Int(iExtIter)); @@ -9345,90 +9345,90 @@ void COutputLegacy::SetHeatFlux_InverseDesign(CSolver *solver_container, CGeomet } else SPRINTF (buffer, ".dat"); - + strcat (cstr, buffer); - + /*--- Read the surface pressure file ---*/ - + string::size_type position; - + Surface_file.open(cstr, ios::in); - + if (!(Surface_file.fail())) { - + getline(Surface_file, text_line); - + while (getline(Surface_file, text_line)) { for (icommas = 0; icommas < 50; icommas++) { position = text_line.find( ",", 0 ); if (position!=string::npos) text_line.erase (position,1); } stringstream point_line(text_line); - + if (geometry->GetnDim() == 2) point_line >> iPoint >> XCoord >> YCoord >> Pressure >> PressureCoeff >> Cf >> HeatFlux; if (geometry->GetnDim() == 3) point_line >> iPoint >> XCoord >> YCoord >> ZCoord >> Pressure >> PressureCoeff >> Cf >> HeatFlux; - + if (PointInDomain[iPoint]) { - + /*--- Find the vertex for the Point and Marker ---*/ - + iMarker = Point2Vertex[iPoint][0]; iVertex = Point2Vertex[iPoint][1]; - + solver_container->SetHeatFluxTarget(iMarker, iVertex, HeatFlux); - + } - + } - + Surface_file.close(); } - + /*--- Compute the pressure difference ---*/ - + HeatFluxDiff = 0.0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { Boundary = config->GetMarker_All_KindBC(iMarker); - + if ((Boundary == EULER_WALL ) || (Boundary == HEAT_FLUX ) || (Boundary == ISOTHERMAL ) || (Boundary == NEARFIELD_BOUNDARY)) { for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - + Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - + HeatFlux = solver_container->GetHeatFlux(iMarker, iVertex); HeatFluxTarget = solver_container->GetHeatFluxTarget(iMarker, iVertex); - + Area = 0.0; for (iDim = 0; iDim < geometry->GetnDim(); iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); - + HeatFluxDiff += Area * (HeatFluxTarget - HeatFlux) * (HeatFluxTarget - HeatFlux); - + } - + } } - + #ifdef HAVE_MPI su2double MyHeatFluxDiff = HeatFluxDiff; HeatFluxDiff = 0.0; SU2_MPI::Allreduce(&MyHeatFluxDiff, &HeatFluxDiff, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #endif - + /*--- Update the total HeatFlux difference coeffient ---*/ - + solver_container->SetTotal_HeatFluxDiff(HeatFluxDiff); - + delete [] Point2Vertex; delete [] PointInDomain; - + } void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) { - + ofstream EquivArea_file, FuncGrad_file; unsigned short iMarker = 0, iDim; short *AzimuthalAngle = NULL; @@ -9441,14 +9441,14 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry *IdPoint = NULL, *IdDomain = NULL, auxDomain; unsigned short iPhiAngle; ofstream NearFieldEA_file; ifstream TargetEA_file; - + su2double XCoordBegin_OF = config->GetEA_IntLimit(0); su2double XCoordEnd_OF = config->GetEA_IntLimit(1); - + unsigned short nDim = geometry->GetnDim(); su2double AoA = -(config->GetAoA()*PI_NUMBER/180.0); su2double EAScaleFactor = config->GetEA_ScaleFactor(); // The EA Obj. Func. should be ~ force based Obj. Func. - + Mach = config->GetMach(); Gamma = config->GetGamma(); Beta = sqrt(Mach*Mach-1.0); @@ -9460,15 +9460,15 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry ModVelocity_Inf = 0; for (iDim = 0; iDim < 3; iDim++) ModVelocity_Inf += Velocity_Inf[iDim] * Velocity_Inf[iDim]; - + factor = 4.0*sqrt(2.0*Beta*R_Plane) / (Gamma*Pressure_Inf*Mach*Mach); - + if (rank == MASTER_NODE) cout << endl << "Writing Equivalent Area files."; #ifndef HAVE_MPI - + /*--- Compute the total number of points on the near-field ---*/ - + nVertex_NearField = 0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY) @@ -9476,16 +9476,16 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); Coord = geometry->node[iPoint]->GetCoord(); - + /*--- Using Face_Normal(z), and Coord(z) we identify only a surface, note that there are 2 NEARFIELD_BOUNDARY surfaces ---*/ - + if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) nVertex_NearField ++; } - + /*--- Create an array with all the coordinates, points, pressures, face area, equivalent area, and nearfield weight ---*/ - + Xcoord = new su2double[nVertex_NearField]; Ycoord = new su2double[nVertex_NearField]; Zcoord = new su2double[nVertex_NearField]; @@ -9498,9 +9498,9 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry TargetArea = new su2double[nVertex_NearField]; NearFieldWeight = new su2double[nVertex_NearField]; Weight = new su2double[nVertex_NearField]; - + /*--- Copy the boundary information to an array ---*/ - + nVertex_NearField = 0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY) @@ -9508,65 +9508,65 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); Coord = geometry->node[iPoint]->GetCoord(); - + if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) { - + IdPoint[nVertex_NearField] = iPoint; Xcoord[nVertex_NearField] = geometry->node[iPoint]->GetCoord(0); Ycoord[nVertex_NearField] = geometry->node[iPoint]->GetCoord(1); - + if (nDim ==2) { AzimuthalAngle[nVertex_NearField] = 0; } - + if (nDim == 3) { Zcoord[nVertex_NearField] = geometry->node[iPoint]->GetCoord(2); - + /*--- Rotate the nearfield cylinder (AoA) only 3D ---*/ - + su2double YcoordRot = Ycoord[nVertex_NearField]; su2double ZcoordRot = Xcoord[nVertex_NearField]*sin(AoA) + Zcoord[nVertex_NearField]*cos(AoA); - + /*--- Compute the Azimuthal angle (resolution of degress in the Azimuthal angle)---*/ - + su2double AngleDouble; short AngleInt; AngleDouble = fabs(atan(-YcoordRot/ZcoordRot)*180.0/PI_NUMBER); - + /*--- Fix an azimuthal line due to misalignments of the near-field ---*/ - + su2double FixAzimuthalLine = config->GetFixAzimuthalLine(); - + if ((AngleDouble >= FixAzimuthalLine - 0.1) && (AngleDouble <= FixAzimuthalLine + 0.1)) AngleDouble = FixAzimuthalLine - 0.1; - + AngleInt = SU2_TYPE::Short(floor(AngleDouble + 0.5)); if (AngleInt >= 0) AzimuthalAngle[nVertex_NearField] = AngleInt; else AzimuthalAngle[nVertex_NearField] = 180 + AngleInt; } - + if (AzimuthalAngle[nVertex_NearField] <= 60) { Pressure[nVertex_NearField] = solver->GetNodes()->GetPressure(iPoint); FaceArea[nVertex_NearField] = fabs(Face_Normal[nDim-1]); nVertex_NearField ++; } - + } } - + #else - + int nProcessor; SU2_MPI::Comm_size(MPI_COMM_WORLD, &nProcessor); - + unsigned long nLocalVertex_NearField = 0, MaxLocalVertex_NearField = 0; int iProcessor; - + unsigned long *Buffer_Receive_nVertex = NULL; if (rank == MASTER_NODE) { Buffer_Receive_nVertex = new unsigned long [nProcessor]; } - + /*--- Compute the total number of points of the near-field ghost nodes ---*/ - + nLocalVertex_NearField = 0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY) @@ -9574,36 +9574,36 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); Coord = geometry->node[iPoint]->GetCoord(); - + if (geometry->node[iPoint]->GetDomain()) if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) nLocalVertex_NearField ++; } - + unsigned long *Buffer_Send_nVertex = new unsigned long [1]; Buffer_Send_nVertex[0] = nLocalVertex_NearField; - + /*--- Send Near-Field vertex information --*/ - + SU2_MPI::Allreduce(&nLocalVertex_NearField, &nVertex_NearField, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); SU2_MPI::Allreduce(&nLocalVertex_NearField, &MaxLocalVertex_NearField, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_nVertex, 1, MPI_UNSIGNED_LONG, Buffer_Receive_nVertex, 1, MPI_UNSIGNED_LONG, MASTER_NODE, MPI_COMM_WORLD); delete [] Buffer_Send_nVertex; - + su2double *Buffer_Send_Xcoord = new su2double[MaxLocalVertex_NearField]; su2double *Buffer_Send_Ycoord = new su2double[MaxLocalVertex_NearField]; su2double *Buffer_Send_Zcoord = new su2double[MaxLocalVertex_NearField]; unsigned long *Buffer_Send_IdPoint = new unsigned long [MaxLocalVertex_NearField]; su2double *Buffer_Send_Pressure = new su2double [MaxLocalVertex_NearField]; su2double *Buffer_Send_FaceArea = new su2double[MaxLocalVertex_NearField]; - + su2double *Buffer_Receive_Xcoord = NULL; su2double *Buffer_Receive_Ycoord = NULL; su2double *Buffer_Receive_Zcoord = NULL; unsigned long *Buffer_Receive_IdPoint = NULL; su2double *Buffer_Receive_Pressure = NULL; su2double *Buffer_Receive_FaceArea = NULL; - + if (rank == MASTER_NODE) { Buffer_Receive_Xcoord = new su2double[nProcessor*MaxLocalVertex_NearField]; Buffer_Receive_Ycoord = new su2double[nProcessor*MaxLocalVertex_NearField]; @@ -9612,22 +9612,22 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry Buffer_Receive_Pressure = new su2double[nProcessor*MaxLocalVertex_NearField]; Buffer_Receive_FaceArea = new su2double[nProcessor*MaxLocalVertex_NearField]; } - + unsigned long nBuffer_Xcoord = MaxLocalVertex_NearField; unsigned long nBuffer_Ycoord = MaxLocalVertex_NearField; unsigned long nBuffer_Zcoord = MaxLocalVertex_NearField; unsigned long nBuffer_IdPoint = MaxLocalVertex_NearField; unsigned long nBuffer_Pressure = MaxLocalVertex_NearField; unsigned long nBuffer_FaceArea = MaxLocalVertex_NearField; - + for (iVertex = 0; iVertex < MaxLocalVertex_NearField; iVertex++) { Buffer_Send_IdPoint[iVertex] = 0; Buffer_Send_Pressure[iVertex] = 0.0; Buffer_Send_FaceArea[iVertex] = 0.0; Buffer_Send_Xcoord[iVertex] = 0.0; Buffer_Send_Ycoord[iVertex] = 0.0; Buffer_Send_Zcoord[iVertex] = 0.0; } - + /*--- Copy coordinates, index points, and pressures to the auxiliar vector --*/ - + nLocalVertex_NearField = 0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) if (config->GetMarker_All_KindBC(iMarker) == NEARFIELD_BOUNDARY) @@ -9635,7 +9635,7 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); Face_Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); Coord = geometry->node[iPoint]->GetCoord(); - + if (geometry->node[iPoint]->GetDomain()) if ((Face_Normal[nDim-1] > 0.0) && (Coord[nDim-1] < 0.0)) { Buffer_Send_IdPoint[nLocalVertex_NearField] = iPoint; @@ -9647,9 +9647,9 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry nLocalVertex_NearField++; } } - + /*--- Send all the information --*/ - + SU2_MPI::Gather(Buffer_Send_Xcoord, nBuffer_Xcoord, MPI_DOUBLE, Buffer_Receive_Xcoord, nBuffer_Xcoord, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Ycoord, nBuffer_Ycoord, MPI_DOUBLE, Buffer_Receive_Ycoord, nBuffer_Ycoord, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Zcoord, nBuffer_Zcoord, MPI_DOUBLE, Buffer_Receive_Zcoord, nBuffer_Zcoord, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -9662,9 +9662,9 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry delete [] Buffer_Send_IdPoint; delete [] Buffer_Send_Pressure; delete [] Buffer_Send_FaceArea; - + if (rank == MASTER_NODE) { - + Xcoord = new su2double[nVertex_NearField]; Ycoord = new su2double[nVertex_NearField]; Zcoord = new su2double[nVertex_NearField]; @@ -9677,43 +9677,43 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry TargetArea = new su2double[nVertex_NearField]; NearFieldWeight = new su2double[nVertex_NearField]; Weight = new su2double[nVertex_NearField]; - + nVertex_NearField = 0; for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) for (iVertex = 0; iVertex < Buffer_Receive_nVertex[iProcessor]; iVertex++) { Xcoord[nVertex_NearField] = Buffer_Receive_Xcoord[iProcessor*MaxLocalVertex_NearField+iVertex]; Ycoord[nVertex_NearField] = Buffer_Receive_Ycoord[iProcessor*MaxLocalVertex_NearField+iVertex]; - + if (nDim == 2) { AzimuthalAngle[nVertex_NearField] = 0; } - + if (nDim == 3) { Zcoord[nVertex_NearField] = Buffer_Receive_Zcoord[iProcessor*MaxLocalVertex_NearField+iVertex]; - + /*--- Rotate the nearfield cylinder ---*/ - + su2double YcoordRot = Ycoord[nVertex_NearField]; su2double ZcoordRot = Xcoord[nVertex_NearField]*sin(AoA) + Zcoord[nVertex_NearField]*cos(AoA); - + /*--- Compute the Azimuthal angle ---*/ - + su2double AngleDouble; short AngleInt; AngleDouble = fabs(atan(-YcoordRot/ZcoordRot)*180.0/PI_NUMBER); - + /*--- Fix an azimuthal line due to misalignments of the near-field ---*/ - + su2double FixAzimuthalLine = config->GetFixAzimuthalLine(); - + if ((AngleDouble >= FixAzimuthalLine - 0.1) && (AngleDouble <= FixAzimuthalLine + 0.1)) AngleDouble = FixAzimuthalLine - 0.1; - + AngleInt = SU2_TYPE::Short(floor(AngleDouble + 0.5)); - + if (AngleInt >= 0) AzimuthalAngle[nVertex_NearField] = AngleInt; else AzimuthalAngle[nVertex_NearField] = 180 + AngleInt; } - + if (AzimuthalAngle[nVertex_NearField] <= 60) { IdPoint[nVertex_NearField] = Buffer_Receive_IdPoint[iProcessor*MaxLocalVertex_NearField+iVertex]; Pressure[nVertex_NearField] = Buffer_Receive_Pressure[iProcessor*MaxLocalVertex_NearField+iVertex]; @@ -9721,36 +9721,36 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry IdDomain[nVertex_NearField] = iProcessor; nVertex_NearField++; } - + } - + delete [] Buffer_Receive_nVertex; - + delete [] Buffer_Receive_Xcoord; delete [] Buffer_Receive_Ycoord; delete [] Buffer_Receive_Zcoord; delete [] Buffer_Receive_IdPoint; delete [] Buffer_Receive_Pressure; delete [] Buffer_Receive_FaceArea; - + } - + #endif - + if (rank == MASTER_NODE) { - + vector PhiAngleList; vector::iterator IterPhiAngleList; - + for (iVertex = 0; iVertex < nVertex_NearField; iVertex++) PhiAngleList.push_back(AzimuthalAngle[iVertex]); - + sort( PhiAngleList.begin(), PhiAngleList.end()); IterPhiAngleList = unique( PhiAngleList.begin(), PhiAngleList.end()); PhiAngleList.resize( IterPhiAngleList - PhiAngleList.begin() ); - + /*--- Create vectors and distribute the values among the different PhiAngle queues ---*/ - + vector > Xcoord_PhiAngle; Xcoord_PhiAngle.resize(PhiAngleList.size()); vector > Ycoord_PhiAngle; Ycoord_PhiAngle.resize(PhiAngleList.size()); vector > Zcoord_PhiAngle; Zcoord_PhiAngle.resize(PhiAngleList.size()); @@ -9762,9 +9762,9 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry vector > TargetArea_PhiAngle; TargetArea_PhiAngle.resize(PhiAngleList.size()); vector > NearFieldWeight_PhiAngle; NearFieldWeight_PhiAngle.resize(PhiAngleList.size()); vector > Weight_PhiAngle; Weight_PhiAngle.resize(PhiAngleList.size()); - + /*--- Distribute the values among the different PhiAngles ---*/ - + for (iVertex = 0; iVertex < nVertex_NearField; iVertex++) for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) if (AzimuthalAngle[iVertex] == PhiAngleList[iPhiAngle]) { @@ -9780,9 +9780,9 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry NearFieldWeight_PhiAngle[iPhiAngle].push_back(NearFieldWeight[iVertex]); Weight_PhiAngle[iPhiAngle].push_back(Weight[iVertex]); } - + /*--- Order the arrays (x Coordinate, Pressure, Point, and Domain) ---*/ - + for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) for (iVertex = 0; iVertex < Xcoord_PhiAngle[iPhiAngle].size(); iVertex++) for (jVertex = 0; jVertex < Xcoord_PhiAngle[iPhiAngle].size() - 1 - iVertex; jVertex++) @@ -9795,91 +9795,91 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry auxPoint = IdPoint_PhiAngle[iPhiAngle][jVertex]; IdPoint_PhiAngle[iPhiAngle][jVertex] = IdPoint_PhiAngle[iPhiAngle][jVertex+1]; IdPoint_PhiAngle[iPhiAngle][jVertex+1] = auxPoint; auxDomain = IdDomain_PhiAngle[iPhiAngle][jVertex]; IdDomain_PhiAngle[iPhiAngle][jVertex] = IdDomain_PhiAngle[iPhiAngle][jVertex+1]; IdDomain_PhiAngle[iPhiAngle][jVertex+1] = auxDomain; } - - + + /*--- Check that all the azimuth lists have the same size ---*/ - + unsigned short nVertex = Xcoord_PhiAngle[0].size(); for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) { unsigned short nVertex_aux = Xcoord_PhiAngle[iPhiAngle].size(); if (nVertex_aux != nVertex) cout <<"Be careful!!! one azimuth list is shorter than the other"<< endl; nVertex = min(nVertex, nVertex_aux); } - + /*--- Compute equivalent area distribution at each azimuth angle ---*/ - + for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) { EquivArea_PhiAngle[iPhiAngle][0] = 0.0; for (iVertex = 1; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) { EquivArea_PhiAngle[iPhiAngle][iVertex] = 0.0; - + Coord_i = Xcoord_PhiAngle[iPhiAngle][iVertex]*cos(AoA) - Zcoord_PhiAngle[iPhiAngle][iVertex]*sin(AoA); - + for (jVertex = 0; jVertex < iVertex-1; jVertex++) { - + Coord_j = Xcoord_PhiAngle[iPhiAngle][jVertex]*cos(AoA) - Zcoord_PhiAngle[iPhiAngle][jVertex]*sin(AoA); jp1Coord = Xcoord_PhiAngle[iPhiAngle][jVertex+1]*cos(AoA) - Zcoord_PhiAngle[iPhiAngle][jVertex+1]*sin(AoA); - + jFunction = factor*(Pressure_PhiAngle[iPhiAngle][jVertex] - Pressure_Inf)*sqrt(Coord_i-Coord_j); jp1Function = factor*(Pressure_PhiAngle[iPhiAngle][jVertex+1] - Pressure_Inf)*sqrt(Coord_i-jp1Coord); - + DeltaX = (jp1Coord-Coord_j); MeanFuntion = 0.5*(jp1Function + jFunction); EquivArea_PhiAngle[iPhiAngle][iVertex] += DeltaX * MeanFuntion; } } } - + /*--- Create a file with the equivalent area distribution at each azimuthal angle ---*/ - + NearFieldEA_file.precision(15); - + if (output) { - + NearFieldEA_file.open("Equivalent_Area.dat", ios::out); NearFieldEA_file << "TITLE = \"Equivalent Area evaluation at each azimuthal angle\"" << "\n"; - + if (config->GetSystemMeasurements() == US) NearFieldEA_file << "VARIABLES = \"Height (in) at r="<< R_Plane*12.0 << " in. (cyl. coord. system)\""; else NearFieldEA_file << "VARIABLES = \"Height (m) at r="<< R_Plane << " m. (cylindrical coordinate system)\""; - + for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) { if (config->GetSystemMeasurements() == US) NearFieldEA_file << ", \"Equivalent Area (ft2), F= " << PhiAngleList[iPhiAngle] << " deg.\""; else NearFieldEA_file << ", \"Equivalent Area (m2), F= " << PhiAngleList[iPhiAngle] << " deg.\""; } - + NearFieldEA_file << "\n"; for (iVertex = 0; iVertex < EquivArea_PhiAngle[0].size(); iVertex++) { - + su2double XcoordRot = Xcoord_PhiAngle[0][iVertex]*cos(AoA) - Zcoord_PhiAngle[0][iVertex]*sin(AoA); su2double XcoordRot_init = Xcoord_PhiAngle[0][0]*cos(AoA) - Zcoord_PhiAngle[0][0]*sin(AoA); - + if (config->GetSystemMeasurements() == US) NearFieldEA_file << scientific << (XcoordRot - XcoordRot_init) * 12.0; else NearFieldEA_file << scientific << (XcoordRot - XcoordRot_init); - + for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) { NearFieldEA_file << scientific << ", " << EquivArea_PhiAngle[iPhiAngle][iVertex]; } - + NearFieldEA_file << "\n"; - + } NearFieldEA_file.close(); - + } - + /*--- Read target equivalent area from the configuration file, this first implementation requires a complete table (same as the original EA table). so... no interpolation. ---*/ - + vector > TargetArea_PhiAngle_Trans; TargetEA_file.open("TargetEA.dat", ios::in); - + if (TargetEA_file.fail()) { /*--- Set the table to 0 ---*/ for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) @@ -9887,68 +9887,68 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry TargetArea_PhiAngle[iPhiAngle][iVertex] = 0.0; } else { - + /*--- skip header lines ---*/ - + string line; getline(TargetEA_file, line); getline(TargetEA_file, line); - + while (TargetEA_file) { - + string line; getline(TargetEA_file, line); istringstream is(line); vector row; unsigned short iter = 0; - + while (is.good()) { string token; getline(is, token,','); - + istringstream js(token); - + su2double data; js >> data; - + /*--- The first element in the table is the coordinate (in or m)---*/ - + if (iter != 0) row.push_back(data); iter++; - + } TargetArea_PhiAngle_Trans.push_back(row); } - + for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) for (iVertex = 0; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) TargetArea_PhiAngle[iPhiAngle][iVertex] = TargetArea_PhiAngle_Trans[iVertex][iPhiAngle]; - + } - + /*--- Divide by the number of Phi angles in the nearfield ---*/ - + su2double PhiFactor = 1.0/su2double(PhiAngleList.size()); - + /*--- Evaluate the objective function ---*/ - + InverseDesign = 0; for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) for (iVertex = 0; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) { Weight_PhiAngle[iPhiAngle][iVertex] = 1.0; Coord_i = Xcoord_PhiAngle[iPhiAngle][iVertex]; - + su2double Difference = EquivArea_PhiAngle[iPhiAngle][iVertex]-TargetArea_PhiAngle[iPhiAngle][iVertex]; su2double percentage = fabs(Difference)*100/fabs(TargetArea_PhiAngle[iPhiAngle][iVertex]); - + if ((percentage < 0.1) || (Coord_i < XCoordBegin_OF) || (Coord_i > XCoordEnd_OF)) Difference = 0.0; - + InverseDesign += EAScaleFactor*PhiFactor*Weight_PhiAngle[iPhiAngle][iVertex]*Difference*Difference; - + } - + /*--- Evaluate the weight of the nearfield pressure (adjoint input) ---*/ - + for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) for (iVertex = 0; iVertex < EquivArea_PhiAngle[iPhiAngle].size(); iVertex++) { Coord_i = Xcoord_PhiAngle[iPhiAngle][iVertex]; @@ -9956,64 +9956,64 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry for (jVertex = iVertex; jVertex < EquivArea_PhiAngle[iPhiAngle].size(); jVertex++) { Coord_j = Xcoord_PhiAngle[iPhiAngle][jVertex]; Weight_PhiAngle[iPhiAngle][iVertex] = 1.0; - + su2double Difference = EquivArea_PhiAngle[iPhiAngle][jVertex]-TargetArea_PhiAngle[iPhiAngle][jVertex]; su2double percentage = fabs(Difference)*100/fabs(TargetArea_PhiAngle[iPhiAngle][jVertex]); - + if ((percentage < 0.1) || (Coord_j < XCoordBegin_OF) || (Coord_j > XCoordEnd_OF)) Difference = 0.0; - + NearFieldWeight_PhiAngle[iPhiAngle][iVertex] += EAScaleFactor*PhiFactor*Weight_PhiAngle[iPhiAngle][iVertex]*2.0*Difference*factor*sqrt(Coord_j-Coord_i); } } - + /*--- Write the Nearfield pressure at each Azimuthal PhiAngle ---*/ - + EquivArea_file.precision(15); - + if (output) { - + EquivArea_file.open("nearfield_flow.dat", ios::out); EquivArea_file << "TITLE = \"Equivalent Area evaluation at each azimuthal angle\"" << "\n"; - + if (config->GetSystemMeasurements() == US) EquivArea_file << "VARIABLES = \"Height (in) at r="<< R_Plane*12.0 << " in. (cyl. coord. system)\",\"Equivalent Area (ft2)\",\"Target Equivalent Area (ft2)\",\"Cp\"" << "\n"; else EquivArea_file << "VARIABLES = \"Height (m) at r="<< R_Plane << " m. (cylindrical coordinate system)\",\"Equivalent Area (m2)\",\"Target Equivalent Area (m2)\",\"Cp\"" << "\n"; - + for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) { EquivArea_file << fixed << "ZONE T= \"F=" << PhiAngleList[iPhiAngle] << " deg.\"" << "\n"; for (iVertex = 0; iVertex < Xcoord_PhiAngle[iPhiAngle].size(); iVertex++) { - + su2double XcoordRot = Xcoord_PhiAngle[0][iVertex]*cos(AoA) - Zcoord_PhiAngle[0][iVertex]*sin(AoA); su2double XcoordRot_init = Xcoord_PhiAngle[0][0]*cos(AoA) - Zcoord_PhiAngle[0][0]*sin(AoA); - + if (config->GetSystemMeasurements() == US) EquivArea_file << scientific << (XcoordRot - XcoordRot_init) * 12.0; else EquivArea_file << scientific << (XcoordRot - XcoordRot_init); - + EquivArea_file << scientific << ", " << EquivArea_PhiAngle[iPhiAngle][iVertex] << ", " << TargetArea_PhiAngle[iPhiAngle][iVertex] << ", " << (Pressure_PhiAngle[iPhiAngle][iVertex]-Pressure_Inf)/Pressure_Inf << "\n"; } } - + EquivArea_file.close(); - + } - + /*--- Write Weight file for adjoint computation ---*/ - + FuncGrad_file.precision(15); - + if (output) { - + FuncGrad_file.open("WeightNF.dat", ios::out); - + FuncGrad_file << scientific << "-1.0"; for (iPhiAngle = 0; iPhiAngle < PhiAngleList.size(); iPhiAngle++) FuncGrad_file << scientific << "\t" << PhiAngleList[iPhiAngle]; FuncGrad_file << "\n"; - + for (iVertex = 0; iVertex < NearFieldWeight_PhiAngle[0].size(); iVertex++) { su2double XcoordRot = Xcoord_PhiAngle[0][iVertex]*cos(AoA) - Zcoord_PhiAngle[0][iVertex]*sin(AoA); FuncGrad_file << scientific << XcoordRot; @@ -10022,41 +10022,41 @@ void COutputLegacy::SpecialOutput_SonicBoom(CSolver *solver, CGeometry *geometry FuncGrad_file << "\n"; } FuncGrad_file.close(); - + } - + /*--- Delete structures ---*/ - + delete [] Xcoord; delete [] Ycoord; delete [] Zcoord; delete [] AzimuthalAngle; delete [] IdPoint; delete [] IdDomain; delete [] Pressure; delete [] FaceArea; delete [] EquivArea; delete [] TargetArea; delete [] NearFieldWeight; delete [] Weight; - + } - + #ifndef HAVE_MPI - + /*--- Store the value of the NearField coefficient ---*/ - + solver->SetTotal_CEquivArea(InverseDesign); - + #else - + /*--- Send the value of the NearField coefficient to all the processors ---*/ - + SU2_MPI::Bcast(&InverseDesign, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); - + /*--- Store the value of the NearField coefficient ---*/ - + solver->SetTotal_CEquivArea(InverseDesign); - + #endif - + } void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) { - + unsigned short iMarker, iDim, iMarker_Analyze; unsigned long iPoint, iVertex; su2double xCoord = 0.0, yCoord = 0.0, zCoord = 0.0, Area = 0.0, *Vector, TotalArea = 0.0; @@ -10074,8 +10074,8 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr unsigned long Total_Index; unsigned short Theta_DC60 = 60, nStation_DC60 = 5; su2double PT_Mean, Mach_Mean, q_Mean, PT, q, *PT_Sector, PT_Sector_Min, DC60, *PT_Station, *PT_Station_Min, *Mach_Station, *Mach_Station_Min, IDR, IDC, IDC_Mach; - - + + bool Engine_HalfModel = config->GetEngine_HalfModel(); su2double SignFlip = 1.0; su2double Beta, Alpha; @@ -10098,11 +10098,11 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr if ((config->GetTabular_FileFormat() == TAB_CSV)) strcpy (cstr, "surface_analysis.vtk"); else strcpy (cstr, "surface_analysis.dat"); - + SurfFlow_file.precision(15); SurfFlow_file.open(cstr, ios::out); - + if ((config->GetTabular_FileFormat() == TAB_CSV)) { SurfFlow_file << "# vtk DataFile Version 3.0" << endl; SurfFlow_file << "vtk output" << endl; @@ -10112,9 +10112,9 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr SurfFlow_file <<"TITLE = \"Surface Analysis\"" <inf\", \"TT/TTinf\", \"P/Pinf\", \"T/Tinf\", \"vx/vinf\", \"vy/vinf\", \"vz/vinf\", \"a (deg)\", \"b (deg)\", \"Mach\", \"Filtered a (deg)\", \"Filtered b (deg)\", \"Filtered Mach\"" << endl; } - + } - + /*--- Loop over all the markers to analyze ---*/ for (iMarker_Analyze = 0; iMarker_Analyze < config->GetnMarker_Analyze(); iMarker_Analyze++) { @@ -10140,7 +10140,7 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr /*--- Communicate the number of local vertices on each partition to the master node ---*/ - + Buffer_Send_nVertex[0] = nLocalVertex_Surface; if (rank == MASTER_NODE) Buffer_Recv_nVertex = new unsigned long [nProcessor]; @@ -10165,36 +10165,36 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr su2double *Buffer_Send_PT = NULL, *Buffer_Recv_PT = NULL; Buffer_Send_PT = new su2double [MaxLocalVertex_Surface]; - + su2double *Buffer_Send_TT = NULL, *Buffer_Recv_TT = NULL; Buffer_Send_TT = new su2double [MaxLocalVertex_Surface]; - + su2double *Buffer_Send_P = NULL, *Buffer_Recv_P = NULL; Buffer_Send_P = new su2double [MaxLocalVertex_Surface]; - + su2double *Buffer_Send_T = NULL, *Buffer_Recv_T = NULL; Buffer_Send_T = new su2double [MaxLocalVertex_Surface]; - + su2double *Buffer_Send_Mach = NULL, *Buffer_Recv_Mach = NULL; Buffer_Send_Mach = new su2double [MaxLocalVertex_Surface]; - + su2double *Buffer_Send_Vel_x = NULL, *Buffer_Recv_Vel_x = NULL; Buffer_Send_Vel_x = new su2double [MaxLocalVertex_Surface]; - + su2double *Buffer_Send_Vel_y = NULL, *Buffer_Recv_Vel_y = NULL; Buffer_Send_Vel_y = new su2double [MaxLocalVertex_Surface]; - + su2double *Buffer_Send_Vel_z = NULL, *Buffer_Recv_Vel_z = NULL; if (nDim == 3) Buffer_Send_Vel_z = new su2double [MaxLocalVertex_Surface]; - + su2double *Buffer_Send_q = NULL, *Buffer_Recv_q = NULL; Buffer_Send_q = new su2double [MaxLocalVertex_Surface]; - + su2double *Buffer_Send_Area = NULL, *Buffer_Recv_Area = NULL; Buffer_Send_Area = new su2double [MaxLocalVertex_Surface]; - + /*--- Prepare the receive buffers on the master node only. ---*/ - + if (rank == MASTER_NODE) { Buffer_Recv_Coord_x = new su2double [nProcessor*MaxLocalVertex_Surface]; Buffer_Recv_Coord_y = new su2double [nProcessor*MaxLocalVertex_Surface]; @@ -10212,25 +10212,25 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr Buffer_Recv_q = new su2double [nProcessor*MaxLocalVertex_Surface]; Buffer_Recv_Area = new su2double [nProcessor*MaxLocalVertex_Surface]; } - + /*--- Loop over all vertices in this partition and load the data of the specified type into the buffer to be sent to the master node. ---*/ - + nVertex_Surface = 0; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { string Marker_TagBound = config->GetMarker_All_TagBound(iMarker); if (Marker_TagBound == Analyze_TagBound) { - + for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - + if (geometry->node[iPoint]->GetDomain()) { - + Buffer_Send_Coord_x[nVertex_Surface] = geometry->node[iPoint]->GetCoord(0); Buffer_Send_Coord_y[nVertex_Surface] = geometry->node[iPoint]->GetCoord(1); if (nDim == 3) { Buffer_Send_Coord_z[nVertex_Surface] = geometry->node[iPoint]->GetCoord(2); } - + Pressure = solver->GetNodes()->GetPressure(iPoint); Density = solver->GetNodes()->GetDensity(iPoint); Temperature = solver->GetNodes()->GetTemperature(iPoint); @@ -10238,61 +10238,61 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr Velocity2 = solver->GetNodes()->GetVelocity2(iPoint); Mach = sqrt(Velocity2)/SoundSpeed; Gamma = config->GetGamma(); - + Mach_Inf = config->GetMach(); Pressure_Inf = config->GetPressure_FreeStreamND(); Temperature_Inf = config->GetTemperature_FreeStreamND(); Velocity_Inf = sqrt(config->GetVelocity_FreeStreamND()[0]*config->GetVelocity_FreeStreamND()[0] + config->GetVelocity_FreeStreamND()[1]*config->GetVelocity_FreeStreamND()[1] + config->GetVelocity_FreeStreamND()[2]*config->GetVelocity_FreeStreamND()[2]); - + Buffer_Send_P[nVertex_Surface] = Pressure / Pressure_Inf; Buffer_Send_T[nVertex_Surface] = Temperature / Temperature_Inf; Buffer_Send_Mach[nVertex_Surface] = Mach; - + TotalPressure = Pressure * pow( 1.0 + Mach * Mach * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0)); TotalPressure_Inf = Pressure_Inf * pow( 1.0 + Mach_Inf * Mach_Inf * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0)); Buffer_Send_PT[nVertex_Surface] = TotalPressure / TotalPressure_Inf; - + TotalTemperature = Temperature * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0)); TotalTemperature_Inf = Temperature_Inf * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0)); Buffer_Send_TT[nVertex_Surface] = TotalTemperature / TotalTemperature_Inf; - + Buffer_Send_Vel_x[nVertex_Surface] = solver->GetNodes()->GetVelocity(iPoint,0) / Velocity_Inf; Buffer_Send_Vel_y[nVertex_Surface] = solver->GetNodes()->GetVelocity(iPoint,1) / Velocity_Inf; if (nDim == 3) { Buffer_Send_Vel_z[nVertex_Surface] = solver->GetNodes()->GetVelocity(iPoint,2) / Velocity_Inf; } - + Buffer_Send_q[nVertex_Surface] = 0.5*Density*Velocity2; - + Vector = geometry->vertex[iMarker][iVertex]->GetNormal(); Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Area += Vector[iDim]*Vector[iDim]; } Area = sqrt(Area); Buffer_Send_Area[nVertex_Surface] = Area; - + /*--- If US system, the output should be in inches ---*/ - + if (config->GetSystemMeasurements() == US) { - + Buffer_Send_Coord_x[nVertex_Surface] *= 12.0; Buffer_Send_Coord_y[nVertex_Surface] *= 12.0; if (nDim == 3) Buffer_Send_Coord_z[nVertex_Surface] *= 12.0; Buffer_Send_Area[nVertex_Surface] *= 144.0; - + } - + nVertex_Surface++; - + } } break; } } - + /*--- Send the information to the master node ---*/ - + #ifdef HAVE_MPI - + SU2_MPI::Gather(Buffer_Send_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_x, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_y, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Coord_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); @@ -10306,9 +10306,9 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr if (nDim == 3) SU2_MPI::Gather(Buffer_Send_Vel_z, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Vel_z, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_q, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_q, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); SU2_MPI::Gather(Buffer_Send_Area, MaxLocalVertex_Surface, MPI_DOUBLE, Buffer_Recv_Area, MaxLocalVertex_Surface, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); - + #else - + for (iVertex = 0; iVertex < MaxLocalVertex_Surface; iVertex++) { Buffer_Recv_Coord_x[iVertex] = Buffer_Send_Coord_x[iVertex]; Buffer_Recv_Coord_y[iVertex] = Buffer_Send_Coord_y[iVertex]; @@ -10324,31 +10324,31 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr Buffer_Recv_q[iVertex] = Buffer_Send_q[iVertex]; Buffer_Recv_Area[iVertex] = Buffer_Send_Area[iVertex]; } - + #endif - + if (rank == MASTER_NODE) { - + /*--- Compute the location of the critical points of the distortion measure, and center of gravity ---*/ - + TotalArea = 0.0; xCoord_CG = 0.0; yCoord_CG = 0.0; zCoord_CG = 0.0; PT_Mean = 0.0; Mach_Mean = 0.0; q_Mean = 0.0; - + for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) { - + /*--- Current index position and global index ---*/ - + Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex; - + /*--- Retrieve the merged data for this node ---*/ - + xCoord = Buffer_Recv_Coord_x[Total_Index]; yCoord = Buffer_Recv_Coord_y[Total_Index]; if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index]; PT = Buffer_Recv_PT[Total_Index]; Mach = Buffer_Recv_Mach[Total_Index]; q = Buffer_Recv_q[Total_Index]; - + Area = Buffer_Recv_Area[Total_Index]; TotalArea += Area; xCoord_CG += xCoord*Area; @@ -10357,66 +10357,66 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr PT_Mean += PT*Area; Mach_Mean += PT*Area; q_Mean += q*Area; - + } } - + /*--- Evaluate the area averaged pressure and CG ---*/ - + xCoord_CG = xCoord_CG / TotalArea; yCoord_CG = yCoord_CG / TotalArea; zCoord_CG = zCoord_CG / TotalArea; PT_Mean /= TotalArea; Mach_Mean /= TotalArea; q_Mean /= TotalArea; - + /*--- If it is a half model, CGy = 0 ---*/ - + if (Engine_HalfModel) { yCoord_CG = 0.0; } - + /*--- Compute hub and tip radius ---*/ - + TipRadius = 1E-6; HubRadius = 1E6; for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) { - + /*--- Current index position and global index ---*/ - + Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex; - + /*--- Retrieve the merged data for this node ---*/ - + xCoord = Buffer_Recv_Coord_x[Total_Index]; yCoord = Buffer_Recv_Coord_y[Total_Index]; if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index]; - + if (nDim == 2) Distance = sqrt((xCoord_CG-xCoord)*(xCoord_CG-xCoord) + (yCoord_CG-yCoord)*(yCoord_CG-yCoord)); - + if (nDim == 3) Distance = sqrt((xCoord_CG-xCoord)*(xCoord_CG-xCoord) + (yCoord_CG-yCoord)*(yCoord_CG-yCoord) + (zCoord_CG-zCoord)*(zCoord_CG-zCoord)); - + if (Distance > TipRadius) TipRadius = Distance; if (Distance < HubRadius) HubRadius = Distance; - + } } - + if (HubRadius/TipRadius < 0.05) HubRadius = 0.0; - + /*--- Evaluate the DC60 parameter ---*/ - + Theta = Theta_DC60; nStation = nStation_DC60; - + nAngle = SU2_TYPE::Int(360/float(Theta)); r = new su2double [nStation+1]; - + /*--- Allocate memory ---*/ - + PT_Sector = new su2double [nAngle]; ProbeArray = new su2double ** [nAngle]; for (iAngle = 0; iAngle < nAngle; iAngle++) { @@ -10425,91 +10425,91 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr ProbeArray[iAngle][iStation] = new su2double [5]; } } - + /*--- Define the radius for each probe ---*/ - + r[0] = HubRadius; r[nStation] = TipRadius; for (iStation = 1; iStation < nStation; iStation++) { r[iStation] = sqrt( r[iStation-1]*r[iStation-1] + (r[nStation]*r[nStation] - r[0]*r[0])/float(nStation) ); } - + /*--- Define the probe rack ---*/ - + UpVector[0] = 0.0; UpVector[1] = 0.0; UpVector[2] = 1.0; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { - + radians = -iAngle*Theta*2.0*PI_NUMBER/360; RotatedVector[0] = UpVector[0]; RotatedVector[1] = UpVector[1] * cos(radians) - UpVector[2] * sin(radians); RotatedVector[2] = UpVector[1] * sin(radians) + UpVector[2] * cos(radians); - + for (iStation = 1; iStation <= nStation; iStation++) { ProbeArray[iAngle][iStation-1][0] = xCoord_CG+RotatedVector[0]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1])); ProbeArray[iAngle][iStation-1][1] = yCoord_CG+RotatedVector[1]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1])); ProbeArray[iAngle][iStation-1][2] = zCoord_CG+RotatedVector[2]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1])); } - + } - + /*--- Compute the Total pressure at each probe, closes grid point to the location ---*/ - + for (iAngle = 0; iAngle < nAngle; iAngle++) { - + for (iStation = 0; iStation < nStation; iStation++) { xCoord_ = ProbeArray[iAngle][iStation][0]; yCoord_ = ProbeArray[iAngle][iStation][1]; zCoord_ = ProbeArray[iAngle][iStation][2]; - + MinDistance = 1E6; - + for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) { - + Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex; xCoord = Buffer_Recv_Coord_x[Total_Index]; yCoord = Buffer_Recv_Coord_y[Total_Index]; if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index]; - + dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord); if (nDim == 3) dz = (zCoord_ - zCoord); - + Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance); - + if (Engine_HalfModel) { - + yCoord = -yCoord; - + dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord); if (nDim == 3) dz_ = (zCoord_ - zCoord); - + Distance_Mirror = dx_*dx_ + dy_*dy_; if (nDim == 3) Distance_Mirror += dz_*dz_; Distance_Mirror = sqrt(Distance_Mirror); - + if (Distance_Mirror < Distance) { Distance = Distance_Mirror; dx = dx_; dy = dy_; if (nDim == 3) dz = dz_; } - + } - + if (Distance <= MinDistance) { MinDistance = Distance; ProbeArray[iAngle][iStation][3] = Buffer_Recv_PT[Total_Index]; ProbeArray[iAngle][iStation][4] = Buffer_Recv_q[Total_Index]; } - + } } - + } - + } - + /*--- Evaluate the average pressure at each sector, fan face and dynamic pressure ---*/ - + PT_Mean = 0.0; q_Mean = 0.0; for (iAngle = 0; iAngle < nAngle; iAngle++) { PT_Sector[iAngle] = 0.0; @@ -10519,50 +10519,50 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr q_Mean += ProbeArray[iAngle][iStation][4]/float(nStation*nAngle); } } - + /*--- Compute the min value of the averaged pressure at each sector ---*/ - + PT_Sector_Min = PT_Sector[0]; for (iAngle = 1; iAngle < nAngle; iAngle++) { if (PT_Sector[iAngle] <= PT_Sector_Min) PT_Sector_Min = PT_Sector[iAngle]; } - + /*--- Set the value of the distortion, it only works for one surface ---*/ - + Mach_Inf = config->GetMach(); Gamma = config->GetGamma(); TotalPressure_Inf = config->GetPressure_FreeStreamND() * pow( 1.0 + Mach_Inf * Mach_Inf * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0)); - + if (q_Mean != 0.0) DC60 = ((PT_Mean - PT_Sector_Min)*TotalPressure_Inf)/q_Mean; else DC60 = 0.0; - + config->SetSurface_DC60(iMarker_Analyze, DC60); - + solver->SetTotal_DC60(DC60); - + /*--- Deallocate the memory ---*/ - + delete[] r; - + delete [] PT_Sector; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { delete[] ProbeArray[iAngle][iStation]; } } delete[] ProbeArray; - - + + /*--- Evaluate the IDC, and IDR parameters ---*/ - + nStation = SU2_TYPE::Int(config->GetDistortionRack()[0]); Theta = SU2_TYPE::Int(config->GetDistortionRack()[1]); nAngle = SU2_TYPE::Int(360/float(Theta)); - + /*--- Allocate memory ---*/ - + r = new su2double [nStation+1]; ProbeArray = new su2double ** [nAngle]; for (iAngle = 0; iAngle < nAngle; iAngle++) { @@ -10571,92 +10571,92 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr ProbeArray[iAngle][iStation] = new su2double [4]; } } - + /*--- Define the radius for each probe ---*/ - + r[0] = HubRadius; r[nStation] = TipRadius; for (iStation = 1; iStation < nStation; iStation++) { r[iStation] = sqrt( r[iStation-1]*r[iStation-1] + (r[nStation]*r[nStation] - r[0]*r[0])/float(nStation) ); } - + /*--- Define the probe rack ---*/ - + UpVector[0] = 0.0; UpVector[1] = 0.0; UpVector[2] = 1.0; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { - + radians = -iAngle*Theta*2.0*PI_NUMBER/360; RotatedVector[0] = UpVector[0]; RotatedVector[1] = UpVector[1] * cos(radians) - UpVector[2] * sin(radians); RotatedVector[2] = UpVector[1] * sin(radians) + UpVector[2] * cos(radians); - + for (iStation = 1; iStation <= nStation; iStation++) { ProbeArray[iAngle][iStation-1][0] = xCoord_CG+RotatedVector[0]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1])); ProbeArray[iAngle][iStation-1][1] = yCoord_CG+RotatedVector[1]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1])); ProbeArray[iAngle][iStation-1][2] = zCoord_CG+RotatedVector[2]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1])); } - + } - + /*--- Compute the Total pressure at each probe, closes grid point to the location ---*/ - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { xCoord_ = ProbeArray[iAngle][iStation][0]; yCoord_ = ProbeArray[iAngle][iStation][1]; zCoord_ = ProbeArray[iAngle][iStation][2]; - + MinDistance = 1E6; - + for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) { - + Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex; xCoord = Buffer_Recv_Coord_x[Total_Index]; yCoord = Buffer_Recv_Coord_y[Total_Index]; if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index]; - + dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord); if (nDim == 3) dz = (zCoord_ - zCoord); - + Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance); - + if (Engine_HalfModel) { - + yCoord = -yCoord; - + dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord); if (nDim == 3) dz_ = (zCoord_ - zCoord); - + Distance_Mirror = dx_*dx_ + dy_*dy_; if (nDim == 3) Distance_Mirror += dz_*dz_; Distance_Mirror = sqrt(Distance_Mirror); - + if (Distance_Mirror < Distance) { Distance = Distance_Mirror; dx = dx_; dy = dy_; if (nDim == 3) dz = dz_; } - + } - + if (Distance <= MinDistance) { MinDistance = Distance; ProbeArray[iAngle][iStation][3] = Buffer_Recv_PT[Total_Index]; } - + } } - + } - + } - + /*--- Evaluate the average and min. pressure at each station/radius and fan ---*/ - + PT_Station = new su2double [nStation]; PT_Station_Min = new su2double [nStation]; - + PT_Mean = 0.0; for (iStation = 0; iStation < nStation; iStation++) { PT_Station[iStation] = 0.0; @@ -10668,97 +10668,97 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr PT_Mean += ProbeArray[iAngle][iStation][3]/float(nStation*nAngle); } } - + /*--- Set the value of the distortion, it only works for one surface ---*/ - + IDC = 0.0; for (iStation = 0; iStation < nStation-1; iStation++) { IDC = max (IDC, 0.5*((PT_Station[iStation] - PT_Station_Min[iStation])/PT_Mean + (PT_Station[iStation+1] - PT_Station_Min[iStation+1])/PT_Mean) ); - + } - + config->SetSurface_IDC(iMarker_Analyze, IDC); solver->SetTotal_IDC(IDC); - + IDR = 0.0; for (iStation = 0; iStation < nStation; iStation++) { IDR = max (IDR, (PT_Mean-PT_Station[iStation])/PT_Mean); } - + config->SetSurface_IDR(iMarker_Analyze, IDR); - + solver->SetTotal_IDR(IDR); - + /*--- Release IDX parameters ---*/ - + delete [] PT_Station_Min; delete [] PT_Station; - + /*--- Evaluate the IDC Mach parameter ---*/ - + /*--- Compute the Mach number at each probe, closes grid point to the location ---*/ - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { xCoord_ = ProbeArray[iAngle][iStation][0]; yCoord_ = ProbeArray[iAngle][iStation][1]; zCoord_ = ProbeArray[iAngle][iStation][2]; - + MinDistance = 1E6; - + for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) { - + Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex; - + xCoord = Buffer_Recv_Coord_x[Total_Index]; yCoord = Buffer_Recv_Coord_y[Total_Index]; if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index]; - + dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord); if (nDim == 3) dz = (zCoord_ - zCoord); - + Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance); - + if (Engine_HalfModel) { - + yCoord = -yCoord; - + dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord); if (nDim == 3) dz_ = (zCoord_ - zCoord); - + Distance_Mirror = dx_*dx_ + dy_*dy_; if (nDim == 3) Distance_Mirror += dz_*dz_; Distance_Mirror = sqrt(Distance_Mirror); - + if (Distance_Mirror < Distance) { Distance = Distance_Mirror; dx = dx_; dy = dy_; if (nDim == 3) dz = dz_; } - + } - + if (Distance <= MinDistance) { MinDistance = Distance; ProbeArray[iAngle][iStation][3] = Buffer_Recv_Mach[Total_Index]; } - + } } - + } - + } - + /*--- Evaluate the average and min. pressure at each station/radius and fan face ---*/ - + Mach_Station = new su2double [nStation]; Mach_Station_Min = new su2double [nStation]; - + Mach_Mean = 0.0; for (iStation = 0; iStation < nStation; iStation++) { Mach_Station[iStation] = 0.0; @@ -10770,26 +10770,26 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr Mach_Mean += ProbeArray[iAngle][iStation][3]/float(nStation*nAngle); } } - + /*--- Set the value of the distortion, it only works for one surface ---*/ - + IDC_Mach = 0.0; for (iStation = 0; iStation < nStation-1; iStation++) { if (Mach_Mean != 0) IDC_Mach = max (IDC_Mach, 0.5*((Mach_Station[iStation] - Mach_Station_Min[iStation])/Mach_Mean + (Mach_Station[iStation+1] - Mach_Station_Min[iStation+1])/Mach_Mean) ); - + } - + config->SetSurface_IDC_Mach(iMarker_Analyze, IDC_Mach); - + solver->SetTotal_IDC_Mach(IDC_Mach); - + delete [] Mach_Station_Min; delete [] Mach_Station; - + /*--- Release distortion parameters ---*/ - + delete[] r; for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { @@ -10797,16 +10797,16 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr } } delete[] ProbeArray; - + /*--- Create the distortion plot ---*/ - + Theta = 10; nStation = 20; - + nAngle = SU2_TYPE::Int(360/float(Theta)); r = new su2double [nStation+1]; - + /*--- Allocate memory ---*/ - + ProbeArray = new su2double ** [nAngle]; for (iAngle = 0; iAngle < nAngle; iAngle++) { ProbeArray[iAngle] = new su2double * [nStation]; @@ -10814,82 +10814,82 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr ProbeArray[iAngle][iStation] = new su2double [11]; } } - + /*--- Define the radius for each probe ---*/ - + r[0] = HubRadius; r[nStation] = TipRadius; - + for (iStation = 1; iStation < nStation; iStation++) { r[iStation] = sqrt( r[iStation-1]*r[iStation-1] + (r[nStation]*r[nStation] - r[0]*r[0])/float(nStation) ); } - + /*--- Define the probe rack ---*/ - + UpVector[0] = 0.0; UpVector[1] = 0.0; UpVector[2] = 1.0; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { - + radians = -iAngle*Theta*2.0*PI_NUMBER/360; RotatedVector[0] = UpVector[0]; RotatedVector[1] = UpVector[1] * cos(radians) - UpVector[2] * sin(radians); RotatedVector[2] = UpVector[1] * sin(radians) + UpVector[2] * cos(radians); - + for (iStation = 1; iStation <= nStation; iStation++) { ProbeArray[iAngle][iStation-1][0] = xCoord_CG+RotatedVector[0]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1])); ProbeArray[iAngle][iStation-1][1] = yCoord_CG+RotatedVector[1]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1])); ProbeArray[iAngle][iStation-1][2] = zCoord_CG+RotatedVector[2]*sqrt(0.5*(r[iStation]*r[iStation]+r[iStation-1]*r[iStation-1])); } - + } - + /*--- Compute the primitieve variables, closest grid point to the location + gradient ---*/ - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { xCoord_ = ProbeArray[iAngle][iStation][0]; yCoord_ = ProbeArray[iAngle][iStation][1]; zCoord_ = ProbeArray[iAngle][iStation][2]; - + MinDistance = 1E6; - + for (iProcessor = 0; iProcessor < nProcessor; iProcessor++) { for (iVertex = 0; iVertex < Buffer_Recv_nVertex[iProcessor]; iVertex++) { - + Total_Index = iProcessor*MaxLocalVertex_Surface+iVertex; xCoord = Buffer_Recv_Coord_x[Total_Index]; yCoord = Buffer_Recv_Coord_y[Total_Index]; if (nDim == 3) zCoord = Buffer_Recv_Coord_z[Total_Index]; - + dx = (xCoord_ - xCoord); dy = (yCoord_ - yCoord); if (nDim == 3) dz = (zCoord_ - zCoord); - + Distance = dx*dx + dy*dy; if (nDim == 3) Distance += dz*dz; Distance = sqrt(Distance); - + SignFlip = 1.0; - + if (Engine_HalfModel) { - + yCoord = -yCoord; - + dx_ = (xCoord_ - xCoord); dy_ = (yCoord_ - yCoord); if (nDim == 3) dz_ = (zCoord_ - zCoord); - + Distance_Mirror = dx_*dx_ + dy_*dy_; if (nDim == 3) Distance_Mirror += dz_*dz_; Distance_Mirror = sqrt(Distance_Mirror); - + if (Distance_Mirror < Distance) { SignFlip = -1.0; Distance = Distance_Mirror; dx = dx_; dy = dy_; if (nDim == 3) dz = dz_; } - + } - - + + if (Distance <= MinDistance) { MinDistance = Distance; ProbeArray[iAngle][iStation][3] = Buffer_Recv_PT[Total_Index]; @@ -10901,16 +10901,16 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr ProbeArray[iAngle][iStation][9] = SignFlip * Buffer_Recv_Vel_y[Total_Index]; if (nDim == 3) ProbeArray[iAngle][iStation][10] = Buffer_Recv_Vel_z[Total_Index]; } - + } } - + } - + } - + /*--- Reverse in the Y direction to move the solution from 3D to 2D ---*/ - + yCoord_CG = -yCoord_CG; for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { @@ -10918,11 +10918,11 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr ProbeArray[iAngle][iStation][1] = -ProbeArray[iAngle][iStation][1]; } } - + if (output) { - + if (config->GetTabular_FileFormat() == TAB_CSV) { - + SurfFlow_file << "\nDATASET UNSTRUCTURED_GRID" << endl; SurfFlow_file <<"POINTS " << nAngle*nStation << " float" << endl; for (iAngle = 0; iAngle < nAngle; iAngle++) { @@ -10930,7 +10930,7 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr SurfFlow_file << ProbeArray[iAngle][iStation][1]-yCoord_CG << " " << ProbeArray[iAngle][iStation][2]-zCoord_CG << " 0.0 " <<" "; } } - + SurfFlow_file <<"\nCELLS " << nAngle*(nStation-1) <<" "<< nAngle*(nStation-1)*5 << endl; for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation-1; iStation++) { @@ -10939,81 +10939,81 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr SurfFlow_file << "4 " << a <<" "<< b <<" "<< c <<" "<< d <<" "; } } - + SurfFlow_file <<"\nCELL_TYPES " << nAngle*(nStation-1) << endl; for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation-1; iStation++) { SurfFlow_file << "9 " ; } } - + SurfFlow_file <<"\nPOINT_DATA " << nAngle*nStation << endl; SurfFlow_file <<"SCALARS PT/PT_inf float" << endl; SurfFlow_file <<"LOOKUP_TABLE default" << endl; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { SurfFlow_file << ProbeArray[iAngle][iStation][3] << " "; } } - + SurfFlow_file <<"SCALARS TT/TT_inf float" << endl; SurfFlow_file <<"LOOKUP_TABLE default" << endl; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { SurfFlow_file << ProbeArray[iAngle][iStation][4] << " "; } } - + SurfFlow_file <<"SCALARS Alpha float" << endl; SurfFlow_file <<"LOOKUP_TABLE default" << endl; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { Alpha = atan(ProbeArray[iAngle][iStation][10]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER); SurfFlow_file << Alpha << " "; } } - + SurfFlow_file <<"SCALARS Beta float" << endl; SurfFlow_file <<"LOOKUP_TABLE default" << endl; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { Beta = atan(ProbeArray[iAngle][iStation][9]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER); SurfFlow_file << Beta << " "; } } - + SurfFlow_file <<"SCALARS Mach float" << endl; SurfFlow_file <<"LOOKUP_TABLE default" << endl; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { SurfFlow_file << ProbeArray[iAngle][iStation][7] << " "; } } - + SurfFlow_file <<"VECTORS Velocity float" << endl; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { SurfFlow_file << ProbeArray[iAngle][iStation][8] << " " << ProbeArray[iAngle][iStation][9] << " " << ProbeArray[iAngle][iStation][10] << " "; } } - + } else { - + SurfFlow_file <<"ZONE T= \"" << Analyze_TagBound <<"\", NODES=" << nAngle*nStation << " , ELEMENTS= " << nAngle*(nStation-1) <<", DATAPACKING=POINT, ZONETYPE=FEQUADRILATERAL" << endl; - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { - + Alpha = atan(ProbeArray[iAngle][iStation][10]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER); Beta = atan(ProbeArray[iAngle][iStation][9]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER); - + Mach_ij = ProbeArray[iAngle][iStation][7]; if (iAngle+1 != nAngle) Mach_ip1j = ProbeArray[iAngle+1][iStation][7]; else Mach_ip1j = ProbeArray[0][iStation][7]; @@ -11024,7 +11024,7 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr if (iStation-1 != -1) Mach_ijm1 = ProbeArray[iAngle][iStation-1][7]; else Mach_ijm1 = ProbeArray[iAngle][nStation-1][7]; Filtered_Mach = (4.0*Mach_ij+Mach_ip1j+Mach_im1j+Mach_ijp1+Mach_ijm1)/8.0; - + Alpha_ij = atan(ProbeArray[iAngle][iStation][10]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER); if (iAngle+1 != nAngle) Alpha_ip1j = atan(ProbeArray[iAngle+1][iStation][10]/ProbeArray[iAngle+1][iStation][8])*360.0/(2.0*PI_NUMBER); else Alpha_ip1j = atan(ProbeArray[0][iStation][10]/ProbeArray[0][iStation][8])*360.0/(2.0*PI_NUMBER); @@ -11035,7 +11035,7 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr if (iStation-1 != -1) Alpha_ijm1 = atan(ProbeArray[iAngle][iStation-1][10]/ProbeArray[iAngle][iStation-1][8])*360.0/(2.0*PI_NUMBER); else Alpha_ijm1 = atan(ProbeArray[iAngle][nStation-1][10]/ProbeArray[iAngle][nStation-1][8])*360.0/(2.0*PI_NUMBER); Filtered_Alpha = (4.0*Alpha_ij+Alpha_ip1j+Alpha_im1j+Alpha_ijp1+Alpha_ijm1)/8.0; - + Beta_ij = atan(ProbeArray[iAngle][iStation][9]/ProbeArray[iAngle][iStation][8])*360.0/(2.0*PI_NUMBER); if (iAngle+1 != nAngle) Beta_ip1j = atan(ProbeArray[iAngle+1][iStation][9]/ProbeArray[iAngle+1][iStation][8])*360.0/(2.0*PI_NUMBER); else Beta_ip1j = atan(ProbeArray[0][iStation][9]/ProbeArray[0][iStation][8])*360.0/(2.0*PI_NUMBER); @@ -11046,8 +11046,8 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr if (iStation-1 != -1) Beta_ijm1 = atan(ProbeArray[iAngle][iStation-1][9]/ProbeArray[iAngle][iStation-1][8])*360.0/(2.0*PI_NUMBER); else Beta_ijm1 = atan(ProbeArray[iAngle][nStation-1][9]/ProbeArray[iAngle][nStation-1][8])*360.0/(2.0*PI_NUMBER); Filtered_Beta = (4.0*Beta_ij+Beta_ip1j+Beta_im1j+Beta_ijp1+Beta_ijm1)/8.0; - - + + SurfFlow_file << " " << ProbeArray[iAngle][iStation][1]-yCoord_CG <<" " << ProbeArray[iAngle][iStation][2]-zCoord_CG @@ -11057,10 +11057,10 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr <<" " << ProbeArray[iAngle][iStation][10] <<" " << Alpha <<" " << Beta << " " << ProbeArray[iAngle][iStation][7] <<" " << Filtered_Alpha <<" " << Filtered_Beta << " " << Filtered_Mach << endl; - + } } - + for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation-1; iStation++) { a = iAngle*nStation+iStation; b = a + nStation; c = b+1; d = a +1; @@ -11068,9 +11068,9 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr SurfFlow_file << a+1 <<" "<< b+1 <<" "<< c+1 <<" "<< d+1 << endl; } } - + /*--- Add extra info ---*/ - + SurfFlow_file << "TEXT X=14, Y=86, F=HELV-BOLD, C=BLUE, H=2.0, "; unsigned short RackProbes = SU2_TYPE::Int(config->GetDistortionRack()[0]); unsigned short RackAngle = SU2_TYPE::Int(config->GetDistortionRack()[1]); @@ -11083,17 +11083,17 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr SurfFlow_file << ", MassFlow " << config->GetSurface_MassFlow(iMarker_Analyze) << ",\\" << "\\n"; SurfFlow_file << "IDC " << config->GetSurface_IDC(iMarker_Analyze)*100 << "%, IDCM " << config->GetSurface_IDC_Mach(iMarker_Analyze)*100 << "%, IDR " << config->GetSurface_IDR(iMarker_Analyze)*100 << "%,\\" << "\\n"; SurfFlow_file << "DC60 " << config->GetSurface_DC60(iMarker_Analyze) << ".\"" << endl; - + } - + } /*--- Release the recv buffers on the master node ---*/ - + delete [] Buffer_Recv_Coord_x; delete [] Buffer_Recv_Coord_y; if (nDim == 3) delete [] Buffer_Recv_Coord_z; - + delete [] Buffer_Recv_PT; delete [] Buffer_Recv_TT; delete [] Buffer_Recv_P; @@ -11103,11 +11103,11 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr delete [] Buffer_Recv_Vel_y; if (nDim == 3) delete [] Buffer_Recv_Vel_z; delete [] Buffer_Recv_q; - + delete [] Buffer_Recv_Area; - + delete [] Buffer_Recv_nVertex; - + delete[] r; for (iAngle = 0; iAngle < nAngle; iAngle++) { for (iStation = 0; iStation < nStation; iStation++) { @@ -11115,9 +11115,9 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr } } delete[] ProbeArray; - + } - + // if ((rank == MASTER_NODE) && !config->GetDiscrete_Adjoint()) { // // cout << "Surface ("<< Analyze_TagBound << "): "; @@ -11129,13 +11129,13 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr // << "%. DC60 " << config->GetSurface_DC60(iMarker_Analyze) << "." << endl; // // } - + /*--- Release the memory for the remaining buffers and exit ---*/ - + delete [] Buffer_Send_Coord_x; delete [] Buffer_Send_Coord_y; if (nDim == 3) delete [] Buffer_Send_Coord_z; - + delete [] Buffer_Send_PT; delete [] Buffer_Send_TT; delete [] Buffer_Send_P; @@ -11145,13 +11145,13 @@ void COutputLegacy::SpecialOutput_Distortion(CSolver *solver, CGeometry *geometr delete [] Buffer_Send_Vel_y; if (nDim == 3) delete [] Buffer_Send_Vel_z; delete [] Buffer_Send_q; - + delete [] Buffer_Send_Area; - + } - + /*--- Close the tecplot file ---*/ - + if (output) { SurfFlow_file.close(); } @@ -11242,7 +11242,7 @@ void COutputLegacy::SpecialOutput_FSI(ofstream *FSIHist_file, CGeometry ****geom /*--- Flow residual output ---*/ case EULER : case NAVIER_STOKES: case RANS : - case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS : + case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS : FSIHist_file[0] << flow_resid; if (turbulent) FSIHist_file[0] << turb_resid; break; @@ -11272,7 +11272,7 @@ void COutputLegacy::SpecialOutput_FSI(ofstream *FSIHist_file, CGeometry ****geom switch (config[ZONE_FLOW]->GetKind_Solver()) { case EULER : case NAVIER_STOKES: case RANS : - case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS : + case INC_EULER : case INC_NAVIER_STOKES: case INC_RANS : FSIHist_file[0] << flow_coeff; if (turbulent) FSIHist_file[0] << turb_resid; if (direct_diff != NO_DERIVATIVE) { @@ -11281,7 +11281,7 @@ void COutputLegacy::SpecialOutput_FSI(ofstream *FSIHist_file, CGeometry ****geom break; case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS: - case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: + case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: FSIHist_file[0] << adj_flow_resid; break; @@ -11521,7 +11521,7 @@ void COutputLegacy::SetSensitivity_Files(CGeometry ***geometry, CConfig **config (config[iZone]->GetMarker_All_KindBC(iMarker) == ISOTHERMAL ) || (config[iZone]->GetMarker_All_KindBC(iMarker) == CHT_WALL_INTERFACE )) { - + nVertex = geometry[iZone][INST_0]->GetnVertex(iMarker); for (iVertex = 0; iVertex < nVertex; iVertex++) { @@ -11811,12 +11811,12 @@ void COutputLegacy::WriteTurboPerfConvHistory(CConfig *config){ cout << endl << "-------------------------------------------------------------------------" << endl; cout << endl; } - + } void COutputLegacy::SpecialOutput_Turbo(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short val_iZone, bool output) { - + string inMarker_Tag, outMarker_Tag, inMarkerTag_Mix; unsigned short nZone = config[val_iZone]->GetnZone(); @@ -11956,14 +11956,14 @@ void COutputLegacy::SpecialOutput_Turbo(CSolver *****solver, CGeometry ****geome SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone)); spanwise_performance_filename.append(string(buffer)); } - + myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc); myfile.setf(ios::scientific); myfile.precision(12); - + myfile << "TITLE = \"Inflow Span-wise Kinematic Values. iExtIter = " << iExtIter << " \"" << endl; myfile << "VARIABLES =" << endl; - + myfile.width(30); myfile << "\"SpanWise Value[m]\""; myfile.width(15); myfile << "\"iSpan\""; myfile.width(30); myfile << "\"Normal Mach[-]\""; @@ -11977,10 +11977,10 @@ void COutputLegacy::SpecialOutput_Turbo(CSolver *****solver, CGeometry ****geome myfile.width(30); myfile << "\"Absolute Flow Angle[deg]\""; myfile.width(30); myfile << "\"Relative Flow Angle[deg]\""; myfile << endl; - - + + for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){ - + myfile.width(30); myfile << SpanWiseValuesIn[iSpan]; myfile.width(15); myfile << iSpan; for (iDim = 0; iDim < 4; iDim++){ @@ -12003,9 +12003,9 @@ void COutputLegacy::SpecialOutput_Turbo(CSolver *****solver, CGeometry ****geome } myfile << endl; } - + myfile.close(); - + /*--- Writing Span wise outflow thermodynamic quantities. ---*/ spanwise_performance_filename = "TURBOMACHINERY/outflow_spanwise_kinematic_values.dat"; if (nZone > 1){ @@ -12014,14 +12014,14 @@ void COutputLegacy::SpecialOutput_Turbo(CSolver *****solver, CGeometry ****geome SPRINTF (buffer, "_%d.dat", SU2_TYPE::Int(val_iZone)); spanwise_performance_filename.append(string(buffer)); } - + myfile.open (spanwise_performance_filename.data(), ios::out | ios::trunc); myfile.setf(ios::scientific); myfile.precision(12); - + myfile << "TITLE = \"Outflow Span-wise Kinematic Values. iExtIter = " << iExtIter << " \"" << endl; myfile << "VARIABLES =" << endl; - + myfile.width(30); myfile << "\"SpanWise Value[m]\""; myfile.width(15); myfile << "\"iSpan\""; myfile.width(30); myfile << "\"Normal Mach[-]\""; @@ -12035,10 +12035,10 @@ void COutputLegacy::SpecialOutput_Turbo(CSolver *****solver, CGeometry ****geome myfile.width(30); myfile << "\"Absolute Flow Angle[deg]\""; myfile.width(30); myfile << "\"Relative Flow Angle[deg]\""; myfile << endl; - - + + for(iSpan = 0; iSpan < config[ZONE_0]->GetnSpan_iZones(val_iZone); iSpan++){ - + myfile.width(30); myfile << SpanWiseValuesOut[iSpan]; myfile.width(15); myfile << iSpan; for (iDim = 0; iDim < 4; iDim++){ @@ -12061,14 +12061,14 @@ void COutputLegacy::SpecialOutput_Turbo(CSolver *****solver, CGeometry ****geome } myfile << endl; } - + myfile.close(); - + } } void COutputLegacy::SpecialOutput_HarmonicBalance(CSolver *****solver, CGeometry ****geometry, CConfig **config, unsigned short iInst, unsigned short val_nInst, bool output) { - + /*--- Write file with flow quantities for harmonic balance HB ---*/ ofstream HB_output_file; ofstream mean_HB_file; @@ -12113,14 +12113,14 @@ void COutputLegacy::SpecialOutput_HarmonicBalance(CSolver *****solver, CGeometry N.B. Summing across processors within a given zone is being done elsewhere. ---*/ for (kInst = 0; kInst < val_nInst; kInst++) { - + /*--- Flow solution coefficients (parallel) ---*/ sbuf_var[0] = solver[ZONE_0][kInst][MESH_0][FLOW_SOL]->GetTotal_CL(); sbuf_var[1] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CD(); sbuf_var[2] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CMx(); sbuf_var[3] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CMy(); sbuf_var[4] = solver[ZONE_0][kInst][INST_0][FLOW_SOL]->GetTotal_CMz(); - + for (iVar = 0; iVar < nVar_output; iVar++) { rbuf_var[iVar] = sbuf_var[iVar]; } @@ -12184,7 +12184,7 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, CConfig **config, unsigned long iExtIter, unsigned short val_nZone) { - + unsigned short iZone, iVar, iInst; unsigned long iPoint; unsigned short nInst = 1; @@ -12198,12 +12198,12 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, (KindSolver == FEM_NAVIER_STOKES) || (KindSolver == FEM_RANS) || (KindSolver == FEM_LES)); - + /*--- Get the file output format ---*/ - + unsigned short FileFormat = config[iZone]->GetTabular_FileFormat(); nInst = config[iZone]->GetnTimeInstances(); - + for (iInst = 0; iInst < nInst; iInst++){ bool cont_adj = config[iZone]->GetContinuous_Adjoint(); @@ -12240,18 +12240,18 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, PrepareOffsets(config[iZone], geometry[iZone][iInst][MESH_0]); /*--- Write out CSV files in parallel for flow and adjoint. ---*/ - + if (rank == MASTER_NODE) cout << endl << "Writing comma-separated values (CSV) surface files." << endl; - + switch (config[iZone]->GetKind_Solver()) { case EULER : case NAVIER_STOKES : case RANS : - case INC_EULER : case INC_NAVIER_STOKES : case INC_RANS : + case INC_EULER : case INC_NAVIER_STOKES : case INC_RANS : if (Wrt_Csv) SetSurfaceCSV_Flow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, iInst); break; case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS : case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS: - case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: + case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: if (Wrt_Csv) SetSurfaceCSV_Adjoint(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0][ADJFLOW_SOL], solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, iInst); @@ -12268,7 +12268,7 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, switch (config[iZone]->GetKind_Solver()) { case EULER : case NAVIER_STOKES : case RANS : - case INC_EULER : case INC_NAVIER_STOKES : case INC_RANS : + case INC_EULER : case INC_NAVIER_STOKES : case INC_RANS : if (compressible) LoadLocalData_Flow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone); else @@ -12276,7 +12276,7 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, break; case ADJ_EULER : case ADJ_NAVIER_STOKES : case ADJ_RANS : case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_RANS: - case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: + case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: case DISC_ADJ_INC_RANS: LoadLocalData_AdjFlow(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone); break; case FEM_ELASTICITY: case DISC_ADJ_FEM: @@ -12289,62 +12289,62 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, LoadLocalData_FEM(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0], iZone); default: break; } - + /*--- Store the solution to be used on the final iteration with cte. lift mode. ---*/ if ((!cont_adj) && (!disc_adj) && (config[iZone]->GetFixed_CL_Mode()) && - (solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetStart_AoA_FD()) && + (solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetStart_AoA_FD()) && iExtIter == solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetIter_Update_AoA()) { //(config[iZone]->GetnExtIter()-config[iZone]->GetIter_dCL_dAlpha() -1 == iExtIter)) { if (rank == MASTER_NODE) cout << "Storing solution output data locally on each rank (cte. CL mode)." << endl; - + Local_Data_Copy = new su2double*[geometry[iZone][iInst][MESH_0]->GetnPoint()]; for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) { Local_Data_Copy[iPoint] = new su2double[nVar_Par]; } - + for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) { for (iVar = 0; iVar < nVar_Par; iVar++) { Local_Data_Copy[iPoint][iVar] = Local_Data[iPoint][iVar]; } } - + } - + /*--- Recover the solution to be used on the final iteration with cte. lift mode. ---*/ if ((!cont_adj) && (!disc_adj) && (config[iZone]->GetFixed_CL_Mode()) && (solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetEnd_AoA_FD()) && - //(iExtIter - solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetIter_Update_AoA() == config[iZone]->GetIter_dCL_dAlpha()) && + //(iExtIter - solver_container[iZone][iInst][MESH_0][FLOW_SOL]->GetIter_Update_AoA() == config[iZone]->GetIter_dCL_dAlpha()) && (Local_Data_Copy != NULL)) { if (rank == MASTER_NODE) cout << "Recovering solution output data locally on each rank (cte. CL mode)." << endl; - + for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) { for (iVar = 0; iVar < nVar_Par; iVar++) { Local_Data[iPoint][iVar] = Local_Data_Copy[iPoint][iVar]; } } - + for (iPoint = 0; iPoint < geometry[iZone][iInst][MESH_0]->GetnPoint(); iPoint++) delete [] Local_Data_Copy[iPoint]; delete [] Local_Data_Copy; - + } - + /*--- After loading the data local to a processor, we perform a sorting, i.e., a linear partitioning of the data across all ranks in the communicator. ---*/ - + if (rank == MASTER_NODE) cout << "Sorting output data across all ranks." << endl; if (fem_solver) SortOutputData_FEM(config[iZone], geometry[iZone][iInst][MESH_0]); else SortOutputData(config[iZone], geometry[iZone][iInst][MESH_0]); - + /*--- Write either a binary or ASCII restart file in parallel. ---*/ if (config[iZone]->GetWrt_Binary_Restart()) { @@ -12363,14 +12363,14 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, WriteCSV_Slice(config[iZone], geometry[iZone][iInst][MESH_0], solver_container[iZone][iInst][MESH_0][FLOW_SOL], iExtIter, iZone, 1); } - + /*--- Write the solution files if they are requested and we are executing with a single rank (all data on one proc and no comm. overhead). Once we have parallel binary versions of Tecplot / ParaView / CGNS / etc., we can allow the write of the viz. files as well. ---*/ if (Wrt_Vol || Wrt_Srf) { - + /*--- First, sort all connectivity into linearly partitioned chunks of elements. ---*/ if (rank == MASTER_NODE) @@ -12403,7 +12403,7 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, false); break; - + case TECPLOT_BINARY: @@ -12416,7 +12416,7 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, false); break; - + case PARAVIEW: @@ -12426,11 +12426,11 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, // WriteParaViewASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0], // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, false); break; - + case PARAVIEW_BINARY: - + /*--- Write a Paraview binary file ---*/ - + if (rank == MASTER_NODE) cout << "Writing Paraview binary volume solution file." << endl; // WriteParaViewBinary_Parallel(config[iZone], geometry[iZone][iInst][MESH_0], // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, false); @@ -12474,16 +12474,16 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, // WriteParaViewASCII_Parallel(config[iZone], geometry[iZone][iInst][MESH_0], // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, iInst, nInst, true); break; - + case PARAVIEW_BINARY: - + /*--- Write a Paraview binary file ---*/ - + if (rank == MASTER_NODE) cout << "Writing Paraview binary surface solution file." << endl; // WriteParaViewBinary_Parallel(config[iZone], geometry[iZone][iInst][MESH_0], // solver_container[iZone][iInst][MESH_0], iZone, val_nZone, true); break; - + default: break; @@ -12515,15 +12515,15 @@ void COutputLegacy::SetResult_Files_Parallel(CSolver *****solver_container, } void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) { - + unsigned short iDim; unsigned short Kind_Solver = config->GetKind_Solver(); unsigned short nDim = geometry->GetnDim(); - + unsigned long iVar, jVar; unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE, iMarker, iVertex; unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0; - + su2double RefArea = config->GetRefArea(); su2double Gamma = config->GetGamma(); su2double RefVel2; @@ -12536,13 +12536,13 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo bool dynamic_grid = config->GetDynamic_Grid(); bool rotating_frame = config->GetRotating_Frame(); bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic; - + int *Local_Halo = NULL; - + stringstream varname; - + /*--- Set the non-dimensionalization for coefficients. ---*/ - + if (dynamic_grid) { Gas_Constant = config->GetGas_ConstantND(); Mach2Vel = sqrt(Gamma*Gas_Constant*config->GetTemperature_FreeStreamND()); @@ -12557,20 +12557,20 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo RefDensity = solver[FLOW_SOL]->GetDensity_Inf(); RefPressure = solver[FLOW_SOL]->GetPressure_Inf(); factor = 1.0 / (0.5*RefDensity*RefArea*RefVel2); - + /*--- Use a switch statement to decide how many solver containers we have in this zone for output. ---*/ - + switch (config->GetKind_Solver()) { case EULER : case NAVIER_STOKES: FirstIndex = FLOW_SOL; SecondIndex = NONE; break; case RANS : FirstIndex = FLOW_SOL; SecondIndex = TURB_SOL; break; default: SecondIndex = NONE; break; } - + nVar_First = solver[FirstIndex]->GetnVar(); if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar(); nVar_Consv_Par = nVar_First + nVar_Second; - + /*--------------------------------------------------------------------------*/ /*--- Step 1: Register the variables that will be output. To register a ---*/ /*--- variable, two things are required. First, increment the ---*/ @@ -12580,26 +12580,26 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo /*--- Second, add a name for the variable to the vector that ---*/ /*--- holds the string names. ---*/ /*--------------------------------------------------------------------------*/ - + /*--- All output files first need the grid coordinates. ---*/ - + nVar_Par = 1; Variable_Names.push_back("x"); nVar_Par += 1; Variable_Names.push_back("y"); if (geometry->GetnDim() == 3) { nVar_Par += 1; Variable_Names.push_back("z"); } - + /*--- At a mininum, the restarts and visualization files need the conservative variables, so these follow next. ---*/ - + nVar_Par += nVar_Consv_Par; - + Variable_Names.push_back("Density"); Variable_Names.push_back("Momentum_x"); Variable_Names.push_back("Momentum_y"); if (geometry->GetnDim() == 3) Variable_Names.push_back("Momentum_z"); Variable_Names.push_back("Energy"); - + if (SecondIndex != NONE) { if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) { Variable_Names.push_back("TKE"); @@ -12609,21 +12609,21 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo Variable_Names.push_back("Nu_Tilde"); } } - + /*--- If requested, register the limiter and residuals for all of the equations in the current flow problem. ---*/ - + /*--- Add the limiters ---*/ - + if (config->GetWrt_Limiters()) { nVar_Par += nVar_Consv_Par; - + Variable_Names.push_back("Limiter_Density"); Variable_Names.push_back("Limiter_Momentum_x"); Variable_Names.push_back("Limiter_Momentum_y"); if (geometry->GetnDim() == 3) Variable_Names.push_back("Limiter_Momentum_z"); Variable_Names.push_back("Limiter_Energy"); - + if (SecondIndex != NONE) { if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) { Variable_Names.push_back("Limiter_TKE"); @@ -12634,18 +12634,18 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo } } } - + /*--- Add the residuals ---*/ - + if (config->GetWrt_Residuals()) { nVar_Par += nVar_Consv_Par; - + Variable_Names.push_back("Residual_Density"); Variable_Names.push_back("Residual_Momentum_x"); Variable_Names.push_back("Residual_Momentum_y"); if (geometry->GetnDim() == 3) Variable_Names.push_back("Residual_Momentum_z"); Variable_Names.push_back("Residual_Energy"); - + if (SecondIndex != NONE) { if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) { Variable_Names.push_back("Residual_TKE"); @@ -12656,37 +12656,37 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo } } } - + /*--- Add the grid velocity. ---*/ - + if (dynamic_grid) { if (geometry->GetnDim() == 2) nVar_Par += 2; else if (geometry->GetnDim() == 3) nVar_Par += 3; - + Variable_Names.push_back("Grid_Velocity_x"); Variable_Names.push_back("Grid_Velocity_y"); if (geometry->GetnDim() == 3) Variable_Names.push_back("Grid_Velocity_z"); } - - + + /*--- Add Pressure, Temperature, Cp, Mach. ---*/ - + nVar_Par += 1; Variable_Names.push_back("Pressure"); - + nVar_Par += 2; Variable_Names.push_back("Temperature"); Variable_Names.push_back("Mach"); - + nVar_Par += 1; if ((config->GetTabular_FileFormat() == TAB_CSV)){ Variable_Names.push_back("Pressure_Coefficient"); } else { Variable_Names.push_back("Cp"); } - + /*--- Add Laminar Viscosity, Skin Friction, Heat Flux, & yPlus to the restart file ---*/ - + if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) { if ((config->GetTabular_FileFormat() == TAB_CSV)){ nVar_Par += 1; Variable_Names.push_back("Laminar_Viscosity"); @@ -12714,9 +12714,9 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo Variable_Names.push_back("h"); } } - + /*--- Add Eddy Viscosity. ---*/ - + if (Kind_Solver == RANS) { nVar_Par += 2; if ((config->GetTabular_FileFormat() == TAB_CSV)){ @@ -12727,16 +12727,16 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo Variable_Names.push_back("mt"); } } - + /*--- Add the distance to the nearest sharp edge if requested. ---*/ - + if (config->GetWrt_SharpEdges()) { nVar_Par += 1; Variable_Names.push_back("Sharp_Edge_Dist"); } - + /*--- Add the intermittency for the BC trans. model. ---*/ - + if (transition) { nVar_Par += 1; if ((config->GetTabular_FileFormat() == TAB_CSV)){ @@ -12745,19 +12745,19 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo Variable_Names.push_back("gBC"); } } - + if (config->GetKind_HybridRANSLES()!=NO_HYBRIDRANSLES){ nVar_Par +=1; Variable_Names.push_back("DES_LengthScale"); nVar_Par +=1; Variable_Names.push_back("Wall_Distance"); } - + if (config->GetKind_RoeLowDiss() != NO_ROELOWDISS){ nVar_Par +=1; Variable_Names.push_back("Roe_Dissipation"); } - + if (solver[FLOW_SOL]->VerificationSolution) { if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) { nVar_Par += 2*nVar_Consv_Par; @@ -12773,9 +12773,9 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo Variable_Names.push_back("Error_Energy"); } } - + /*--- New variables get registered here before the end of the loop. ---*/ - + if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) { nVar_Par += 2; Variable_Names.push_back("Vorticity_x"); @@ -12783,14 +12783,14 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo if (geometry->GetnDim() == 3) { nVar_Par += 1; Variable_Names.push_back("Vorticity_z"); } - + if (geometry->GetnDim() == 3) { nVar_Par +=1; Variable_Names.push_back("Q_Criterion"); } } - + if (rotating_frame) { nVar_Par += 2; Variable_Names.push_back("Relative_Velocity_x"); @@ -12799,7 +12799,7 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo nVar_Par += 1; Variable_Names.push_back("Relative_Velocity_z"); } } - + if (config->GetWrt_MeshQuality()) { nVar_Par +=1; Variable_Names.push_back("Orthogonality"); @@ -12808,11 +12808,11 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo nVar_Par +=1; Variable_Names.push_back("Volume_Ratio"); } - - - + + + /*--- Auxiliary vectors for variables defined on surfaces only. ---*/ - + if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) { Aux_Frict_x = new su2double[geometry->GetnPoint()]; Aux_Frict_y = new su2double[geometry->GetnPoint()]; @@ -12820,12 +12820,12 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo Aux_Heat = new su2double[geometry->GetnPoint()]; Aux_yPlus = new su2double[geometry->GetnPoint()]; Aux_Buffet = new su2double[geometry->GetnPoint()]; - + /*--- First, loop through the mesh in order to find and store the value of the viscous coefficients at any surface nodes. They will be placed in an auxiliary vector and then communicated like all other volumetric variables. ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { Aux_Frict_x[iPoint] = 0.0; Aux_Frict_y[iPoint] = 0.0; @@ -12848,30 +12848,30 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo } } } - + /*--- Allocate the local data structure now that we know how many variables are in the output. ---*/ - + Local_Data = new su2double*[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { Local_Data[iPoint] = new su2double[nVar_Par]; } - + Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + /*--- Search all send/recv boundaries on this partition for any periodic nodes that were part of the original domain. We want to recover these for visualization purposes. ---*/ - + if (!Wrt_Halo) { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { - + /*--- Checking for less than or equal to the rank, because there may be some periodic halo nodes that send info to the same rank. ---*/ - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && @@ -12881,7 +12881,7 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo } } } - + /*--------------------------------------------------------------------------*/ /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/ /*--- the restart and vizualization files. Note that we need to ---*/ @@ -12893,47 +12893,47 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo /*--- ordering of the data loading MUST match the order of the ---*/ /*--- variable registration above for the files to be correct. ---*/ /*--------------------------------------------------------------------------*/ - + jPoint = 0; - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Restart the column index with each new point. ---*/ - + iVar = 0; - + /*--- Load the grid node coordinate values. ---*/ - + for (iDim = 0; iDim < geometry->GetnDim(); iDim++) { Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim); if (config->GetSystemMeasurements() == US) Local_Data[jPoint][iVar] *= 12.0; iVar++; } - + /*--- Load the conservative variable states for the mean flow variables. ---*/ - + for (jVar = 0; jVar < nVar_First; jVar++) { Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar); iVar++; } - + /*--- If this is RANS, i.e., the second solver container is not empty, then load data for the conservative turbulence variables. ---*/ - + if (SecondIndex != NONE) { for (jVar = 0; jVar < nVar_Second; jVar++) { Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetSolution(iPoint, jVar); iVar++; } } - + /*--- If limiters and/or residuals are requested. ---*/ - + /*--- Limiters ---*/ if (config->GetWrt_Limiters()) { /*--- Mean Flow Limiters ---*/ @@ -12949,27 +12949,27 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo } } } - + /*--- Residuals ---*/ if (config->GetWrt_Residuals()) { /*--- Mean Flow Residuals ---*/ for (jVar = 0; jVar < nVar_First; jVar++) { - Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar); + Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes(iPoint, jVar); iVar++; } /*--- RANS Residuals ---*/ if (SecondIndex != NONE) { for (jVar = 0; jVar < nVar_Second; jVar++) { - Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes.GetBlock(iPoint, jVar); + Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes(iPoint, jVar); iVar++; } } } - - - + + + /*--- Load buffers with the three grid velocity components. ---*/ - + if (dynamic_grid) { Grid_Vel = geometry->node[iPoint]->GetGridVel(); Local_Data[jPoint][iVar] = Grid_Vel[0]; iVar++; @@ -12979,22 +12979,22 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo iVar++; } } - + /*--- Load data for the pressure, temperature, Cp, and Mach variables. ---*/ - + Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetPressure(iPoint); iVar++; Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetTemperature(iPoint); iVar++; Local_Data[jPoint][iVar] = sqrt(solver[FLOW_SOL]->GetNodes()->GetVelocity2(iPoint))/solver[FLOW_SOL]->GetNodes()->GetSoundSpeed(iPoint); iVar++; Local_Data[jPoint][iVar] = (solver[FLOW_SOL]->GetNodes()->GetPressure(iPoint) - RefPressure)*factor*RefArea; iVar++; - + if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) { - + /*--- Load data for the laminar viscosity. ---*/ - + Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); iVar++; - + /*--- Load data for the skin friction, heat flux, buffet, and y-plus. ---*/ - + Local_Data[jPoint][iVar] = Aux_Frict_x[iPoint]; iVar++; Local_Data[jPoint][iVar] = Aux_Frict_y[iPoint]; iVar++; if (geometry->GetnDim() == 3) { @@ -13002,74 +13002,74 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo iVar++; } if (config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR) { - Local_Data[jPoint][iVar] = Aux_Buffet[iPoint]; + Local_Data[jPoint][iVar] = Aux_Buffet[iPoint]; iVar++; } Local_Data[jPoint][iVar] = Aux_Heat[iPoint]; iVar++; - + } - + /*--- Load data for the Eddy viscosity for RANS. ---*/ - + if (Kind_Solver == RANS) { Local_Data[jPoint][iVar] = Aux_yPlus[iPoint]; iVar++; Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetEddyViscosity(iPoint); iVar++; } - + /*--- Load data for the distance to the nearest sharp edge. ---*/ - + if (config->GetWrt_SharpEdges()) { Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetSharpEdge_Distance(); iVar++; } - + /*--- Load data for the intermittency of the BC trans. model. ---*/ - + if (transition) { Local_Data[jPoint][iVar] = solver[TURB_SOL]->GetNodes()->GetGammaBC(iPoint); iVar++; } - + if (config->GetKind_HybridRANSLES()!=NO_HYBRIDRANSLES){ Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetDES_LengthScale(iPoint); iVar++; Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetWall_Distance(); iVar++; } - + if (config->GetKind_RoeLowDiss() != NO_ROELOWDISS){ Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetRoe_Dissipation(iPoint); iVar++; } - + if (solver[FLOW_SOL]->VerificationSolution) { if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) { - + /*--- Get the physical time if necessary. ---*/ su2double time = 0.0; if (config->GetTime_Marching()) time = config->GetPhysicalTime(); - + /* Set the pointers to the coordinates and solution of this DOF. */ const su2double *coor = geometry->node[iPoint]->GetCoord(); su2double *solDOF = solver[FLOW_SOL]->GetNodes()->GetSolution(iPoint); su2double mmsSol[5] = {0.0,0.0,0.0,0.0,0.0}; su2double error[5] = {0.0,0.0,0.0,0.0,0.0}; - + /* Get the verification solution. */ solver[FLOW_SOL]->VerificationSolution->GetSolution(coor, time, mmsSol); for (jVar = 0; jVar < nVar_First; jVar++) { Local_Data[jPoint][iVar] = mmsSol[jVar]; iVar++; } - + /* Get local error from the verification solution class. */ solver[FLOW_SOL]->VerificationSolution->GetLocalError(coor, time, solDOF, error); for (jVar = 0; jVar < nVar_First; jVar++) { Local_Data[jPoint][iVar] = error[jVar]; iVar++; } - + } } - + /*--- New variables can be loaded to the Local_Data structure here, assuming they were registered above correctly. ---*/ - + if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) { Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[0]; iVar++; Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[1]; iVar++; @@ -13077,17 +13077,17 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[2]; iVar++; } - + if (nDim == 3){ for (iDim = 0; iDim < nDim; iDim++) { for (unsigned short jDim = 0; jDim < nDim; jDim++) { Grad_Vel[iDim][jDim] = solver[FLOW_SOL]->GetNodes()->GetGradient_Primitive(iPoint, iDim+1, jDim); } } - + /*--- Q Criterion Eq 1.2 of---*/ /*--- HALLER, G. (2005). An objective definition of a vortex. Journal of Fluid Mechanics, 525, 1-26. doi:10.1017/S0022112004002526 ---*/ - + su2double s11 = Grad_Vel[0][0]; su2double s12 = 0.5 * (Grad_Vel[0][1] + Grad_Vel[1][0]); su2double s13 = 0.5 * (Grad_Vel[0][2] + Grad_Vel[2][0]); @@ -13097,15 +13097,15 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo su2double omega12 = 0.5 * (Grad_Vel[0][1] - Grad_Vel[1][0]); su2double omega13 = 0.5 * (Grad_Vel[0][2] - Grad_Vel[2][0]); su2double omega23 = 0.5 * (Grad_Vel[1][2] - Grad_Vel[2][1]); - + Q = 2. * pow( omega12, 2.) + 2. * pow( omega13, 2.) + 2. * pow( omega23, 2.) - \ pow( s11, 2.) - pow( s22, 2.) - pow( s33, 2.0) - 2. * pow( s12, 2.) - 2. * pow( s13, 2.) - 2. * pow( s23, 2.0); Local_Data[jPoint][iVar] = Q; iVar++; } } - + /*--- For rotating frame problems, compute the relative velocity. ---*/ - + if (rotating_frame) { Grid_Vel = geometry->node[iPoint]->GetGridVel(); su2double *Solution = solver[FLOW_SOL]->GetNodes()->GetSolution(iPoint); @@ -13118,7 +13118,7 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo } /*--- Output the mesh quality metrics. ---*/ - + if (config->GetWrt_MeshQuality()) { Local_Data[jPoint][iVar] = geometry->Orthogonality[iPoint]; iVar++; Local_Data[jPoint][iVar] = geometry->Aspect_Ratio[iPoint]; iVar++; @@ -13126,17 +13126,17 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo } } - + /*--- Increment the point counter, as there may have been halos we skipped over during the data loading. ---*/ - + jPoint++; - + } - - + + /*--- Free memory for auxiliary vectors. ---*/ - + if ((Kind_Solver == NAVIER_STOKES) || (Kind_Solver == RANS)) { delete [] Aux_Frict_x; delete [] Aux_Frict_y; @@ -13145,9 +13145,9 @@ void COutputLegacy::LoadLocalData_Flow(CConfig *config, CGeometry *geometry, CSo delete [] Aux_yPlus; delete [] Aux_Buffet; } - + delete [] Local_Halo; - + } void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) { @@ -13268,17 +13268,17 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, /*--- Add the limiters ---*/ - + if (config->GetWrt_Limiters()) { nVar_Par += nVar_Consv_Par; - + Variable_Names.push_back("Limiter_Pressure"); Variable_Names.push_back("Limiter_Velocity_x"); Variable_Names.push_back("Limiter_Velocity_y"); if (geometry->GetnDim() == 3) Variable_Names.push_back("Limiter_Velocity_z"); if (energy || weakly_coupled_heat) Variable_Names.push_back("Limiter_Temperature"); - + if (SecondIndex != NONE) { if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) { Variable_Names.push_back("Limiter_TKE"); @@ -13289,19 +13289,19 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, } } } - + /*--- Add the residuals ---*/ - + if (config->GetWrt_Residuals()) { nVar_Par += nVar_Consv_Par; - + Variable_Names.push_back("Residual_Pressure"); Variable_Names.push_back("Residual_Velocity_x"); Variable_Names.push_back("Residual_Velocity_y"); if (geometry->GetnDim() == 3) Variable_Names.push_back("Residual_Velocity_z"); if (energy || weakly_coupled_heat) Variable_Names.push_back("Residual_Temperature"); - + if (SecondIndex != NONE) { if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) { Variable_Names.push_back("Residual_TKE"); @@ -13312,29 +13312,29 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, } } } - + /*--- Add the grid velocity. ---*/ - + if (dynamic_grid) { if (geometry->GetnDim() == 2) nVar_Par += 2; else if (geometry->GetnDim() == 3) nVar_Par += 3; - + Variable_Names.push_back("Grid_Velocity_x"); Variable_Names.push_back("Grid_Velocity_y"); if (geometry->GetnDim() == 3) Variable_Names.push_back("Grid_Velocity_z"); } - + /*--- Add Cp. ---*/ - + nVar_Par += 1; if ((config->GetTabular_FileFormat() == TAB_CSV)){ Variable_Names.push_back("Pressure_Coefficient"); } else { Variable_Names.push_back("Cp"); } - + /*--- Add Laminar Viscosity, Skin Friction, and Heat Flux to the restart file ---*/ - + if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) { if ((config->GetTabular_FileFormat() == TAB_CSV)){ nVar_Par += 1; Variable_Names.push_back("Laminar_Viscosity"); @@ -13362,9 +13362,9 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, } } } - + /*--- Add Y+ and Eddy Viscosity. ---*/ - + if (Kind_Solver == INC_RANS) { nVar_Par += 2; if ((config->GetTabular_FileFormat() == TAB_CSV)){ @@ -13375,16 +13375,16 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, Variable_Names.push_back("mt"); } } - + /*--- Add the distance to the nearest sharp edge if requested. ---*/ - + if (config->GetWrt_SharpEdges()) { nVar_Par += 1; Variable_Names.push_back("Sharp_Edge_Dist"); } - + /*--- Add the intermittency for the BC trans. model. ---*/ - + if (transition) { nVar_Par += 1; if ((config->GetTabular_FileFormat() == TAB_CSV)){ @@ -13393,22 +13393,22 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, Variable_Names.push_back("gBC"); } } - + if (variable_density) { nVar_Par += 1; Variable_Names.push_back("Density"); } - + if (wrt_cp) { nVar_Par += 1; Variable_Names.push_back("Specific_Heat"); } - + if (wrt_kt) { nVar_Par += 1; Variable_Names.push_back("Thermal_Conductivity"); } - + if (solver[FLOW_SOL]->VerificationSolution) { if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) { nVar_Par += 2*nVar_Consv_Par; @@ -13424,19 +13424,19 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, if (energy || weakly_coupled_heat) Variable_Names.push_back("Error_Temperature"); } } - + if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) { nVar_Par += 2; Variable_Names.push_back("Vorticity_x"); Variable_Names.push_back("Vorticity_y"); nVar_Par += 1; Variable_Names.push_back("Vorticity_z"); - + if (geometry->GetnDim() == 3) { nVar_Par +=1; Variable_Names.push_back("Q_Criterion"); } } - + if (config->GetWrt_MeshQuality()) { nVar_Par +=1; Variable_Names.push_back("Orthogonality"); @@ -13445,10 +13445,10 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, nVar_Par +=1; Variable_Names.push_back("Volume_Ratio"); } - + /*--- New variables get registered here before the end of the loop. ---*/ - - + + /*--- Auxiliary vectors for variables defined on surfaces only. ---*/ @@ -13574,7 +13574,7 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, } /*--- If limiters and/or residuals are requested. ---*/ - + /*--- Limiters ---*/ if (config->GetWrt_Limiters()) { /*--- Mean Flow Limiters ---*/ @@ -13590,27 +13590,27 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, } } } - + /*--- Residuals ---*/ if (config->GetWrt_Residuals()) { /*--- Mean Flow Residuals ---*/ for (jVar = 0; jVar < nVar_First; jVar++) { - Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar); + Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes(iPoint, jVar); iVar++; } /*--- RANS Residuals ---*/ if (SecondIndex != NONE) { for (jVar = 0; jVar < nVar_Second; jVar++) { - Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes.GetBlock(iPoint, jVar); + Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes(iPoint, jVar); iVar++; } } } - - + + /*--- Load buffers with the three grid velocity components. ---*/ - + if (dynamic_grid) { Grid_Vel = geometry->node[iPoint]->GetGridVel(); Local_Data[jPoint][iVar] = Grid_Vel[0]; iVar++; @@ -13620,112 +13620,112 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, iVar++; } } - + /*--- Load data for Cp and Mach variables. ---*/ - + Local_Data[jPoint][iVar] = (solver[FLOW_SOL]->GetNodes()->GetPressure(iPoint) - RefPressure)*factor*RefArea; iVar++; - + if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) { - + /*--- Load data for the laminar viscosity. ---*/ - + Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); iVar++; - + /*--- Load data for the skin friction, heat flux, and y-plus. ---*/ - + Local_Data[jPoint][iVar] = Aux_Frict_x[iPoint]; iVar++; Local_Data[jPoint][iVar] = Aux_Frict_y[iPoint]; iVar++; if (geometry->GetnDim() == 3) { Local_Data[jPoint][iVar] = Aux_Frict_z[iPoint]; iVar++; } - + if (energy || weakly_coupled_heat) { Local_Data[jPoint][iVar] = Aux_Heat[iPoint]; iVar++; } - + } - + /*--- Load data for the Eddy viscosity for RANS. ---*/ - + if (Kind_Solver == INC_RANS) { Local_Data[jPoint][iVar] = Aux_yPlus[iPoint]; iVar++; Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetEddyViscosity(iPoint); iVar++; } - + /*--- Load data for the distance to the nearest sharp edge. ---*/ - + if (config->GetWrt_SharpEdges()) { Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetSharpEdge_Distance(); iVar++; } - + /*--- Load data for the intermittency of the BC trans. model. ---*/ - + if (transition) { Local_Data[jPoint][iVar] = solver[TURB_SOL]->GetNodes()->GetGammaBC(iPoint); iVar++; } - + /*--- Load density if we are solving a variable density problem. ---*/ - + if (variable_density) { Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetDensity(iPoint); iVar++; } - + /*--- Load Cp and conductivity if they are temperature-dependent. ---*/ if (wrt_cp) { Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetSpecificHeatCp(iPoint); iVar++; } - + if (wrt_kt) { Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetThermalConductivity(iPoint); iVar++; } - + if (solver[FLOW_SOL]->VerificationSolution) { if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) { - + /*--- Get the physical time if necessary. ---*/ su2double time = 0.0; if (config->GetTime_Marching()) time = config->GetPhysicalTime(); - + /* Set the pointers to the coordinates and solution of this DOF. */ const su2double *coor = geometry->node[iPoint]->GetCoord(); su2double *solDOF = solver[FLOW_SOL]->GetNodes()->GetSolution(iPoint); su2double mmsSol[5] = {0.0,0.0,0.0,0.0,0.0}; su2double error[5] = {0.0,0.0,0.0,0.0,0.0}; - + /* Get the verification solution. */ solver[FLOW_SOL]->VerificationSolution->GetSolution(coor, time, mmsSol); for (jVar = 0; jVar < nVar_First; jVar++) { Local_Data[jPoint][iVar] = mmsSol[jVar]; iVar++; } - + /* Get local error from the verification solution class. */ solver[FLOW_SOL]->VerificationSolution->GetLocalError(coor, time, solDOF, error); for (jVar = 0; jVar < nVar_First; jVar++) { Local_Data[jPoint][iVar] = error[jVar]; iVar++; } - + } } - + if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) { - + Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[0]; iVar++; Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[1]; iVar++; Local_Data[jPoint][iVar] = solver[FLOW_SOL]->GetNodes()->GetVorticity(iPoint)[2]; iVar++; - + if (nDim == 3){ for (iDim = 0; iDim < nDim; iDim++) { for (unsigned short jDim = 0; jDim < nDim; jDim++) { Grad_Vel[iDim][jDim] = solver[FLOW_SOL]->GetNodes()->GetGradient_Primitive(iPoint, iDim+1, jDim); } } - + /*--- Q Criterion Eq 1.2 of---*/ /*--- HALLER, G. (2005). An objective definition of a vortex. Journal of Fluid Mechanics, 525, 1-26. doi:10.1017/S0022112004002526 ---*/ - + su2double s11 = Grad_Vel[0][0]; su2double s12 = 0.5 * (Grad_Vel[0][1] + Grad_Vel[1][0]); su2double s13 = 0.5 * (Grad_Vel[0][2] + Grad_Vel[2][0]); @@ -13735,37 +13735,37 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, su2double omega12 = 0.5 * (Grad_Vel[0][1] - Grad_Vel[1][0]); su2double omega13 = 0.5 * (Grad_Vel[0][2] - Grad_Vel[2][0]); su2double omega23 = 0.5 * (Grad_Vel[1][2] - Grad_Vel[2][1]); - + Q = 2. * pow( omega12, 2.) + 2. * pow( omega13, 2.) + 2. * pow( omega23, 2.) - \ pow( s11, 2.) - pow( s22, 2.) - pow( s33, 2.0) - 2. * pow( s12, 2.) - 2. * pow( s13, 2.) - 2. * pow( s23, 2.0); - + Local_Data[jPoint][iVar] = Q; iVar++; } } - + /*--- Output the mesh quality metrics. ---*/ - + if (config->GetWrt_MeshQuality()) { Local_Data[jPoint][iVar] = geometry->Orthogonality[iPoint]; iVar++; Local_Data[jPoint][iVar] = geometry->Aspect_Ratio[iPoint]; iVar++; Local_Data[jPoint][iVar] = geometry->Volume_Ratio[iPoint]; iVar++; } - + /*--- New variables can be loaded to the Local_Data structure here, assuming they were registered above correctly. ---*/ - + } - + /*--- Increment the point counter, as there may have been halos we skipped over during the data loading. ---*/ - + jPoint++; - + } - + /*--- Free memory for auxiliary vectors. ---*/ - + if ((Kind_Solver == INC_NAVIER_STOKES) || (Kind_Solver == INC_RANS)) { delete [] Aux_Frict_x; delete [] Aux_Frict_y; @@ -13775,48 +13775,48 @@ void COutputLegacy::LoadLocalData_IncFlow(CConfig *config, CGeometry *geometry, } delete [] Local_Halo; - + } void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) { - + unsigned short iDim; unsigned short Kind_Solver = config->GetKind_Solver(); unsigned short nDim = geometry->GetnDim(); - + unsigned long iVar, jVar; unsigned long iPoint, jPoint, FirstIndex = NONE, SecondIndex = NONE, iMarker, iVertex; unsigned long nVar_First = 0, nVar_Second = 0, nVar_Consv_Par = 0; - + su2double *Aux_Sens = NULL; su2double *Grid_Vel = NULL; su2double *Normal, Area; - + bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); bool dynamic_grid = config->GetDynamic_Grid(); bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic; - + int *Local_Halo; - + stringstream varname; - + /*--- Use a switch statement to decide how many solver containers we have in this zone for output. ---*/ - + switch (config->GetKind_Solver()) { case ADJ_EULER : case ADJ_NAVIER_STOKES : FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; break; case ADJ_RANS : FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Cont()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; break; - case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: + case DISC_ADJ_EULER: case DISC_ADJ_NAVIER_STOKES: case DISC_ADJ_INC_EULER: case DISC_ADJ_INC_NAVIER_STOKES: FirstIndex = ADJFLOW_SOL; SecondIndex = NONE; break; case DISC_ADJ_RANS: case DISC_ADJ_INC_RANS: FirstIndex = ADJFLOW_SOL; if (config->GetFrozen_Visc_Disc()) SecondIndex = NONE; else SecondIndex = ADJTURB_SOL; break; } - + nVar_First = solver[FirstIndex]->GetnVar(); if (SecondIndex != NONE) nVar_Second = solver[SecondIndex]->GetnVar(); nVar_Consv_Par = nVar_First + nVar_Second; - + /*--------------------------------------------------------------------------*/ /*--- Step 1: Register the variables that will be output. To register a ---*/ /*--- variable, two things are required. First, increment the ---*/ @@ -13826,20 +13826,20 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, /*--- Second, add a name for the variable to the vector that ---*/ /*--- holds the string names. ---*/ /*--------------------------------------------------------------------------*/ - + /*--- All output files first need the grid coordinates. ---*/ - + nVar_Par = 1; Variable_Names.push_back("x"); nVar_Par += 1; Variable_Names.push_back("y"); if (geometry->GetnDim() == 3) { nVar_Par += 1; Variable_Names.push_back("z"); } - + /*--- At a mininum, the restarts and visualization files need the conservative variables, so these follow next. ---*/ - + nVar_Par += nVar_Consv_Par; - + /*--- For now, leave the names as "Conservative_", etc., in order to avoid confusion with the serial version, which still prints these names. Names can be set alternatively by using the commented code @@ -13887,9 +13887,9 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, /*--- If requested, register the limiter and residuals for all of the equations in the current flow problem. ---*/ - + /*--- Add the limiters ---*/ - + if (config->GetWrt_Limiters()) { nVar_Par += nVar_Consv_Par; if (incompressible) { @@ -13916,9 +13916,9 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, } } } - + /*--- Add the residuals ---*/ - + if (config->GetWrt_Residuals()) { nVar_Par += nVar_Consv_Par; if (incompressible) { @@ -13945,9 +13945,9 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, } } } - + /*--- Add the grid velocity. ---*/ - + if (dynamic_grid) { if (geometry->GetnDim() == 2) nVar_Par += 2; else if (geometry->GetnDim() == 3) nVar_Par += 3; @@ -13955,14 +13955,14 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, Variable_Names.push_back("Grid_Velocity_y"); if (geometry->GetnDim() == 3) Variable_Names.push_back("Grid_Velocity_z"); } - + /*--- All adjoint solvers write the surface sensitivity. ---*/ - + nVar_Par += 1; Variable_Names.push_back("Surface_Sensitivity"); - + /*--- For the continouus adjoint, we write either convective scheme's dissipation sensor (centered) or limiter (uwpind) for adj. density. ---*/ - + if (( Kind_Solver == ADJ_EULER ) || ( Kind_Solver == ADJ_NAVIER_STOKES ) || ( Kind_Solver == ADJ_RANS )) { @@ -13973,20 +13973,20 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, Variable_Names.push_back("Limiter_Adjoint_Density"); } } - + /*--- New variables get registered here before the end of the loop. ---*/ - - - + + + /*--- Auxiliary vectors for variables defined on surfaces only. ---*/ - + Aux_Sens = new su2double[geometry->GetnPoint()]; - + /*--- First, loop through the mesh in order to find and store the value of the viscous coefficients at any surface nodes. They will be placed in an auxiliary vector and then communicated like all other volumetric variables. ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { Aux_Sens[iPoint] = 0.0; } @@ -14001,30 +14001,30 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, Aux_Sens[iPoint] = solver[ADJFLOW_SOL]->GetCSensitivity(iMarker, iVertex)/Area; } } - + /*--- Allocate the local data structure now that we know how many variables are in the output. ---*/ - + Local_Data = new su2double*[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { Local_Data[iPoint] = new su2double[nVar_Par]; } - + Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + /*--- Search all send/recv boundaries on this partition for any periodic nodes that were part of the original domain. We want to recover these for visualization purposes. ---*/ - + if (!Wrt_Halo) { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { - + /*--- Checking for less than or equal to the rank, because there may be some periodic halo nodes that send info to the same rank. ---*/ - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && @@ -14034,7 +14034,7 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, } } } - + /*--------------------------------------------------------------------------*/ /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/ /*--- the restart and vizualization files. Note that we need to ---*/ @@ -14046,41 +14046,41 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, /*--- ordering of the data loading MUST match the order of the ---*/ /*--- variable registration above for the files to be correct. ---*/ /*--------------------------------------------------------------------------*/ - + jPoint = 0; - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Restart the column index with each new point. ---*/ - + iVar = 0; - + /*--- Load the grid node coordinate values. ---*/ - + for (iDim = 0; iDim < geometry->GetnDim(); iDim++) { Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim); if (config->GetSystemMeasurements() == US) Local_Data[jPoint][iVar] *= 12.0; iVar++; } - + /*--- Load the conservative variable states for the mean flow variables. If requested, load the limiters and residuals as well. ---*/ - + for (jVar = 0; jVar < nVar_First; jVar++) { Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar); iVar++; } - - + + /*--- If this is Adj. RANS, i.e., the second solver container is not empty, then load data for the conservative turbulence variables and the limiters / residuals (if requested). ----*/ - + if (SecondIndex != NONE) { for (jVar = 0; jVar < nVar_Second; jVar++) { Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetSolution(iPoint, jVar); @@ -14103,7 +14103,7 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, iVar++; } } - + if (config->GetWrt_Limiters()) { for (jVar = 0; jVar < nVar_First; jVar++) { Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetLimiter(iPoint, jVar); @@ -14116,11 +14116,11 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, } } } - + if (config->GetWrt_Residuals()) { for (jVar = 0; jVar < nVar_First; jVar++) { if (!config->GetDiscrete_Adjoint()) { - Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar); + Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes(iPoint, jVar); } else { Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar) - solver[FirstIndex]->GetNodes()->GetSolution_Old(iPoint, jVar); @@ -14130,7 +14130,7 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, if (SecondIndex != NONE) { for (jVar = 0; jVar < nVar_Second; jVar++) { if (!config->GetDiscrete_Adjoint()) { - Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes.GetBlock(iPoint, jVar); + Local_Data[jPoint][iVar] = solver[SecondIndex]->LinSysRes(iPoint, jVar); } else { Local_Data[jPoint][iVar] = solver[SecondIndex]->GetNodes()->GetSolution(iPoint, jVar) - solver[SecondIndex]->GetNodes()->GetSolution_Old(iPoint, jVar); @@ -14139,9 +14139,9 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, } } } - + /*--- Load buffers with the three grid velocity components. ---*/ - + if (dynamic_grid) { Grid_Vel = geometry->node[iPoint]->GetGridVel(); Local_Data[jPoint][iVar] = Grid_Vel[0]; iVar++; @@ -14151,13 +14151,13 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, iVar++; } } - + /*--- Load data for the surface sensitivity. ---*/ - + Local_Data[iPoint][iVar] = Aux_Sens[iPoint]; iVar++; - + /*--- Load data for the convective scheme sensor. ---*/ - + if (( Kind_Solver == ADJ_EULER ) || ( Kind_Solver == ADJ_NAVIER_STOKES ) || ( Kind_Solver == ADJ_RANS )) { @@ -14167,53 +14167,53 @@ void COutputLegacy::LoadLocalData_AdjFlow(CConfig *config, CGeometry *geometry, Local_Data[jPoint][iVar] = solver[ADJFLOW_SOL]->GetNodes()->GetLimiter(iPoint, 0); iVar++; } } - + /*--- New variables can be loaded to the Local_Data structure here, assuming they were registered above correctly. ---*/ - + } - + /*--- Increment the point counter, as there may have been halos we skipped over during the data loading. ---*/ - + jPoint++; } - - + + /*--- Free memory for auxiliary vectors. ---*/ - + delete [] Aux_Sens; delete [] Local_Halo; - + } void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) { - + unsigned short iDim; - + unsigned long iVar, jVar; unsigned long iPoint, jPoint, FirstIndex = NONE, iMarker, iVertex; unsigned long nVar_First = 0, nVar_Consv_Par = 0; - + su2double *Node_Vel = NULL, *Node_Accel = NULL; const su2double *Stress = NULL; bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic; int *Local_Halo = NULL; - + stringstream varname; - + /*--- Use a switch statement to decide how many solver containers we have in this zone for output. ---*/ - + switch (config->GetKind_Solver()) { case FEM_ELASTICITY: FirstIndex = FEA_SOL; break; case DISC_ADJ_FEM: FirstIndex = ADJFEA_SOL; break; } - + nVar_First = solver[FirstIndex]->GetnVar(); nVar_Consv_Par = nVar_First; - + /*--------------------------------------------------------------------------*/ /*--- Step 1: Register the variables that will be output. To register a ---*/ /*--- variable, two things are required. First, increment the ---*/ @@ -14223,25 +14223,25 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr /*--- Second, add a name for the variable to the vector that ---*/ /*--- holds the string names. ---*/ /*--------------------------------------------------------------------------*/ - + /*--- All output files first need the grid coordinates. ---*/ - + nVar_Par = 1; Variable_Names.push_back("x"); nVar_Par += 1; Variable_Names.push_back("y"); if (geometry->GetnDim() == 3) { nVar_Par += 1; Variable_Names.push_back("z"); } - + /*--- At a mininum, the restarts and visualization files need the conservative variables, so these follow next. ---*/ - + nVar_Par += nVar_Consv_Par; - + /*--- For now, leave the names as "Conservative_", etc., in order to avoid confusion with the serial version, which still prints these names. Names can be set alternatively by using the commented code below. ---*/ - + Variable_Names.push_back("Displacement_x"); Variable_Names.push_back("Displacement_y"); if (geometry->GetnDim() == 3) @@ -14249,10 +14249,10 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr /*--- If requested, register the limiter and residuals for all of the equations in the current flow problem. ---*/ - - + + /*--- Add the residuals ---*/ - + if (config->GetWrt_Residuals()) { nVar_Par += nVar_Consv_Par; Variable_Names.push_back("Residual_Displacement_x"); @@ -14260,10 +14260,10 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr if (geometry->GetnDim() == 3) Variable_Names.push_back("Residual_Displacement_z"); } - + /*--- If the analysis is dynamic... ---*/ if (config->GetTime_Domain()) { - + /*--- Velocities ---*/ nVar_Par += 2; Variable_Names.push_back("Velocity_x"); @@ -14272,7 +14272,7 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr nVar_Par += 1; Variable_Names.push_back("Velocity_z"); } - + /*--- Accelerations ---*/ nVar_Par += 2; Variable_Names.push_back("Acceleration_x"); @@ -14282,11 +14282,11 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr Variable_Names.push_back("Acceleration_z"); } } - + if (!(config->GetDiscrete_Adjoint())) { - + /*--- Add the stresses. ---*/ - + nVar_Par += 3; Variable_Names.push_back("Sxx"); Variable_Names.push_back("Syy"); @@ -14297,41 +14297,41 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr Variable_Names.push_back("Sxz"); Variable_Names.push_back("Syz"); } - + /*--- Add the Von Mises Stress. ---*/ - + nVar_Par += 1; Variable_Names.push_back("Von_Mises_Stress"); - + } - + /*--- New variables get registered here before the end of the loop. ---*/ - - - + + + /*--- Allocate the local data structure now that we know how many variables are in the output. ---*/ - + Local_Data = new su2double*[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { Local_Data[iPoint] = new su2double[nVar_Par]; } - + Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + /*--- Search all send/recv boundaries on this partition for any periodic nodes that were part of the original domain. We want to recover these for visualization purposes. ---*/ - + if (!Wrt_Halo) { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { - + /*--- Checking for less than or equal to the rank, because there may be some periodic halo nodes that send info to the same rank. ---*/ - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && @@ -14341,7 +14341,7 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr } } } - + /*--------------------------------------------------------------------------*/ /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/ /*--- the restart and vizualization files. Note that we need to ---*/ @@ -14353,51 +14353,51 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr /*--- ordering of the data loading MUST match the order of the ---*/ /*--- variable registration above for the files to be correct. ---*/ /*--------------------------------------------------------------------------*/ - + jPoint = 0; - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Restart the column index with each new point. ---*/ - + iVar = 0; - + /*--- Load the grid node coordinate values. ---*/ - + for (iDim = 0; iDim < geometry->GetnDim(); iDim++) { Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim); if (config->GetSystemMeasurements() == US) Local_Data[jPoint][iVar] *= 12.0; iVar++; } - + /*--- Load the conservative variable states for the mean flow variables. If requested, load the limiters and residuals as well. ---*/ - + for (jVar = 0; jVar < nVar_First; jVar++) { Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar); iVar++; } - + if (config->GetWrt_Residuals()) { for (jVar = 0; jVar < nVar_First; jVar++) { - Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar); + Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes(iPoint, jVar); iVar++; } } - - - + + + /*--- Load the velocities and accelerations (dynamic calculations). ---*/ - + if (config->GetTime_Domain()) { - + /*--- Velocities ---*/ - + Node_Vel = solver[FEA_SOL]->GetNodes()->GetSolution_Vel(iPoint); Local_Data[jPoint][iVar] = Node_Vel[0]; iVar++; Local_Data[jPoint][iVar] = Node_Vel[1]; iVar++; @@ -14405,9 +14405,9 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr Local_Data[jPoint][iVar] = Node_Vel[2]; iVar++; } - + /*--- Accelerations ---*/ - + Node_Accel = solver[FEA_SOL]->GetNodes()->GetSolution_Accel(iPoint); Local_Data[jPoint][iVar] = Node_Accel[0]; iVar++; Local_Data[jPoint][iVar] = Node_Accel[1]; iVar++; @@ -14416,20 +14416,20 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr iVar++; } } - + if (!(config->GetDiscrete_Adjoint())) { - + /*--- Add the stresses. ---*/ - + Stress = solver[FEA_SOL]->GetNodes()->GetStress_FEM(iPoint); - + /*--- Sigma xx ---*/ Local_Data[jPoint][iVar] = Stress[0]; iVar++; /*--- Sigma yy ---*/ Local_Data[jPoint][iVar] = Stress[1]; iVar++; /*--- Sigma xy ---*/ Local_Data[jPoint][iVar] = Stress[2]; iVar++; - + if (geometry->GetnDim() == 3) { /*--- Sigma zz ---*/ Local_Data[jPoint][iVar] = Stress[3]; iVar++; @@ -14438,56 +14438,56 @@ void COutputLegacy::LoadLocalData_Elasticity(CConfig *config, CGeometry *geometr /*--- Sigma yz ---*/ Local_Data[jPoint][iVar] = Stress[5]; iVar++; } - + /*--- Add the Von Mises Stress. ---*/ - + Local_Data[iPoint][iVar] = solver[FEA_SOL]->GetNodes()->GetVonMises_Stress(iPoint); iVar++; - - + + /*--- New variables can be loaded to the Local_Data structure here, assuming they were registered above correctly. ---*/ - + } - - + + /*--- Increment the point counter, as there may have been halos we skipped over during the data loading. ---*/ - + jPoint++; } } - + /*--- Free memory for auxiliary vectors. ---*/ - + delete [] Local_Halo; - + } void COutputLegacy::LoadLocalData_Base(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone) { - + unsigned short iDim; - + unsigned long iVar, jVar; unsigned long iPoint, jPoint, FirstIndex = NONE, iMarker, iVertex; unsigned long nVar_First = 0, nVar_Consv_Par = 0; - + bool Wrt_Halo = config->GetWrt_Halo(), isPeriodic; - + int *Local_Halo; - + stringstream varname; - + /*--- Use a switch statement to decide how many solver containers we have in this zone for output. ---*/ - + switch (config->GetKind_Solver()) { case HEAT_EQUATION: FirstIndex = HEAT_SOL; break; } - + nVar_First = solver[FirstIndex]->GetnVar(); nVar_Consv_Par = nVar_First; - + /*--------------------------------------------------------------------------*/ /*--- Step 1: Register the variables that will be output. To register a ---*/ /*--- variable, two things are required. First, increment the ---*/ @@ -14497,31 +14497,31 @@ void COutputLegacy::LoadLocalData_Base(CConfig *config, CGeometry *geometry, CSo /*--- Second, add a name for the variable to the vector that ---*/ /*--- holds the string names. ---*/ /*--------------------------------------------------------------------------*/ - + /*--- All output files first need the grid coordinates. ---*/ - + nVar_Par = 1; Variable_Names.push_back("x"); nVar_Par += 1; Variable_Names.push_back("y"); if (geometry->GetnDim() == 3) { nVar_Par += 1; Variable_Names.push_back("z"); } - + /*--- At a mininum, the restarts and visualization files need the conservative variables, so these follow next. ---*/ - + nVar_Par += nVar_Consv_Par; for (iVar = 0; iVar < nVar_Consv_Par; iVar++) { varname << "Conservative_" << iVar+1; Variable_Names.push_back(varname.str()); varname.str(""); } - + /*--- If requested, register the residuals for all of the equations in the current problem. ---*/ - - + + /*--- Add the residuals ---*/ - + if (config->GetWrt_Residuals()) { nVar_Par += nVar_Consv_Par; for (iVar = 0; iVar < nVar_Consv_Par; iVar++) { @@ -14530,34 +14530,34 @@ void COutputLegacy::LoadLocalData_Base(CConfig *config, CGeometry *geometry, CSo varname.str(""); } } - + /*--- New variables get registered here before the end of the loop. ---*/ - - - + + + /*--- Allocate the local data structure now that we know how many variables are in the output. ---*/ - + Local_Data = new su2double*[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { Local_Data[iPoint] = new su2double[nVar_Par]; } - + Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + /*--- Search all send/recv boundaries on this partition for any periodic nodes that were part of the original domain. We want to recover these for visualization purposes. ---*/ - + if (!Wrt_Halo) { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { - + /*--- Checking for less than or equal to the rank, because there may be some periodic halo nodes that send info to the same rank. ---*/ - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && @@ -14567,7 +14567,7 @@ void COutputLegacy::LoadLocalData_Base(CConfig *config, CGeometry *geometry, CSo } } } - + /*--------------------------------------------------------------------------*/ /*--- Step 2: Loop over all grid nodes and load up the desired data for ---*/ /*--- the restart and vizualization files. Note that we need to ---*/ @@ -14579,103 +14579,103 @@ void COutputLegacy::LoadLocalData_Base(CConfig *config, CGeometry *geometry, CSo /*--- ordering of the data loading MUST match the order of the ---*/ /*--- variable registration above for the files to be correct. ---*/ /*--------------------------------------------------------------------------*/ - + jPoint = 0; - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- Check for halos & write only if requested ---*/ - + if (!Local_Halo[iPoint] || Wrt_Halo) { - + /*--- Restart the column index with each new point. ---*/ - + iVar = 0; - + /*--- Load the grid node coordinate values. ---*/ - + for (iDim = 0; iDim < geometry->GetnDim(); iDim++) { Local_Data[jPoint][iVar] = geometry->node[iPoint]->GetCoord(iDim); if (config->GetSystemMeasurements() == US) Local_Data[jPoint][iVar] *= 12.0; iVar++; } - + /*--- Load the conservative variable states for the mean flow variables. If requested, load the limiters and residuals as well. ---*/ - + for (jVar = 0; jVar < nVar_First; jVar++) { Local_Data[jPoint][iVar] = solver[FirstIndex]->GetNodes()->GetSolution(iPoint, jVar); iVar++; } - + if (config->GetWrt_Residuals()) { for (jVar = 0; jVar < nVar_First; jVar++) { - Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes.GetBlock(iPoint, jVar); + Local_Data[jPoint][iVar] = solver[FirstIndex]->LinSysRes(iPoint, jVar); iVar++; } } - - + + /*--- New variables can be loaded to the Local_Data structure here, assuming they were registered above correctly. ---*/ - + /*--- Increment the point counter, as there may have been halos we skipped over during the data loading. ---*/ - + jPoint++; - + } } - + /*--- Free memory for auxiliary vectors. ---*/ - + delete [] Local_Halo; - + } void COutputLegacy::SortConnectivity(CConfig *config, CGeometry *geometry, unsigned short val_iZone) { /*--- Flags identifying the types of files to be written. ---*/ - + bool Wrt_Vol = config->GetWrt_Vol_Sol(); bool Wrt_Srf = config->GetWrt_Srf_Sol(); - + /*--- Sort connectivity for each type of element (excluding halos). Note In these routines, we sort the connectivity into a linear partitioning across all processors based on the global index of the grid nodes. ---*/ - + /*--- Sort volumetric grid connectivity. ---*/ - + if (Wrt_Vol) { - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE)) cout <<"Sorting volumetric grid connectivity." << endl; - + SortVolumetricConnectivity(config, geometry, TRIANGLE ); SortVolumetricConnectivity(config, geometry, QUADRILATERAL); SortVolumetricConnectivity(config, geometry, TETRAHEDRON ); SortVolumetricConnectivity(config, geometry, HEXAHEDRON ); SortVolumetricConnectivity(config, geometry, PRISM ); SortVolumetricConnectivity(config, geometry, PYRAMID ); - + } - + /*--- Sort surface grid connectivity. ---*/ - + if (Wrt_Srf) { - + if ((rank == MASTER_NODE) && (size != SINGLE_NODE)) cout <<"Sorting surface grid connectivity." << endl; - + SortSurfaceConnectivity(config, geometry, LINE ); SortSurfaceConnectivity(config, geometry, TRIANGLE ); SortSurfaceConnectivity(config, geometry, QUADRILATERAL); - + } - + /*--- Reduce the total number of cells we will be writing in the output files. ---*/ - + unsigned long nTotal_Elem = nParallel_Tria + nParallel_Quad + nParallel_Tetr + nParallel_Hexa + nParallel_Pris + nParallel_Pyra; unsigned long nTotal_Surf_Elem = nParallel_Line + nParallel_BoundTria + nParallel_BoundQuad; #ifndef HAVE_MPI @@ -14685,21 +14685,21 @@ void COutputLegacy::SortConnectivity(CConfig *config, CGeometry *geometry, unsig SU2_MPI::Allreduce(&nTotal_Elem, &nGlobal_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); SU2_MPI::Allreduce(&nTotal_Surf_Elem, &nSurf_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); #endif - + } void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) { - + unsigned long iProcessor; unsigned short NODES_PER_ELEMENT = 0; unsigned long iPoint, jPoint, kPoint, nLocalPoint, nTotalPoint; unsigned long nElem_Total = 0, Global_Index; - + unsigned long iVertex, iMarker; int SendRecv, RecvFrom; - + bool notPeriodic, notHalo, addedPeriodic, isPeriodic; - + int *Local_Halo = NULL; int *Conn_Elem = NULL; @@ -14708,12 +14708,12 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome SU2_MPI::Status status; int ind; #endif - + /*--- Store the local number of this element type and the number of nodes per this element type. In serial, this will be the total number of this element type in the entire mesh. In parallel, it is the number on only the current partition. ---*/ - + switch (Elem_Type) { case TRIANGLE: NODES_PER_ELEMENT = N_POINTS_TRIANGLE; @@ -14736,22 +14736,22 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome default: SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION); } - + /*--- Force the removal of all added periodic elements (use global index). First, we isolate and create a list of all added periodic points, excluding those that were part of the original domain (we want these to be in the output files). ---*/ - + vector Added_Periodic; Added_Periodic.clear(); - + if (config->GetKind_SU2() != SU2_DEF) { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - + if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) && (SendRecv < 0)) { @@ -14761,21 +14761,21 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome } } } - + /*--- Now we communicate this information to all processors, so that they can force the removal of these particular nodes by flagging them as halo points. In general, this should be a small percentage of the total mesh, so the communication/storage costs here shouldn't be prohibitive. ---*/ - + /*--- First communicate the number of points that each rank has found. ---*/ - + unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0; unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL; Buffer_Recv_nAddedPeriodic = new unsigned long[size]; - + nAddedPeriodic = Added_Periodic.size(); Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); @@ -14785,18 +14785,18 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome maxAddedPeriodic = nAddedPeriodic; Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0]; #endif - + /*--- Communicate the global index values of all added periodic nodes. ---*/ unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic]; unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic]; - + for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) { Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint]; } - + /*--- Gather the element connectivity information. All processors will now have a copy of the global index values for all added periodic points. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, @@ -14805,73 +14805,73 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++) Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint]; #endif - + /*--- Search all send/recv boundaries on this partition for halo cells. In particular, consider only the recv conditions (these are the true halo nodes). Check the ranks of the processors that are communicating and choose to keep only the halo cells from the higher rank processor. Here, we are also choosing to keep periodic nodes that were part of the original domain. We will check the communicated list of added periodic points. ---*/ - + Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); RecvFrom = abs(SendRecv)-1; - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); Global_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- We need to keep one copy of overlapping halo cells. ---*/ - + notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) && (SendRecv < 0) && (rank > RecvFrom)); - + /*--- We want to keep the periodic nodes that were part of the original domain. For SU2_DEF we want to keep all periodic nodes. ---*/ - + if (config->GetKind_SU2() == SU2_DEF) { isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0)); }else { isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1)); } - + notPeriodic = (isPeriodic && (SendRecv < 0)); - + /*--- Lastly, check that this isn't an added periodic point that we will forcibly remove. Use the communicated list of these points. ---*/ - + addedPeriodic = false; kPoint = 0; for (iProcessor = 0; iProcessor < (unsigned long)size; iProcessor++) { for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) { if (Global_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint]) addedPeriodic = true; } - + /*--- Adjust jNode to index of next proc's data in the buffers. ---*/ - + kPoint = (iProcessor+1)*maxAddedPeriodic; - + } - + /*--- If we found either of these types of nodes, flag them to be kept. ---*/ - + if ((notHalo || notPeriodic) && !addedPeriodic) { Local_Halo[iPoint] = false; } - + } } } - + /*--- Now that we've done the gymnastics to find any periodic points, compute the total number of local and global points for the output. ---*/ - + nLocalPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (Local_Halo[iPoint] == false) @@ -14883,31 +14883,31 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome #else nTotalPoint = nLocalPoint; #endif - + /*--- Compute the number of points that will be on each processor. This is a linear partitioning with the addition of a simple load balancing for any remainder points. ---*/ - + unsigned long *npoint_procs = new unsigned long[size]; unsigned long *starting_node = new unsigned long[size]; unsigned long *ending_node = new unsigned long[size]; unsigned long *nPoint_Linear = new unsigned long[size+1]; - + unsigned long total_pt_accounted = 0; for (int ii = 0; ii < size; ii++) { npoint_procs[ii] = nTotalPoint/size; total_pt_accounted = total_pt_accounted + npoint_procs[ii]; } - + /*--- Get the number of remainder points after the even division. ---*/ - + unsigned long rem_points = nTotalPoint-total_pt_accounted; for (unsigned long ii = 0; ii < rem_points; ii++) { npoint_procs[ii]++; } - + /*--- Store the local number of nodes and the beginning/end index ---*/ - + starting_node[0] = 0; ending_node[0] = starting_node[0] + npoint_procs[0]; nPoint_Linear[0] = 0; @@ -14917,46 +14917,46 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1]; } nPoint_Linear[size] = nTotalPoint; - + /*--- We start with the connectivity distributed across all procs with no particular ordering assumed. We need to loop through our local partition and decide how many elements we must send to each other rank in order to have all elements sorted according to a linear partitioning of the grid nodes, i.e., rank 0 holds the first nPoint()/nProcessors nodes. First, initialize a counter and flag. ---*/ - + int *nElem_Send = new int[size+1]; nElem_Send[0] = 0; int *nElem_Recv = new int[size+1]; nElem_Recv[0] = 0; int *nElem_Flag = new int[size]; - + for (int ii=0; ii < size; ii++) { nElem_Send[ii] = 0; nElem_Recv[ii] = 0; nElem_Flag[ii]= -1; } nElem_Send[size] = 0; nElem_Recv[size] = 0; - + for (int ii = 0; ii < (int)geometry->GetnElem(); ii++ ) { if (geometry->elem[ii]->GetVTK_Type() == Elem_Type) { for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) { - + /*--- Get the index of the current point. ---*/ - + iPoint = geometry->elem[ii]->GetNode(jj); Global_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- Search for the lowest global index in this element. We send the element to the processor owning the range that includes the lowest global index value. ---*/ - + for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) { jPoint = geometry->elem[ii]->GetNode(kk); unsigned long newID = geometry->node[jPoint]->GetGlobalIndex(); if (newID < Global_Index) Global_Index = newID; } - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -14964,93 +14964,93 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--; - + /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - + if ((nElem_Flag[iProcessor] != ii)) { nElem_Flag[iProcessor] = ii; nElem_Send[iProcessor+1]++; } - + } } } - + /*--- Communicate the number of cells to be sent/recv'd amongst all processors. After this communication, each proc knows how many cells it will receive from each other processor. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT, &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD); #else nElem_Recv[1] = nElem_Send[1]; #endif - + /*--- Prepare to send connectivities. First check how many messages we will be sending and receiving. Here we also put the counters into cumulative storage format to make the communications simpler. ---*/ - + int nSends = 0, nRecvs = 0; for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1; - + for (int ii = 0; ii < size; ii++) { if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++; if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++; - + nElem_Send[ii+1] += nElem_Send[ii]; nElem_Recv[ii+1] += nElem_Recv[ii]; } - + /*--- Allocate memory to hold the connectivity that we are sending. ---*/ - + unsigned long *connSend = NULL; connSend = new unsigned long[NODES_PER_ELEMENT*nElem_Send[size]]; for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Send[size]; ii++) connSend[ii] = 0; - + /*--- Allocate arrays for storing halo flags. ---*/ - + unsigned short *haloSend = new unsigned short[nElem_Send[size]]; for (int ii = 0; ii < nElem_Send[size]; ii++) haloSend[ii] = false; - + /*--- Create an index variable to keep track of our index position as we load up the send buffer. ---*/ - + unsigned long *index = new unsigned long[size]; for (int ii=0; ii < size; ii++) index[ii] = NODES_PER_ELEMENT*nElem_Send[ii]; - + unsigned long *haloIndex = new unsigned long[size]; for (int ii=0; ii < size; ii++) haloIndex[ii] = nElem_Send[ii]; - + /*--- Loop through our elements and load the elems and their additional data that we will send to the other procs. ---*/ - + for (int ii = 0; ii < (int)geometry->GetnElem(); ii++) { if (geometry->elem[ii]->GetVTK_Type() == Elem_Type) { for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) { - + /*--- Get the index of the current point. ---*/ - + iPoint = geometry->elem[ii]->GetNode(jj); Global_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- Search for the lowest global index in this element. We send the element to the processor owning the range that includes the lowest global index value. ---*/ - + for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) { jPoint = geometry->elem[ii]->GetNode(kk); unsigned long newID = geometry->node[jPoint]->GetGlobalIndex(); if (newID < Global_Index) Global_Index = newID; } - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -15058,67 +15058,67 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--; - + /*--- Load connectivity into the buffer for sending ---*/ - + if (nElem_Flag[iProcessor] != ii) { - + nElem_Flag[iProcessor] = ii; unsigned long nn = index[iProcessor]; unsigned long mm = haloIndex[iProcessor]; - + /*--- Load the connectivity values. ---*/ - + for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) { iPoint = geometry->elem[ii]->GetNode(kk); connSend[nn] = geometry->node[iPoint]->GetGlobalIndex(); nn++; - + /*--- Check if this is a halo node. If so, flag this element as a halo cell. We will use this later to sort and remove any duplicates from the connectivity list. ---*/ - + if (Local_Halo[iPoint]) haloSend[mm] = true; - + } - + /*--- Increment the index by the message length ---*/ - + index[iProcessor] += NODES_PER_ELEMENT; haloIndex[iProcessor]++; - + } } } } - + /*--- Free memory after loading up the send buffer. ---*/ - + delete [] index; delete [] haloIndex; - + /*--- Allocate the memory that we need for receiving the conn values and then cue up the non-blocking receives. Note that we do not include our own rank in the communications. We will directly copy our own data later. ---*/ - + unsigned long *connRecv = NULL; connRecv = new unsigned long[NODES_PER_ELEMENT*nElem_Recv[size]]; for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Recv[size]; ii++) connRecv[ii] = 0; - + unsigned short *haloRecv = new unsigned short[nElem_Recv[size]]; for (int ii = 0; ii < nElem_Recv[size]; ii++) haloRecv[ii] = false; - + #ifdef HAVE_MPI /*--- We need double the number of messages to send both the conn. and the flags for the halo cells. ---*/ - + send_req = new SU2_MPI::Request[2*nSends]; recv_req = new SU2_MPI::Request[2*nRecvs]; - + /*--- Launch the non-blocking recv's for the connectivity. ---*/ - + unsigned long iMessage = 0; for (int ii=0; ii nElem_Recv[ii])) { @@ -15132,9 +15132,9 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome iMessage++; } } - + /*--- Launch the non-blocking sends of the connectivity. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Send[ii])) { @@ -15148,9 +15148,9 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome iMessage++; } } - + /*--- Repeat the process to communicate the halo flags. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Recv[ii])) { @@ -15164,9 +15164,9 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome iMessage++; } } - + /*--- Launch the non-blocking sends of the halo flags. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Send[ii])) { @@ -15181,41 +15181,41 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome } } #endif - + /*--- Copy my own rank's data into the recv buffer directly. ---*/ - + int mm = NODES_PER_ELEMENT*nElem_Recv[rank]; int ll = NODES_PER_ELEMENT*nElem_Send[rank]; int kk = NODES_PER_ELEMENT*nElem_Send[rank+1]; - + for (int nn=ll; nn 0) Conn_Elem = new int[NODES_PER_ELEMENT*nElem_Recv[size]]; int count = 0; nElem_Total = 0; for (int ii = 0; ii < nElem_Recv[size]; ii++) { @@ -15227,10 +15227,10 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome } } } - + /*--- Store the particular global element count in the class data, and set the class data pointer to the connectivity array. ---*/ - + switch (Elem_Type) { case TRIANGLE: nParallel_Tria = nElem_Total; @@ -15260,9 +15260,9 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION); break; } - + /*--- Free temporary memory from communications ---*/ - + delete [] connSend; delete [] connRecv; delete [] haloSend; @@ -15273,7 +15273,7 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome delete [] nElem_Flag; delete [] Buffer_Recv_nAddedPeriodic; delete [] Buffer_Send_AddedPeriodic; - delete [] Buffer_Recv_AddedPeriodic; + delete [] Buffer_Recv_AddedPeriodic; delete [] npoint_procs; delete [] starting_node; delete [] ending_node; @@ -15282,31 +15282,31 @@ void COutputLegacy::SortVolumetricConnectivity(CConfig *config, CGeometry *geome } void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) { - + unsigned long iProcessor; unsigned short NODES_PER_ELEMENT; unsigned long iPoint, jPoint, kPoint, nLocalPoint, nTotalPoint; unsigned long nElem_Total = 0, Global_Index; - + unsigned long iVertex, iMarker; int SendRecv, RecvFrom; - + bool notPeriodic, notHalo, addedPeriodic, isPeriodic; - + int *Local_Halo = NULL; int *Conn_Elem = NULL; - + #ifdef HAVE_MPI SU2_MPI::Request *send_req, *recv_req; SU2_MPI::Status status; int ind; #endif - + /*--- Store the local number of this element type and the number of nodes per this element type. In serial, this will be the total number of this element type in the entire mesh. In parallel, it is the number on only the current partition. ---*/ - + switch (Elem_Type) { case LINE: NODES_PER_ELEMENT = N_POINTS_LINE; @@ -15322,22 +15322,22 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry NODES_PER_ELEMENT = 0; break; } - + /*--- Force the removal of all added periodic elements (use global index). First, we isolate and create a list of all added periodic points, excluding those that were part of the original domain (we want these to be in the output files). ---*/ - + vector Added_Periodic; Added_Periodic.clear(); - + if (config->GetKind_SU2() != SU2_DEF) { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - + if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) && (SendRecv < 0)) { @@ -15347,21 +15347,21 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry } } } - + /*--- Now we communicate this information to all processors, so that they can force the removal of these particular nodes by flagging them as halo points. In general, this should be a small percentage of the total mesh, so the communication/storage costs here shouldn't be prohibitive. ---*/ - + /*--- First communicate the number of points that each rank has found. ---*/ - + unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0; unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL; Buffer_Recv_nAddedPeriodic = new unsigned long[size]; - + nAddedPeriodic = Added_Periodic.size(); Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); @@ -15371,18 +15371,18 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry maxAddedPeriodic = nAddedPeriodic; Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0]; #endif - + /*--- Communicate the global index values of all added periodic nodes. ---*/ unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic]; unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic]; - + for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) { Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint]; } - + /*--- Gather the element connectivity information. All processors will now have a copy of the global index values for all added periodic points. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, @@ -15391,109 +15391,109 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++) Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint]; #endif - + /*--- Search all send/recv boundaries on this partition for halo cells. In particular, consider only the recv conditions (these are the true halo nodes). Check the ranks of the processors that are communicating and choose to keep only the halo cells from the higher rank processor. Here, we are also choosing to keep periodic nodes that were part of the original domain. We will check the communicated list of added periodic points. ---*/ - + Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); RecvFrom = abs(SendRecv)-1; - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); Global_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- We need to keep one copy of overlapping halo cells. ---*/ - + notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) && (SendRecv < 0) && (rank > RecvFrom)); - + /*--- We want to keep the periodic nodes that were part of the original domain. For SU2_DEF we want to keep all periodic nodes. ---*/ - + if (config->GetKind_SU2() == SU2_DEF) { isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0)); }else { isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1)); } - + notPeriodic = (isPeriodic && (SendRecv < 0)); - + /*--- Lastly, check that this isn't an added periodic point that we will forcibly remove. Use the communicated list of these points. ---*/ - + addedPeriodic = false; kPoint = 0; for (iProcessor = 0; iProcessor < (unsigned long)size; iProcessor++) { for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) { if (Global_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint]) addedPeriodic = true; } - + /*--- Adjust jNode to index of next proc's data in the buffers. ---*/ - + kPoint = (iProcessor+1)*maxAddedPeriodic; - + } - + /*--- If we found either of these types of nodes, flag them to be kept. ---*/ - + if ((notHalo || notPeriodic) && !addedPeriodic) { Local_Halo[iPoint] = false; } - + } } } - + /*--- Now that we've done the gymnastics to find any periodic points, compute the total number of local and global points for the output. ---*/ - + nLocalPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (Local_Halo[iPoint] == false) nLocalPoint++; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); #else nTotalPoint = nLocalPoint; #endif - + /*--- Compute the number of points that will be on each processor. This is a linear partitioning with the addition of a simple load balancing for any remainder points. ---*/ - + unsigned long *npoint_procs = new unsigned long[size]; unsigned long *starting_node = new unsigned long[size]; unsigned long *ending_node = new unsigned long[size]; unsigned long *nPoint_Linear = new unsigned long[size+1]; - + unsigned long total_pt_accounted = 0; for (int ii = 0; ii < size; ii++) { npoint_procs[ii] = nTotalPoint/size; total_pt_accounted = total_pt_accounted + npoint_procs[ii]; } - + /*--- Get the number of remainder points after the even division. ---*/ - + unsigned long rem_points = nTotalPoint-total_pt_accounted; for (unsigned long ii = 0; ii < rem_points; ii++) { npoint_procs[ii]++; } - + /*--- Store the local number of nodes and the beginning/end index ---*/ - + starting_node[0] = 0; ending_node[0] = starting_node[0] + npoint_procs[0]; nPoint_Linear[0] = 0; @@ -15503,18 +15503,18 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1]; } nPoint_Linear[size] = nTotalPoint; - + /*--- We start with the connectivity distributed across all procs with no particular ordering assumed. We need to loop through our local partition and decide how many elements we must send to each other rank in order to have all elements sorted according to a linear partitioning of the grid nodes, i.e., rank 0 holds the first nPoint()/nProcessors nodes. First, initialize a counter and flag. ---*/ - + int *nElem_Send = new int[size+1]; nElem_Send[0] = 0; int *nElem_Recv = new int[size+1]; nElem_Recv[0] = 0; int *nElem_Flag = new int[size]; - + for (int ii=0; ii < size; ii++) { nElem_Send[ii] = 0; nElem_Recv[ii] = 0; @@ -15524,29 +15524,29 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_Plotting(iMarker) == YES) { - + for (int ii = 0; ii < (int)geometry->GetnElem_Bound(iMarker); ii++) { - + if (geometry->bound[iMarker][ii]->GetVTK_Type() == Elem_Type) { for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) { - + /*--- Get the index of the current point. ---*/ - + iPoint = geometry->bound[iMarker][ii]->GetNode(jj); Global_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- Search for the lowest global index in this element. We send the element to the processor owning the range that includes the lowest global index value. ---*/ - + for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) { jPoint = geometry->bound[iMarker][ii]->GetNode(kk); unsigned long newID = geometry->node[jPoint]->GetGlobalIndex(); if (newID < Global_Index) Global_Index = newID; } - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -15554,99 +15554,99 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--; - + /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - + if ((nElem_Flag[iProcessor] != ii)) { nElem_Flag[iProcessor] = ii; nElem_Send[iProcessor+1]++; } - + } } } } } - + /*--- Communicate the number of cells to be sent/recv'd amongst all processors. After this communication, each proc knows how many cells it will receive from each other processor. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT, &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD); #else nElem_Recv[1] = nElem_Send[1]; #endif - + /*--- Prepare to send connectivities. First check how many messages we will be sending and receiving. Here we also put the counters into cumulative storage format to make the communications simpler. ---*/ - + int nSends = 0, nRecvs = 0; for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1; - + for (int ii = 0; ii < size; ii++) { if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++; if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++; - + nElem_Send[ii+1] += nElem_Send[ii]; nElem_Recv[ii+1] += nElem_Recv[ii]; } - + /*--- Allocate memory to hold the connectivity that we are sending. ---*/ - + unsigned long *connSend = NULL; connSend = new unsigned long[NODES_PER_ELEMENT*nElem_Send[size]]; for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Send[size]; ii++) connSend[ii] = 0; - + /*--- Allocate arrays for storing halo flags. ---*/ - + unsigned short *haloSend = new unsigned short[nElem_Send[size]]; for (int ii = 0; ii < nElem_Send[size]; ii++) haloSend[ii] = false; - + /*--- Create an index variable to keep track of our index position as we load up the send buffer. ---*/ - + unsigned long *index = new unsigned long[size]; for (int ii=0; ii < size; ii++) index[ii] = NODES_PER_ELEMENT*nElem_Send[ii]; - + unsigned long *haloIndex = new unsigned long[size]; for (int ii=0; ii < size; ii++) haloIndex[ii] = nElem_Send[ii]; - + /*--- Loop through our elements and load the elems and their additional data that we will send to the other procs. ---*/ - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_Plotting(iMarker) == YES) { - + for (int ii = 0; ii < (int)geometry->GetnElem_Bound(iMarker); ii++) { - + if (geometry->bound[iMarker][ii]->GetVTK_Type() == Elem_Type) { for ( int jj = 0; jj < NODES_PER_ELEMENT; jj++ ) { - + /*--- Get the index of the current point. ---*/ - + iPoint = geometry->bound[iMarker][ii]->GetNode(jj); Global_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- Search for the lowest global index in this element. We send the element to the processor owning the range that includes the lowest global index value. ---*/ - + for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) { jPoint = geometry->bound[iMarker][ii]->GetNode(kk); unsigned long newID = geometry->node[jPoint]->GetGlobalIndex(); if (newID < Global_Index) Global_Index = newID; } - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -15654,69 +15654,69 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--; - + /*--- Load connectivity into the buffer for sending ---*/ - + if (nElem_Flag[iProcessor] != ii) { - + nElem_Flag[iProcessor] = ii; unsigned long nn = index[iProcessor]; unsigned long mm = haloIndex[iProcessor]; - + /*--- Load the connectivity values. ---*/ - + for (int kk = 0; kk < NODES_PER_ELEMENT; kk++) { iPoint = geometry->bound[iMarker][ii]->GetNode(kk); connSend[nn] = geometry->node[iPoint]->GetGlobalIndex(); nn++; - + /*--- Check if this is a halo node. If so, flag this element as a halo cell. We will use this later to sort and remove any duplicates from the connectivity list. ---*/ - + if (Local_Halo[iPoint]) haloSend[mm] = true; - + } - + /*--- Increment the index by the message length ---*/ - + index[iProcessor] += NODES_PER_ELEMENT; haloIndex[iProcessor]++; - + } } } } } } - + /*--- Free memory after loading up the send buffer. ---*/ - + delete [] index; delete [] haloIndex; - + /*--- Allocate the memory that we need for receiving the conn values and then cue up the non-blocking receives. Note that we do not include our own rank in the communications. We will directly copy our own data later. ---*/ - + unsigned long *connRecv = NULL; connRecv = new unsigned long[NODES_PER_ELEMENT*nElem_Recv[size]]; for (int ii = 0; ii < NODES_PER_ELEMENT*nElem_Recv[size]; ii++) connRecv[ii] = 0; - + unsigned short *haloRecv = new unsigned short[nElem_Recv[size]]; for (int ii = 0; ii < nElem_Recv[size]; ii++) haloRecv[ii] = false; - + #ifdef HAVE_MPI /*--- We need double the number of messages to send both the conn. and the flags for the halo cells. ---*/ - + send_req = new SU2_MPI::Request[2*nSends]; recv_req = new SU2_MPI::Request[2*nRecvs]; - + /*--- Launch the non-blocking recv's for the connectivity. ---*/ - + unsigned long iMessage = 0; for (int ii=0; ii nElem_Recv[ii])) { @@ -15730,9 +15730,9 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry iMessage++; } } - + /*--- Launch the non-blocking sends of the connectivity. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Send[ii])) { @@ -15746,9 +15746,9 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry iMessage++; } } - + /*--- Repeat the process to communicate the halo flags. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Recv[ii])) { @@ -15762,9 +15762,9 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry iMessage++; } } - + /*--- Launch the non-blocking sends of the halo flags. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Send[ii])) { @@ -15779,41 +15779,41 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry } } #endif - + /*--- Copy my own rank's data into the recv buffer directly. ---*/ - + int mm = NODES_PER_ELEMENT*nElem_Recv[rank]; int ll = NODES_PER_ELEMENT*nElem_Send[rank]; int kk = NODES_PER_ELEMENT*nElem_Send[rank+1]; - + for (int nn=ll; nn 0) Conn_Elem = new int[NODES_PER_ELEMENT*nElem_Recv[size]]; int count = 0; nElem_Total = 0; for (int ii = 0; ii < nElem_Recv[size]; ii++) { @@ -15828,7 +15828,7 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry /*--- Store the particular global element count in the class data, and set the class data pointer to the connectivity array. ---*/ - + switch (Elem_Type) { case LINE: nParallel_Line = nElem_Total; @@ -15846,9 +15846,9 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION); break; } - + /*--- Free temporary memory from communications ---*/ - + delete [] connSend; delete [] connRecv; delete [] haloSend; @@ -15864,40 +15864,40 @@ void COutputLegacy::SortSurfaceConnectivity(CConfig *config, CGeometry *geometry delete [] starting_node; delete [] ending_node; delete [] nPoint_Linear; - + } void COutputLegacy::SortOutputData(CConfig *config, CGeometry *geometry) { - + unsigned short iMarker; unsigned long iProcessor; unsigned long iPoint, Global_Index, nLocalPoint, nTotalPoint, iVertex; - + int VARS_PER_POINT = nVar_Par; int *Local_Halo = NULL; bool isPeriodic; - + #ifdef HAVE_MPI SU2_MPI::Request *send_req, *recv_req; SU2_MPI::Status status; int ind; #endif - + /*--- Search all send/recv boundaries on this partition for any periodic nodes that were part of the original domain. We want to recover these for visualization purposes. ---*/ - + Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { - + /*--- Checking for less than or equal to the rank, because there may be some periodic halo nodes that send info to the same rank. ---*/ - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && @@ -15906,46 +15906,46 @@ void COutputLegacy::SortOutputData(CConfig *config, CGeometry *geometry) { } } } - + /*--- Sum total number of nodes that belong to the domain ---*/ - + nLocalPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (Local_Halo[iPoint] == false) nLocalPoint++; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); #else nTotalPoint = nLocalPoint; #endif - + /*--- Now that we know the actual number of points we need to output, compute the number of points that will be on each processor. This is a linear partitioning with the addition of a simple load balancing for any remainder points. ---*/ - + unsigned long *npoint_procs = new unsigned long[size]; unsigned long *starting_node = new unsigned long[size]; unsigned long *ending_node = new unsigned long[size]; unsigned long *nPoint_Linear = new unsigned long[size+1]; - + unsigned long total_pt_accounted = 0; for (int ii = 0; ii < size; ii++) { npoint_procs[ii] = nTotalPoint/size; total_pt_accounted = total_pt_accounted + npoint_procs[ii]; } - + /*--- Get the number of remainder points after the even division. ---*/ - + unsigned long rem_points = nTotalPoint-total_pt_accounted; for (unsigned long ii = 0; ii < rem_points; ii++) { npoint_procs[ii]++; } - + /*--- Store the local number of nodes and the beginning/end index ---*/ - + starting_node[0] = 0; ending_node[0] = starting_node[0] + npoint_procs[0]; nPoint_Linear[0] = 0; @@ -15955,37 +15955,37 @@ void COutputLegacy::SortOutputData(CConfig *config, CGeometry *geometry) { nPoint_Linear[ii] = nPoint_Linear[ii-1] + npoint_procs[ii-1]; } nPoint_Linear[size] = nTotalPoint; - + /*--- We start with the grid nodes distributed across all procs with no particular ordering assumed. We need to loop through our local partition and decide how many nodes we must send to each other rank in order to have all nodes sorted according to a linear partitioning of the grid nodes, i.e., rank 0 holds the first ~ nGlobalPoint()/nProcessors nodes. First, initialize a counter and flag. ---*/ - + int *nPoint_Send = new int[size+1]; nPoint_Send[0] = 0; int *nPoint_Recv = new int[size+1]; nPoint_Recv[0] = 0; int *nPoint_Flag = new int[size]; - + for (int ii=0; ii < size; ii++) { nPoint_Send[ii] = 0; nPoint_Recv[ii] = 0; nPoint_Flag[ii]= -1; } nPoint_Send[size] = 0; nPoint_Recv[size] = 0; - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++ ) { - + /*--- We only write interior points and recovered periodic points. ---*/ - + if (!Local_Halo[iPoint]) { - + /*--- Get the global index of the current point. ---*/ - + Global_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -15993,83 +15993,83 @@ void COutputLegacy::SortOutputData(CConfig *config, CGeometry *geometry) { while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--; - + /*--- If we have not visited this node yet, increment our number of elements that must be sent to a particular proc. ---*/ - + if (nPoint_Flag[iProcessor] != (int)iPoint) { nPoint_Flag[iProcessor] = (int)iPoint; nPoint_Send[iProcessor+1]++; } - + } } - + /*--- Communicate the number of nodes to be sent/recv'd amongst all processors. After this communication, each proc knows how many cells it will receive from each other processor. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Alltoall(&(nPoint_Send[1]), 1, MPI_INT, &(nPoint_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD); #else nPoint_Recv[1] = nPoint_Send[1]; #endif - + /*--- Prepare to send coordinates. First check how many messages we will be sending and receiving. Here we also put the counters into cumulative storage format to make the communications simpler. ---*/ - + int nSends = 0, nRecvs = 0; for (int ii=0; ii < size; ii++) nPoint_Flag[ii] = -1; - + for (int ii = 0; ii < size; ii++) { if ((ii != rank) && (nPoint_Send[ii+1] > 0)) nSends++; if ((ii != rank) && (nPoint_Recv[ii+1] > 0)) nRecvs++; - + nPoint_Send[ii+1] += nPoint_Send[ii]; nPoint_Recv[ii+1] += nPoint_Recv[ii]; } - + /*--- Allocate memory to hold the connectivity that we are sending. ---*/ - + su2double *connSend = NULL; connSend = new su2double[VARS_PER_POINT*nPoint_Send[size]]; for (int ii = 0; ii < VARS_PER_POINT*nPoint_Send[size]; ii++) connSend[ii] = 0; - + /*--- Allocate arrays for sending the global ID. ---*/ - + unsigned long *idSend = new unsigned long[nPoint_Send[size]]; for (int ii = 0; ii < nPoint_Send[size]; ii++) idSend[ii] = 0; - + /*--- Create an index variable to keep track of our index positions as we load up the send buffer. ---*/ - + unsigned long *index = new unsigned long[size]; for (int ii=0; ii < size; ii++) index[ii] = VARS_PER_POINT*nPoint_Send[ii]; - + unsigned long *idIndex = new unsigned long[size]; for (int ii=0; ii < size; ii++) idIndex[ii] = nPoint_Send[ii]; - + /*--- Loop through our elements and load the elems and their additional data that we will send to the other procs. ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - + /*--- We only write interior points and recovered periodic points. ---*/ - + if (!Local_Halo[iPoint]) { - + /*--- Get the index of the current point. ---*/ - + Global_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- Search for the processor that owns this point. ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -16077,61 +16077,61 @@ void COutputLegacy::SortOutputData(CConfig *config, CGeometry *geometry) { while(Global_Index >= nPoint_Linear[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear[iProcessor]) iProcessor--; - + /*--- Load node coordinates into the buffer for sending. ---*/ - + if (nPoint_Flag[iProcessor] != (int)iPoint) { - + nPoint_Flag[iProcessor] = (int)iPoint; unsigned long nn = index[iProcessor]; - + /*--- Load the data values. ---*/ - + for (unsigned short kk = 0; kk < VARS_PER_POINT; kk++) { connSend[nn] = Local_Data[iPoint][kk]; nn++; } - + /*--- Load the global ID (minus offset) for sorting the points once they all reach the correct processor. ---*/ - + nn = idIndex[iProcessor]; idSend[nn] = Global_Index - starting_node[iProcessor]; - + /*--- Increment the index by the message length ---*/ - + index[iProcessor] += VARS_PER_POINT; idIndex[iProcessor]++; - + } } } - + /*--- Free memory after loading up the send buffer. ---*/ - + delete [] index; delete [] idIndex; - + /*--- Allocate the memory that we need for receiving the conn values and then cue up the non-blocking receives. Note that we do not include our own rank in the communications. We will directly copy our own data later. ---*/ - + su2double *connRecv = NULL; connRecv = new su2double[VARS_PER_POINT*nPoint_Recv[size]]; for (int ii = 0; ii < VARS_PER_POINT*nPoint_Recv[size]; ii++) connRecv[ii] = 0; - + unsigned long *idRecv = new unsigned long[nPoint_Recv[size]]; for (int ii = 0; ii < nPoint_Recv[size]; ii++) idRecv[ii] = 0; - + #ifdef HAVE_MPI /*--- We need double the number of messages to send both the conn. and the global IDs. ---*/ - + send_req = new SU2_MPI::Request[2*nSends]; recv_req = new SU2_MPI::Request[2*nRecvs]; - + unsigned long iMessage = 0; for (int ii=0; ii nPoint_Recv[ii])) { @@ -16145,9 +16145,9 @@ void COutputLegacy::SortOutputData(CConfig *config, CGeometry *geometry) { iMessage++; } } - + /*--- Launch the non-blocking sends of the connectivity. ---*/ - + iMessage = 0; for (int ii=0; ii nPoint_Send[ii])) { @@ -16161,9 +16161,9 @@ void COutputLegacy::SortOutputData(CConfig *config, CGeometry *geometry) { iMessage++; } } - + /*--- Repeat the process to communicate the global IDs. ---*/ - + iMessage = 0; for (int ii=0; ii nPoint_Recv[ii])) { @@ -16177,9 +16177,9 @@ void COutputLegacy::SortOutputData(CConfig *config, CGeometry *geometry) { iMessage++; } } - + /*--- Launch the non-blocking sends of the global IDs. ---*/ - + iMessage = 0; for (int ii=0; ii nPoint_Send[ii])) { @@ -16194,40 +16194,40 @@ void COutputLegacy::SortOutputData(CConfig *config, CGeometry *geometry) { } } #endif - + /*--- Copy my own rank's data into the recv buffer directly. ---*/ - + int mm = VARS_PER_POINT*nPoint_Recv[rank]; int ll = VARS_PER_POINT*nPoint_Send[rank]; int kk = VARS_PER_POINT*nPoint_Send[rank+1]; - + for (int nn=ll; nnGetnPoint(); iPoint++) delete [] Local_Data[iPoint]; delete [] Local_Data; - + delete [] Local_Halo; delete [] npoint_procs; delete [] starting_node; delete [] ending_node; delete [] nPoint_Linear; - + } void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) { - + unsigned short iMarker; unsigned long iProcessor; unsigned long iPoint, jPoint, kPoint, iElem; unsigned long Global_Index, nLocalPoint, nTotalPoint, iVertex; - + int VARS_PER_POINT = nVar_Par; int *Local_Halo = NULL; int iNode, count; int SendRecv, RecvFrom; - + bool notPeriodic, notHalo, addedPeriodic, isPeriodic; #ifdef HAVE_MPI @@ -16291,7 +16291,7 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) SU2_MPI::Status status; int ind; #endif - + /*--------------------------------------------------------------------------*/ /*--- Step 1: We already have the surface connectivity spread out in ---*/ /*--- linear partitions across all procs and the output data ---*/ @@ -16304,21 +16304,21 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) /*--- different between the nodes and elements, so we will ---*/ /*--- have to move between the two systems in this routine. ---*/ /*--------------------------------------------------------------------------*/ - + /*--- Search all send/recv boundaries on this partition for any periodic nodes that were part of the original domain. We want to recover these for visualization purposes. This is the linear partitioning for nodes. ---*/ - + Local_Halo = new int[geometry->GetnPoint()]; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { - + /*--- Checking for less than or equal to the rank, because there may be some periodic halo nodes that send info to the same rank. ---*/ - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && @@ -16327,48 +16327,48 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) } } } - + /*--- Sum total number of nodes that belong to the domain ---*/ - + nLocalPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (Local_Halo[iPoint] == false) nLocalPoint++; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); #else nTotalPoint = nLocalPoint; #endif - + /*--- Now that we know the actual number of points we need to output, compute the number of points that will be on each processor. This is a linear partitioning with the addition of a simple load balancing for any remainder points. ---*/ - + unsigned long *npoint_procs = new unsigned long[size]; unsigned long *starting_node = new unsigned long[size]; unsigned long *ending_node = new unsigned long[size]; - + unsigned long *nPoint_Linear_Nodes = new unsigned long[size+1]; unsigned long *nPoint_Linear_Elems = new unsigned long[size+1]; - + unsigned long total_pt_accounted = 0; for (int ii = 0; ii < size; ii++) { npoint_procs[ii] = nTotalPoint/size; total_pt_accounted = total_pt_accounted + npoint_procs[ii]; } - + /*--- Get the number of remainder points after the even division. ---*/ - + unsigned long rem_points = nTotalPoint-total_pt_accounted; for (unsigned long ii = 0; ii < rem_points; ii++) { npoint_procs[ii]++; } - + /*--- Store the local number of nodes and the beginning/end index ---*/ - + starting_node[0] = 0; ending_node[0] = starting_node[0] + npoint_procs[0]; nPoint_Linear_Nodes[0] = 0; @@ -16378,34 +16378,34 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) nPoint_Linear_Nodes[ii] = nPoint_Linear_Nodes[ii-1] + npoint_procs[ii-1]; } nPoint_Linear_Nodes[size] = nTotalPoint; - + /*--- Prepare to check and communicate the nodes that each proc has locally from the surface connectivity. ---*/ - + int *nElem_Send = new int[size+1]; nElem_Send[0] = 0; int *nElem_Recv = new int[size+1]; nElem_Recv[0] = 0; int *nElem_Flag = new int[size]; - + for (int ii=0; ii < size; ii++) { nElem_Send[ii] = 0; nElem_Recv[ii] = 0; nElem_Flag[ii]= -1; } nElem_Send[size] = 0; nElem_Recv[size] = 0; - + /*--- Loop through our local line elements and check where each of the grid nodes resides based on global index. ---*/ - + for (int ii = 0; ii < (int)nParallel_Line; ii++) { for ( int jj = 0; jj < N_POINTS_LINE; jj++ ) { - + /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/ - + iNode = ii*N_POINTS_LINE+jj; Global_Index = Conn_BoundLine_Par[iNode]-1; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -16413,33 +16413,33 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--; - + /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - + if ((nElem_Flag[iProcessor] != iNode)) { nElem_Flag[iProcessor] = iNode; nElem_Send[iProcessor+1]++; } - + } } - + /*--- Reset out flags and then loop through our local triangle surface elements performing the same check for where each grid node resides. ---*/ - + for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1; - + for (int ii = 0; ii < (int)nParallel_BoundTria; ii++) { for ( int jj = 0; jj < N_POINTS_TRIANGLE; jj++ ) { - + /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/ - + iNode = ii*N_POINTS_TRIANGLE + jj; Global_Index = Conn_BoundTria_Par[iNode]-1; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -16447,33 +16447,33 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--; - + /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - + if ((nElem_Flag[iProcessor] != iNode)) { nElem_Flag[iProcessor] = iNode; nElem_Send[iProcessor+1]++; } - + } } - + /*--- Reset out flags and then loop through our local quad surface elements performing the same check for where each grid node resides. ---*/ - + for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1; - + for (int ii = 0; ii < (int)nParallel_BoundQuad; ii++) { for ( int jj = 0; jj < N_POINTS_QUADRILATERAL; jj++ ) { - + /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/ - + iNode = ii*N_POINTS_QUADRILATERAL+jj; Global_Index = Conn_BoundQuad_Par[iNode]-1; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -16481,69 +16481,69 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--; - + /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - + if ((nElem_Flag[iProcessor] != iNode)) { nElem_Flag[iProcessor] = iNode; nElem_Send[iProcessor+1]++; } - + } } - + /*--- Communicate the number of nodes to be sent/recv'd amongst all processors. After this communication, each proc knows how many nodes it will receive from each other processor. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT, &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD); #else nElem_Recv[1] = nElem_Send[1]; #endif - + /*--- Prepare to send. First check how many messages we will be sending and receiving. Here we also put the counters into cumulative storage format to make the communications simpler. ---*/ - + int nSends = 0, nRecvs = 0; for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1; - + for (int ii = 0; ii < size; ii++) { if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++; if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++; - + nElem_Send[ii+1] += nElem_Send[ii]; nElem_Recv[ii+1] += nElem_Recv[ii]; } - + /*--- Allocate arrays for sending the global ID. ---*/ - + unsigned long *idSend = new unsigned long[nElem_Send[size]]; for (int ii = 0; ii < nElem_Send[size]; ii++) idSend[ii] = 0; - + /*--- Create an index variable to keep track of our index positions as we load up the send buffer. ---*/ - + unsigned long *idIndex = new unsigned long[size]; for (int ii=0; ii < size; ii++) idIndex[ii] = nElem_Send[ii]; - + /*--- Now loop back through the local connectivities for the surface elements and load up the global IDs for sending to their home proc. ---*/ - + for (int ii = 0; ii < (int)nParallel_Line; ii++) { for ( int jj = 0; jj < N_POINTS_LINE; jj++ ) { - + /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/ - + iNode = ii*N_POINTS_LINE+jj; Global_Index = Conn_BoundLine_Par[iNode]-1; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -16551,39 +16551,39 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--; - + /*--- Load global ID into the buffer for sending ---*/ - + if (nElem_Flag[iProcessor] != iNode) { - + nElem_Flag[iProcessor] = iNode; unsigned long nn = idIndex[iProcessor]; - + /*--- Load the connectivity values. ---*/ - + idSend[nn] = Global_Index; nn++; - + /*--- Increment the index by the message length ---*/ - + idIndex[iProcessor]++; - + } - + } } - + for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1; - + for (int ii = 0; ii < (int)nParallel_BoundTria; ii++) { for ( int jj = 0; jj < N_POINTS_TRIANGLE; jj++ ) { - + /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/ - + iNode = ii*N_POINTS_TRIANGLE + jj; Global_Index = Conn_BoundTria_Par[iNode]-1; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -16591,39 +16591,39 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--; - + /*--- Load global ID into the buffer for sending ---*/ - + if (nElem_Flag[iProcessor] != iNode) { - + nElem_Flag[iProcessor] = iNode; unsigned long nn = idIndex[iProcessor]; - + /*--- Load the connectivity values. ---*/ - + idSend[nn] = Global_Index; nn++; - + /*--- Increment the index by the message length ---*/ - + idIndex[iProcessor]++; - + } - + } } - + for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1; - + for (int ii = 0; ii < (int)nParallel_BoundQuad; ii++) { for ( int jj = 0; jj < N_POINTS_QUADRILATERAL; jj++ ) { - + /*--- Get global index. Note the -1 since it was 1-based for viz. ---*/ - + iNode = ii*N_POINTS_QUADRILATERAL+jj; Global_Index = Conn_BoundQuad_Par[iNode]-1; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -16631,46 +16631,46 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--; - + /*--- Load global ID into the buffer for sending ---*/ - + if (nElem_Flag[iProcessor] != iNode) { - + nElem_Flag[iProcessor] = iNode; unsigned long nn = idIndex[iProcessor]; - + /*--- Load the connectivity values. ---*/ - + idSend[nn] = Global_Index; nn++; - + /*--- Increment the index by the message length ---*/ - + idIndex[iProcessor]++; - + } - + } } - + /*--- Allocate the memory that we need for receiving the global IDs values and then cue up the non-blocking receives. Note that we do not include our own rank in the communications. We will directly copy our own data later. ---*/ - + unsigned long *idRecv = NULL; idRecv = new unsigned long[nElem_Recv[size]]; for (int ii = 0; ii < nElem_Recv[size]; ii++) idRecv[ii] = 0; - + #ifdef HAVE_MPI /*--- We need double the number of messages to send both the conn. and the flags for the halo cells. ---*/ - + send_req = new SU2_MPI::Request[nSends]; recv_req = new SU2_MPI::Request[nRecvs]; - + /*--- Launch the non-blocking recv's for the global IDs. ---*/ - + unsigned long iMessage = 0; for (int ii=0; ii nElem_Recv[ii])) { @@ -16684,9 +16684,9 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) iMessage++; } } - + /*--- Launch the non-blocking sends of the global IDs. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Send[ii])) { @@ -16701,30 +16701,30 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) } } #endif - + /*--- Copy my own rank's data into the recv buffer directly. ---*/ - + int mm = nElem_Recv[rank]; int ll = nElem_Send[rank]; int kk = nElem_Send[rank+1]; - + for (int nn=ll; nn Added_Periodic; Added_Periodic.clear(); - + if (config->GetKind_SU2() != SU2_DEF) { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - + if ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 0) && (SendRecv < 0)) { @@ -16860,21 +16860,21 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) } } } - + /*--- Now we communicate this information to all processors, so that they can force the removal of these particular nodes by flagging them as halo points. In general, this should be a small percentage of the total mesh, so the communication/storage costs here shouldn't be prohibitive. ---*/ - + /*--- First communicate the number of points that each rank has found. ---*/ - + unsigned long nAddedPeriodic = 0, maxAddedPeriodic = 0; unsigned long Buffer_Send_nAddedPeriodic[1], *Buffer_Recv_nAddedPeriodic = NULL; Buffer_Recv_nAddedPeriodic = new unsigned long[size]; - + nAddedPeriodic = Added_Periodic.size(); Buffer_Send_nAddedPeriodic[0] = nAddedPeriodic; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nAddedPeriodic, &maxAddedPeriodic, 1, MPI_UNSIGNED_LONG, MPI_MAX, MPI_COMM_WORLD); @@ -16884,18 +16884,18 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) maxAddedPeriodic = nAddedPeriodic; Buffer_Recv_nAddedPeriodic[0] = Buffer_Send_nAddedPeriodic[0]; #endif - + /*--- Communicate the global index values of all added periodic nodes. ---*/ unsigned long *Buffer_Send_AddedPeriodic = new unsigned long[maxAddedPeriodic]; unsigned long *Buffer_Recv_AddedPeriodic = new unsigned long[size*maxAddedPeriodic]; - + for (iPoint = 0; iPoint < Added_Periodic.size(); iPoint++) { Buffer_Send_AddedPeriodic[iPoint] = Added_Periodic[iPoint]; } - + /*--- Gather the element connectivity information. All processors will now have a copy of the global index values for all added periodic points. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Allgather(Buffer_Send_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, Buffer_Recv_AddedPeriodic, maxAddedPeriodic, MPI_UNSIGNED_LONG, @@ -16904,103 +16904,103 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) for (iPoint = 0; iPoint < maxAddedPeriodic; iPoint++) Buffer_Recv_AddedPeriodic[iPoint] = Buffer_Send_AddedPeriodic[iPoint]; #endif - + /*--- Search all send/recv boundaries on this partition for halo cells. In particular, consider only the recv conditions (these are the true halo nodes). Check the ranks of the processors that are communicating and choose to keep only the halo cells from the higher rank processor. Here, we are also choosing to keep periodic nodes that were part of the original domain. We will check the communicated list of added periodic points. ---*/ - + for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) Local_Halo[iPoint] = !geometry->node[iPoint]->GetDomain(); - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if (config->GetMarker_All_KindBC(iMarker) == SEND_RECEIVE) { SendRecv = config->GetMarker_All_SendRecv(iMarker); RecvFrom = abs(SendRecv)-1; - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); Global_Index = geometry->node[iPoint]->GetGlobalIndex(); - + /*--- We need to keep one copy of overlapping halo cells. ---*/ - + notHalo = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() == 0) && (SendRecv < 0) && (rank > RecvFrom)); - + /*--- We want to keep the periodic nodes that were part of the original domain. For SU2_DEF we want to keep all periodic nodes. ---*/ - + if (config->GetKind_SU2() == SU2_DEF) { isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0)); }else { isPeriodic = ((geometry->vertex[iMarker][iVertex]->GetRotation_Type() > 0) && (geometry->vertex[iMarker][iVertex]->GetRotation_Type() % 2 == 1)); } - + notPeriodic = (isPeriodic && (SendRecv < 0)); - + /*--- Lastly, check that this isn't an added periodic point that we will forcibly remove. Use the communicated list of these points. ---*/ - + addedPeriodic = false; kPoint = 0; for (iProcessor = 0; iProcessor < (unsigned long)size; iProcessor++) { for (jPoint = 0; jPoint < Buffer_Recv_nAddedPeriodic[iProcessor]; jPoint++) { if (Global_Index == Buffer_Recv_AddedPeriodic[kPoint+jPoint]) addedPeriodic = true; } - + /*--- Adjust jNode to index of next proc's data in the buffers. ---*/ - + kPoint = (iProcessor+1)*maxAddedPeriodic; - + } - + /*--- If we found either of these types of nodes, flag them to be kept. ---*/ - + if ((notHalo || notPeriodic) && !addedPeriodic) { Local_Halo[iPoint] = false; } - + } } } - + /*--- Now that we've done the gymnastics to find any periodic points, compute the total number of local and global points for the output. ---*/ - + nLocalPoint = 0; for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) if (Local_Halo[iPoint] == false) nLocalPoint++; - + #ifdef HAVE_MPI SU2_MPI::Allreduce(&nLocalPoint, &nTotalPoint, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); #else nTotalPoint = nLocalPoint; #endif - + /*--- Compute the number of points that will be on each processor. This is a linear partitioning with the addition of a simple load balancing for any remainder points. ---*/ - + total_pt_accounted = 0; for (int ii = 0; ii < size; ii++) { npoint_procs[ii] = nTotalPoint/size; total_pt_accounted = total_pt_accounted + npoint_procs[ii]; } - + /*--- Get the number of remainder points after the even division. ---*/ - + rem_points = nTotalPoint-total_pt_accounted; for (unsigned long ii = 0; ii < rem_points; ii++) { npoint_procs[ii]++; } - + /*--- Store the local number of nodes and the beginning/end index ---*/ - + starting_node[0] = 0; ending_node[0] = starting_node[0] + npoint_procs[0]; nPoint_Linear_Elems[0] = 0; @@ -17010,25 +17010,25 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) nPoint_Linear_Elems[ii] = nPoint_Linear_Elems[ii-1] + npoint_procs[ii-1]; } nPoint_Linear_Elems[size] = nTotalPoint; - + /*--- Reset our flags and counters ---*/ - + for (int ii=0; ii < size; ii++) { nElem_Send[ii] = 0; nElem_Recv[ii] = 0; nElem_Flag[ii]= -1; } nElem_Send[size] = 0; nElem_Recv[size] = 0; - + /*--- Loop through my local surface nodes, find which proc the global value lives on, then communicate the global ID and remumbered value. ---*/ - + for (int ii = 0; ii < (int)nSurf_Poin_Par; ii++) { - + Global_Index = globalP[ii]; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -17036,75 +17036,75 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--; - + /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - + if ((nElem_Flag[iProcessor] != ii)) { nElem_Flag[iProcessor] = ii; nElem_Send[iProcessor+1]++; } - + } - + /*--- Communicate the number of cells to be sent/recv'd amongst all processors. After this communication, each proc knows how many cells it will receive from each other processor. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT, &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD); #else nElem_Recv[1] = nElem_Send[1]; #endif - + /*--- Prepare to send. First check how many messages we will be sending and receiving. Here we also put the counters into cumulative storage format to make the communications simpler. ---*/ - + nSends = 0; nRecvs = 0; for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1; - + for (int ii = 0; ii < size; ii++) { if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++; if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++; - + nElem_Send[ii+1] += nElem_Send[ii]; nElem_Recv[ii+1] += nElem_Recv[ii]; } - + /*--- Allocate memory to hold the globals that we are sending. ---*/ - + unsigned long *globalSend = NULL; globalSend = new unsigned long[nElem_Send[size]]; for (int ii = 0; ii < nElem_Send[size]; ii++) globalSend[ii] = 0; - + /*--- Allocate memory to hold the renumbering that we are sending. ---*/ - + unsigned long *renumbSend = NULL; renumbSend = new unsigned long[nElem_Send[size]]; for (int ii = 0; ii < nElem_Send[size]; ii++) renumbSend[ii] = 0; - + /*--- Create an index variable to keep track of our index position as we load up the send buffer. ---*/ - + unsigned long *index = new unsigned long[size]; for (int ii=0; ii < size; ii++) index[ii] = nElem_Send[ii]; - + /*--- Loop back through and load up the buffers for the global IDs and their new renumbering values. ---*/ - + for (int ii = 0; ii < (int)nSurf_Poin_Par; ii++) { - + Global_Index = globalP[ii]; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -17112,51 +17112,51 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--; - - + + if (nElem_Flag[iProcessor] != ii) { - + nElem_Flag[iProcessor] = ii; unsigned long nn = index[iProcessor]; - + globalSend[nn] = Global_Index; renumbSend[nn] = renumbP[ii]; - + /*--- Increment the index by the message length ---*/ - + index[iProcessor]++; - + } } - + /*--- Free memory after loading up the send buffer. ---*/ - + delete [] index; - + /*--- Allocate the memory that we need for receiving the values and then cue up the non-blocking receives. Note that we do not include our own rank in the communications. We will directly copy our own data later. ---*/ - + unsigned long *globalRecv = NULL; globalRecv = new unsigned long[nElem_Recv[size]]; for (int ii = 0; ii < nElem_Recv[size]; ii++) globalRecv[ii] = 0; - + unsigned long *renumbRecv = NULL; renumbRecv = new unsigned long[nElem_Recv[size]]; for (int ii = 0; ii < nElem_Recv[size]; ii++) renumbRecv[ii] = 0; - + #ifdef HAVE_MPI /*--- We need double the number of messages to send both the conn. and the flags for the halo cells. ---*/ - + send_req = new SU2_MPI::Request[2*nSends]; recv_req = new SU2_MPI::Request[2*nRecvs]; - + /*--- Launch the non-blocking recv's for the global ID. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Recv[ii])) { @@ -17170,9 +17170,9 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) iMessage++; } } - + /*--- Launch the non-blocking sends of the global ID. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Send[ii])) { @@ -17186,9 +17186,9 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) iMessage++; } } - + /*--- Launch the non-blocking recv's for the renumbered ID. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Recv[ii])) { @@ -17202,9 +17202,9 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) iMessage++; } } - + /*--- Launch the non-blocking sends of the renumbered ID. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Send[ii])) { @@ -17218,66 +17218,66 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) iMessage++; } } - + #endif - + /*--- Load our own procs data into the buffers directly. ---*/ - + mm = nElem_Recv[rank]; ll = nElem_Send[rank]; kk = nElem_Send[rank+1]; - + for (int nn=ll; nn renumber for nodes. Note the adding of 1 back in here for the eventual viz. purposes. ---*/ - + map Global2Renumber; for (int ii = 0; ii < nElem_Recv[size]; ii++) { Global2Renumber[globalRecv[ii]] = renumbRecv[ii] + 1; } - - + + /*--- The final step is one last pass over all elements to check for points outside of the linear partitions of the elements. Again, note that elems were distributed based on their smallest global ID, so some nodes of the elem may have global IDs lying outside of the linear partitioning. We need to recover the mapping for these outliers. We loop over all local surface elements to find these. ---*/ - + vector::iterator it; vector outliers; - + for (int ii = 0; ii < (int)nParallel_Line; ii++) { for ( int jj = 0; jj < N_POINTS_LINE; jj++ ) { - + iNode = ii*N_POINTS_LINE+jj; Global_Index = Conn_BoundLine_Par[iNode]-1; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -17285,26 +17285,26 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--; - + /*--- Store the global ID if it is outside our own linear partition. ---*/ - + if ((iProcessor != (unsigned long)rank)) { outliers.push_back(Global_Index); } - + } } - + for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1; - + for (int ii = 0; ii < (int)nParallel_BoundTria; ii++) { for ( int jj = 0; jj < N_POINTS_TRIANGLE; jj++ ) { - + iNode = ii*N_POINTS_TRIANGLE + jj; Global_Index = Conn_BoundTria_Par[iNode]-1; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -17312,26 +17312,26 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--; - + /*--- Store the global ID if it is outside our own linear partition. ---*/ - + if ((iProcessor != (unsigned long)rank)) { outliers.push_back(Global_Index); } - + } } - + for (int ii=0; ii < size; ii++) nElem_Flag[ii]= -1; - + for (int ii = 0; ii < (int)nParallel_BoundQuad; ii++) { for ( int jj = 0; jj < N_POINTS_QUADRILATERAL; jj++ ) { - + iNode = ii*N_POINTS_QUADRILATERAL+jj; Global_Index = Conn_BoundQuad_Par[iNode]-1; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -17339,40 +17339,40 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Elems[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Elems[iProcessor]) iProcessor--; - + /*--- Store the global ID if it is outside our own linear partition. ---*/ - + if ((iProcessor != (unsigned long)rank)) { outliers.push_back(Global_Index); } - + } } - + /*--- Create a unique list of global IDs that fall outside of our procs linear partition. ---*/ - + sort(outliers.begin(), outliers.end()); it = unique(outliers.begin(), outliers.end()); outliers.resize(it - outliers.begin()); - + /*--- Now loop over the outliers and communicate to those procs that hold the new numbering for our outlier points. We need to ask for the new numbering from these procs. ---*/ - + for (int ii=0; ii < size; ii++) { nElem_Send[ii] = 0; nElem_Recv[ii] = 0; nElem_Flag[ii]= -1; } nElem_Send[size] = 0; nElem_Recv[size] = 0; - + for (int ii = 0; ii < (int)outliers.size(); ii++) { - + Global_Index = outliers[ii]; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -17380,61 +17380,61 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--; - + /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - + if ((nElem_Flag[iProcessor] != ii)) { nElem_Flag[iProcessor] = ii; nElem_Send[iProcessor+1]++; } - + } - + /*--- Communicate the number of cells to be sent/recv'd amongst all processors. After this communication, each proc knows how many cells it will receive from each other processor. ---*/ - + #ifdef HAVE_MPI SU2_MPI::Alltoall(&(nElem_Send[1]), 1, MPI_INT, &(nElem_Recv[1]), 1, MPI_INT, MPI_COMM_WORLD); #else nElem_Recv[1] = nElem_Send[1]; #endif - + /*--- Prepare to send connectivities. First check how many messages we will be sending and receiving. Here we also put the counters into cumulative storage format to make the communications simpler. ---*/ - + nSends = 0; nRecvs = 0; for (int ii=0; ii < size; ii++) nElem_Flag[ii] = -1; - + for (int ii = 0; ii < size; ii++) { if ((ii != rank) && (nElem_Send[ii+1] > 0)) nSends++; if ((ii != rank) && (nElem_Recv[ii+1] > 0)) nRecvs++; - + nElem_Send[ii+1] += nElem_Send[ii]; nElem_Recv[ii+1] += nElem_Recv[ii]; } - + delete [] idSend; idSend = new unsigned long[nElem_Send[size]]; for (int ii = 0; ii < nElem_Send[size]; ii++) idSend[ii] = 0; - + /*--- Reset our index variable for reuse. ---*/ - + for (int ii=0; ii < size; ii++) idIndex[ii] = nElem_Send[ii]; - + /*--- Loop over the outliers again and load up the global IDs. ---*/ - + for (int ii = 0; ii < (int)outliers.size(); ii++) { - + Global_Index = outliers[ii]; - + /*--- Search for the processor that owns this point ---*/ - + iProcessor = Global_Index/npoint_procs[0]; if (iProcessor >= (unsigned long)size) iProcessor = (unsigned long)size-1; @@ -17442,45 +17442,45 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) while(Global_Index >= nPoint_Linear_Nodes[iProcessor+1]) iProcessor++; else while(Global_Index < nPoint_Linear_Nodes[iProcessor]) iProcessor--; - + /*--- If we have not visited this element yet, increment our number of elements that must be sent to a particular proc. ---*/ - + if ((nElem_Flag[iProcessor] != ii)) { - + nElem_Flag[iProcessor] = ii; unsigned long nn = idIndex[iProcessor]; - + /*--- Load the global ID values. ---*/ - + idSend[nn] = Global_Index; nn++; - + /*--- Increment the index by the message length ---*/ - + idIndex[iProcessor]++; - + } } - + /*--- Allocate the memory that we need for receiving the values and then cue up the non-blocking receives. Note that we do not include our own rank in the communications. We will directly copy our own data later. ---*/ - + delete [] idRecv; idRecv = new unsigned long[nElem_Recv[size]]; for (int ii = 0; ii < nElem_Recv[size]; ii++) idRecv[ii] = 0; - + #ifdef HAVE_MPI /*--- We need double the number of messages to send both the conn. and the flags for the halo cells. ---*/ - + send_req = new SU2_MPI::Request[nSends]; recv_req = new SU2_MPI::Request[nRecvs]; - + /*--- Launch the non-blocking recv's for the connectivity. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Recv[ii])) { @@ -17494,9 +17494,9 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) iMessage++; } } - + /*--- Launch the non-blocking sends of the connectivity. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Send[ii])) { @@ -17511,33 +17511,33 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) } } #endif - + /*--- Copy my own rank's data into the recv buffer directly. ---*/ - + mm = nElem_Recv[rank]; ll = nElem_Send[rank]; kk = nElem_Send[rank+1]; - + for (int nn=ll; nn nElem_Send[ii])) { @@ -17571,9 +17571,9 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) iMessage++; } } - + /*--- Launch the non-blocking recv's for the connectivity. ---*/ - + iMessage = 0; for (int ii=0; ii nElem_Recv[ii])) { @@ -17588,55 +17588,55 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) } } #endif - + /*--- Copy my own rank's data into the recv buffer directly. ---*/ - + mm = nElem_Send[rank]; ll = nElem_Recv[rank]; kk = nElem_Recv[rank+1]; - + for (int nn=ll; nn renumber transformation. Note that by construction, + the global -> renumber transformation. Note that by construction, nElem_Send[ii] == outliers.size(). We also add in the 1 for viz. here. ---*/ - + for (int ii = 0; ii < nElem_Send[size]; ii++) { Global2Renumber[outliers[ii]] = idSend[ii] + 1; } - + /*--- We can now overwrite the local connectivity for our surface elems using our completed map with the new global renumbering. Whew!! Note the -1 when accessing the conn from the map. ---*/ - + for (iElem = 0; iElem < nParallel_Line; iElem++) { iNode = (int)iElem*N_POINTS_LINE; Conn_BoundLine_Par[iNode+0] = (int)Global2Renumber[Conn_BoundLine_Par[iNode+0]-1]; Conn_BoundLine_Par[iNode+1] = (int)Global2Renumber[Conn_BoundLine_Par[iNode+1]-1]; } - + for (iElem = 0; iElem < nParallel_BoundTria; iElem++) { iNode = (int)iElem*N_POINTS_TRIANGLE; Conn_BoundTria_Par[iNode+0] = (int)Global2Renumber[Conn_BoundTria_Par[iNode+0]-1]; Conn_BoundTria_Par[iNode+1] = (int)Global2Renumber[Conn_BoundTria_Par[iNode+1]-1]; Conn_BoundTria_Par[iNode+2] = (int)Global2Renumber[Conn_BoundTria_Par[iNode+2]-1]; } - + for (iElem = 0; iElem < nParallel_BoundQuad; iElem++) { iNode = (int)iElem*N_POINTS_QUADRILATERAL; Conn_BoundQuad_Par[iNode+0] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+0]-1]; @@ -17644,14 +17644,14 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) Conn_BoundQuad_Par[iNode+2] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+2]-1]; Conn_BoundQuad_Par[iNode+3] = (int)Global2Renumber[Conn_BoundQuad_Par[iNode+3]-1]; } - + /*--- Free temporary memory ---*/ - + delete [] idIndex; delete [] surfPoint; delete [] globalP; delete [] renumbP; - + delete [] idSend; delete [] idRecv; delete [] globalSend; @@ -17672,13 +17672,13 @@ void COutputLegacy::SortOutputData_Surface(CConfig *config, CGeometry *geometry) delete [] nPoint_Linear_Nodes; delete [] nPoint_Send; delete [] nPoint_Recv; - + } void COutputLegacy::WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst) { - + /*--- Local variables ---*/ - + unsigned short nZone = geometry->GetnZone(), nInst = config->GetnTimeInstances(); unsigned short iVar; unsigned long iPoint, iExtIter = config->GetInnerIter(); @@ -17688,11 +17688,11 @@ void COutputLegacy::WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geom config->GetDiscrete_Adjoint()); ofstream restart_file; string filename; - + int iProcessor; /*--- Retrieve filename from config ---*/ - + // if ((config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint())) { // filename = config->GetRestart_AdjFileName(); // filename = config->GetObjFunc_Extension(filename); @@ -17703,11 +17703,11 @@ void COutputLegacy::WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geom // } else { // filename = config->GetRestart_FileName(); // } - + /*--- Append the zone number if multizone problems ---*/ if (nZone > 1) filename= config->GetMultizone_FileName(filename, val_iZone, ".dat"); - + /*--- Append the zone number if multiple instance problems ---*/ if (nInst > 1) filename= config->GetMultiInstance_FileName(filename, val_iInst, ".dat"); @@ -17720,9 +17720,9 @@ void COutputLegacy::WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geom } else if ((fem || disc_adj_fem) && (config->GetWrt_Dynamic())) { filename = config->GetUnsteady_FileName(filename, SU2_TYPE::Int(iExtIter), ".dat"); } - + /*--- Only the master node writes the header. ---*/ - + if (rank == MASTER_NODE) { restart_file.open(filename.c_str(), ios::out); restart_file.precision(15); @@ -17732,39 +17732,39 @@ void COutputLegacy::WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geom restart_file << "\t\"" << Variable_Names[Variable_Names.size()-1] << "\"" << endl; restart_file.close(); } - + #ifdef HAVE_MPI SU2_MPI::Barrier(MPI_COMM_WORLD); #endif - + /*--- All processors open the file. ---*/ - + restart_file.open(filename.c_str(), ios::out | ios::app); restart_file.precision(15); - + /*--- Write the restart file in parallel, processor by processor. ---*/ - + unsigned long myPoint = 0, offset = 0, Global_Index; for (iProcessor = 0; iProcessor < size; iProcessor++) { if (rank == iProcessor) { for (iPoint = 0; iPoint < nParallel_Poin; iPoint++) { - + /*--- Global Index of the current point. (note outer loop over procs) ---*/ - + Global_Index = iPoint + offset; - + /*--- Only write original domain points, i.e., exclude any periodic or halo nodes, even if they are output in the viz. files. ---*/ - + if (Global_Index < nPoint_Restart) { - + /*--- Write global index. (note outer loop over procs) ---*/ - + restart_file << Global_Index << "\t"; myPoint++; - + /*--- Loop over the variables and write the values to file ---*/ - + for (iVar = 0; iVar < nVar_Par; iVar++) { restart_file << scientific << Parallel_Data[iVar][iPoint] << "\t"; } @@ -17778,7 +17778,7 @@ void COutputLegacy::WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geom SU2_MPI::Allreduce(&myPoint, &offset, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); SU2_MPI::Barrier(MPI_COMM_WORLD); #endif - + } /*--- Write the metadata (master rank alone) ----*/ @@ -17809,7 +17809,7 @@ void COutputLegacy::WriteRestart_Parallel_ASCII(CConfig *config, CGeometry *geom /*--- All processors close the file. ---*/ restart_file.close(); - + } void COutputLegacy::WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geometry, CSolver **solver, unsigned short val_iZone, unsigned short val_iInst) { @@ -17862,7 +17862,7 @@ void COutputLegacy::WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geo /*--- Prepare the first ints containing the counts. The first is a magic number that we can use to check for binary files (it is the hex representation for "SU2"). The second two values are number of variables - and number of points (DoFs). The last two values are for metadata: + and number of points (DoFs). The last two values are for metadata: one int for ExtIter and 8 su2doubles. ---*/ int var_buf_size = 5; @@ -17908,13 +17908,13 @@ void COutputLegacy::WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geo } /*--- Set a timer for the binary file writing. ---*/ - + #ifndef HAVE_MPI StartTime = su2double(clock())/su2double(CLOCKS_PER_SEC); #else StartTime = MPI_Wtime(); #endif - + #ifndef HAVE_MPI FILE* fhw; @@ -17930,9 +17930,9 @@ void COutputLegacy::WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geo fwrite(var_buf, var_buf_size, sizeof(int), fhw); file_size += (su2double)var_buf_size*sizeof(int); - + /*--- Write the variable names to the file. Note that we are adopting a - fixed length of 33 for the string length to match with CGNS. This is + fixed length of 33 for the string length to match with CGNS. This is needed for when we read the strings later. ---*/ for (iVar = 0; iVar < nVar_Par; iVar++) { @@ -18004,7 +18004,7 @@ void COutputLegacy::WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geo } /*--- First, write the number of variables and points (i.e., cols and rows), - which we will need in order to read the file later. Also, write the + which we will need in order to read the file later. Also, write the variable string names here. Only the master rank writes the header. ---*/ if (rank == MASTER_NODE) { @@ -18075,32 +18075,32 @@ void COutputLegacy::WriteRestart_Parallel_Binary(CConfig *config, CGeometry *geo #endif /*--- Compute and store the write time. ---*/ - + #ifndef HAVE_MPI StopTime = su2double(clock())/su2double(CLOCKS_PER_SEC); #else StopTime = MPI_Wtime(); #endif UsedTime = StopTime-StartTime; - + /*--- Communicate the total file size for the restart ---*/ - + #ifdef HAVE_MPI su2double my_file_size = file_size; SU2_MPI::Allreduce(&my_file_size, &file_size, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); #endif - + /*--- Compute and store the bandwidth ---*/ - + Bandwidth = file_size/(1.0e6)/UsedTime; config->SetRestart_Bandwidth_Agg(config->GetRestart_Bandwidth_Agg()+Bandwidth); - + if ((rank == MASTER_NODE) && (wrt_perf)) { cout << "Wrote " << file_size/1.0e6 << " MB to disk in "; cout << UsedTime << " s. (" << Bandwidth << " MB/s)." << endl; } - + /*--- Free temporary data buffer for writing the binary file. ---*/ delete [] buf; @@ -18355,13 +18355,13 @@ void COutputLegacy::WriteCSV_Slice(CConfig *config, CGeometry *geometry, delete [] Buffer_Send_Data; delete [] Buffer_Send_GlobalIndex; - + } void COutputLegacy::DeallocateConnectivity_Parallel(CConfig *config, CGeometry *geometry, bool surf_sol) { - + /*--- Deallocate memory for connectivity data on each processor. ---*/ - + if (surf_sol) { if (Conn_BoundLine_Par != NULL) delete [] Conn_BoundLine_Par; if (Conn_BoundTria_Par != NULL) delete [] Conn_BoundTria_Par; @@ -18375,13 +18375,13 @@ void COutputLegacy::DeallocateConnectivity_Parallel(CConfig *config, CGeometry * if (Conn_Pris_Par != NULL) delete [] Conn_Pris_Par; if (Conn_Pyra_Par != NULL) delete [] Conn_Pyra_Par; } - + } void COutputLegacy::DeallocateData_Parallel(CConfig *config, CGeometry *geometry) { - + /*--- Deallocate memory for solution data ---*/ - + for (unsigned short iVar = 0; iVar < nVar_Par; iVar++) { if (Parallel_Data[iVar] != NULL) delete [] Parallel_Data[iVar]; } @@ -18400,18 +18400,18 @@ void COutputLegacy::DeallocateData_Parallel(CConfig *config, CGeometry *geometry } void COutputLegacy::DeallocateSurfaceData_Parallel(CConfig *config, CGeometry *geometry) { - + /*--- Deallocate memory for surface solution data ---*/ for (unsigned short iVar = 0; iVar < nVar_Par; iVar++) { if (Parallel_Surf_Data[iVar] != NULL) delete [] Parallel_Surf_Data[iVar]; } if (Parallel_Surf_Data != NULL) delete [] Parallel_Surf_Data; - + } void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geometry, CConfig *config, bool output) { - + unsigned short iDim, iMarker, iMarker_Analyze; unsigned long iVertex, iPoint; su2double Mach = 0.0, Pressure, Temperature = 0.0, TotalPressure = 0.0, TotalTemperature = 0.0, @@ -18431,7 +18431,7 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo bool axisymmetric = config->GetAxisymmetric(); unsigned short nMarker_Analyze = config->GetnMarker_Analyze(); - + su2double *Vector = new su2double[nDim]; su2double *Surface_MassFlow = new su2double[nMarker]; su2double *Surface_Mach = new su2double[nMarker]; @@ -18447,11 +18447,11 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo su2double *Surface_VelocityIdeal = new su2double[nMarker]; su2double *Surface_Area = new su2double[nMarker]; su2double *Surface_MassFlow_Abs = new su2double[nMarker]; - + /*--- Compute the numerical fan face Mach number, and the total area of the inflow ---*/ - + for (iMarker = 0; iMarker < nMarker; iMarker++) { - + Surface_MassFlow[iMarker] = 0.0; Surface_Mach[iMarker] = 0.0; Surface_Temperature[iMarker] = 0.0; @@ -18468,14 +18468,14 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo Surface_MassFlow_Abs[iMarker] = 0.0; if (config->GetMarker_All_Analyze(iMarker) == YES) { - + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - + if (geometry->node[iPoint]->GetDomain()) { - + geometry->vertex[iMarker][iVertex]->GetNormal(Vector); - + if (axisymmetric) { if (geometry->node[iPoint]->GetCoord(1) != 0.0) AxiFactor = 2.0*PI_NUMBER*geometry->node[iPoint]->GetCoord(1); @@ -18495,7 +18495,7 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo Vn += Velocity[iDim] * Vector[iDim] * AxiFactor; MassFlow += Vector[iDim] * AxiFactor * Density * Velocity[iDim]; } - + Area = sqrt (Area); if (AxiFactor == 0.0) Vn = 0.0; else Vn /= Area; Vn2 = Vn * Vn; @@ -18537,7 +18537,7 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo if (Kind_Average == AVERAGE_MASSFLUX) Weight = abs(MassFlow); else if (Kind_Average == AVERAGE_AREA) Weight = abs(Area); else Weight = 1.0; - + Surface_Mach[iMarker] += Mach*Weight; Surface_Temperature[iMarker] += Temperature*Weight; Surface_Density[iMarker] += Density*Weight; @@ -18556,13 +18556,13 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo } } - + } - + } - + /*--- Copy to the appropriate structure ---*/ - + su2double *Surface_MassFlow_Local = new su2double [nMarker_Analyze]; su2double *Surface_Mach_Local = new su2double [nMarker_Analyze]; su2double *Surface_Temperature_Local = new su2double [nMarker_Analyze]; @@ -18576,7 +18576,7 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo su2double *Surface_TotalPressure_Local = new su2double [nMarker_Analyze]; su2double *Surface_Area_Local = new su2double [nMarker_Analyze]; su2double *Surface_MassFlow_Abs_Local = new su2double [nMarker_Analyze]; - + su2double *Surface_MassFlow_Total = new su2double [nMarker_Analyze]; su2double *Surface_Mach_Total = new su2double [nMarker_Analyze]; su2double *Surface_Temperature_Total = new su2double [nMarker_Analyze]; @@ -18607,7 +18607,7 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo Surface_TotalPressure_Local[iMarker_Analyze] = 0.0; Surface_Area_Local[iMarker_Analyze] = 0.0; Surface_MassFlow_Abs_Local[iMarker_Analyze] = 0.0; - + Surface_MassFlow_Total[iMarker_Analyze] = 0.0; Surface_Mach_Total[iMarker_Analyze] = 0.0; Surface_Temperature_Total[iMarker_Analyze] = 0.0; @@ -18625,17 +18625,17 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo Surface_MomentumDistortion_Total[iMarker_Analyze] = 0.0; } - + /*--- Compute the numerical fan face Mach number, mach number, temperature and the total area ---*/ - + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - + if (config->GetMarker_All_Analyze(iMarker) == YES) { - + for (iMarker_Analyze= 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) { - + /*--- Add the Surface_MassFlow, and Surface_Area to the particular boundary ---*/ - + if (config->GetMarker_All_TagBound(iMarker) == config->GetMarker_Analyze_TagBound(iMarker_Analyze)) { Surface_MassFlow_Local[iMarker_Analyze] += Surface_MassFlow[iMarker]; Surface_Mach_Local[iMarker_Analyze] += Surface_Mach[iMarker]; @@ -18651,13 +18651,13 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo Surface_Area_Local[iMarker_Analyze] += Surface_Area[iMarker]; Surface_MassFlow_Abs_Local[iMarker_Analyze] += Surface_MassFlow_Abs[iMarker]; } - + } - + } - + } - + #ifdef HAVE_MPI if (config->GetComm_Level() == COMM_FULL) { SU2_MPI::Allreduce(Surface_MassFlow_Local, Surface_MassFlow_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); @@ -18675,7 +18675,7 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo SU2_MPI::Allreduce(Surface_MassFlow_Abs_Local, Surface_MassFlow_Abs_Total, nMarker_Analyze, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); } #else - + for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) { Surface_MassFlow_Total[iMarker_Analyze] = Surface_MassFlow_Local[iMarker_Analyze]; Surface_Mach_Total[iMarker_Analyze] = Surface_Mach_Local[iMarker_Analyze]; @@ -18691,14 +18691,14 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo Surface_Area_Total[iMarker_Analyze] = Surface_Area_Local[iMarker_Analyze]; Surface_MassFlow_Abs_Total[iMarker_Analyze] = Surface_MassFlow_Abs_Local[iMarker_Analyze]; } - + #endif - + /*--- Compute the value of Surface_Area_Total, and Surface_Pressure_Total, and set the value in the config structure for future use ---*/ - + for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) { - + if (Kind_Average == AVERAGE_MASSFLUX) Weight = Surface_MassFlow_Abs_Total[iMarker_Analyze]; else if (Kind_Average == AVERAGE_AREA) Weight = abs(Surface_Area_Total[iMarker_Analyze]); else Weight = 1.0; @@ -18740,28 +18740,28 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo } } - + for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) { - + su2double MassFlow = Surface_MassFlow_Total[iMarker_Analyze] * config->GetDensity_Ref() * config->GetVelocity_Ref(); if (config->GetSystemMeasurements() == US) MassFlow *= 32.174; config->SetSurface_MassFlow(iMarker_Analyze, MassFlow); - + su2double Mach = Surface_Mach_Total[iMarker_Analyze]; config->SetSurface_Mach(iMarker_Analyze, Mach); - + su2double Temperature = Surface_Temperature_Total[iMarker_Analyze] * config->GetTemperature_Ref(); config->SetSurface_Temperature(iMarker_Analyze, Temperature); - + su2double Pressure = Surface_Pressure_Total[iMarker_Analyze] * config->GetPressure_Ref(); config->SetSurface_Pressure(iMarker_Analyze, Pressure); - + su2double Density = Surface_Density_Total[iMarker_Analyze] * config->GetDensity_Ref(); config->SetSurface_Density(iMarker_Analyze, Density); - + su2double Enthalpy = Surface_Enthalpy_Total[iMarker_Analyze]; config->SetSurface_Enthalpy(iMarker_Analyze, Enthalpy); - + su2double NormalVelocity = Surface_NormalVelocity_Total[iMarker_Analyze] * config->GetVelocity_Ref(); config->SetSurface_NormalVelocity(iMarker_Analyze, NormalVelocity); @@ -18779,10 +18779,10 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo su2double TotalTemperature = Surface_TotalTemperature_Total[iMarker_Analyze] * config->GetTemperature_Ref(); config->SetSurface_TotalTemperature(iMarker_Analyze, TotalTemperature); - + su2double TotalPressure = Surface_TotalPressure_Total[iMarker_Analyze] * config->GetPressure_Ref(); config->SetSurface_TotalPressure(iMarker_Analyze, TotalPressure); - + } /*--- Compute the average static pressure drop between two surfaces. Note @@ -18802,30 +18802,30 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo } if ((rank == MASTER_NODE) && !config->GetDiscrete_Adjoint() && output) { - + cout.precision(6); cout.setf(ios::scientific, ios::floatfield); cout << endl << "Computing surface mean values." << endl << endl; - + for (iMarker_Analyze = 0; iMarker_Analyze < nMarker_Analyze; iMarker_Analyze++) { cout << "Surface "<< config->GetMarker_Analyze_TagBound(iMarker_Analyze) << ":" << endl; - + if (nDim == 3) { if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Area (m^2): "; else cout << setw(20) << "Area (ft^2): "; } else { if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Area (m): "; else cout << setw(20) << "Area (ft): "; } - + if (config->GetSystemMeasurements() == SI) cout << setw(15) << fabs(Surface_Area_Total[iMarker_Analyze]); else if (config->GetSystemMeasurements() == US) cout << setw(15) << fabs(Surface_Area_Total[iMarker_Analyze])*12.0*12.0; - + cout << endl; su2double MassFlow = config->GetSurface_MassFlow(iMarker_Analyze); if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Mf (kg/s): " << setw(15) << MassFlow; else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Mf (lbs/s): " << setw(15) << MassFlow; - + su2double NormalVelocity = config->GetSurface_NormalVelocity(iMarker_Analyze); if (config->GetSystemMeasurements() == SI) cout << setw(20) << "Vn (m/s): " << setw(15) << NormalVelocity; else if (config->GetSystemMeasurements() == US) cout << setw(20) << "Vn (ft/s): " << setw(15) << NormalVelocity; - + cout << endl; su2double Uniformity = config->GetSurface_Uniformity(iMarker_Analyze); @@ -18849,7 +18849,7 @@ void COutputLegacy::SpecialOutput_AnalyzeSurface(CSolver *solver, CGeometry *geo su2double Pressure = config->GetSurface_Pressure(iMarker_Analyze); if (config->GetSystemMeasurements() == SI) cout << setw(20) << "P (Pa): " << setw(15) << Pressure; else if (config->GetSystemMeasurements() == US) cout << setw(20) << "P (psf): " << setw(15) << Pressure; - + su2double TotalPressure = config->GetSurface_TotalPressure(iMarker_Analyze); if (config->GetSystemMeasurements() == SI) cout << setw(20) << "PT (Pa): " << setw(15) <GetSystemMeasurements() == US) cout << setw(20) << "PT (psf): " << setw(15) <GetTabular_FileFormat() == TAB_CSV){ @@ -20526,7 +20526,7 @@ void COutputLegacy::LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSol Variable_Names.push_back("Cp"); } Variable_Names.push_back("Mach"); - + if ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_LES)){ nVar_Par += 1; Variable_Names.push_back("Laminar_Viscosity"); @@ -20535,7 +20535,7 @@ void COutputLegacy::LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSol nVar_Par += 1; Variable_Names.push_back("Eddy_Viscosity"); } - + if (solver[FLOW_SOL]->VerificationSolution) { if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) { nVar_Par += 2*nVar_Consv_Par; @@ -20551,9 +20551,9 @@ void COutputLegacy::LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSol Variable_Names.push_back("Error_Energy"); } } - + /*--- New variables get registered here before the end of the loop. ---*/ - + /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary geometrical information for the FEM DG solver. ---*/ @@ -20598,34 +20598,34 @@ void COutputLegacy::LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSol const unsigned long offset = nVar_First*volElem[l].offsetDOFsSolLocal; su2double *solDOFs = solver[FirstIndex]->GetVecSolDOFs() + offset; - + for(unsigned short j=0; jSetTDState_rhoe(U[0], StaticEnergy); - + /*--- Load data for the pressure, temperature, Cp, and Mach variables. ---*/ - + Local_Data[jPoint][iVar] = DGFluidModel->GetPressure(); iVar++; Local_Data[jPoint][iVar] = DGFluidModel->GetTemperature(); iVar++; Local_Data[jPoint][iVar] = DGFluidModel->GetCp(); iVar++; Local_Data[jPoint][iVar] = sqrt(Velocity2)/DGFluidModel->GetSoundSpeed(); iVar++; - + if ((Kind_Solver == FEM_NAVIER_STOKES) || (Kind_Solver == FEM_LES)){ Local_Data[jPoint][iVar] = DGFluidModel->GetLaminarViscosity(); iVar++; } @@ -20649,14 +20649,14 @@ void COutputLegacy::LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSol // todo: Export Eddy instead of Laminar viscosity Local_Data[jPoint][iVar] = DGFluidModel->GetLaminarViscosity(); iVar++; } - + if (solver[FLOW_SOL]->VerificationSolution) { if (solver[FLOW_SOL]->VerificationSolution->ExactSolutionKnown()) { - + /*--- Get the physical time if necessary. ---*/ su2double time = 0.0; if (config->GetTime_Marching()) time = config->GetPhysicalTime(); - + /* Get the verification solution. */ su2double mmsSol[5]; solver[FLOW_SOL]->VerificationSolution->GetSolution(coor, time, mmsSol); @@ -20664,7 +20664,7 @@ void COutputLegacy::LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSol Local_Data[jPoint][iVar] = mmsSol[jVar]; iVar++; } - + /* Get local error from the verification solution class. */ su2double error[5]; solver[FLOW_SOL]->VerificationSolution->GetLocalError(coor, time, U, error); @@ -20674,17 +20674,17 @@ void COutputLegacy::LoadLocalData_FEM(CConfig *config, CGeometry *geometry, CSol } } } - + /*--- New variables can be loaded to the Local_Data structure here, assuming they were registered above correctly. ---*/ - + } - + /*--- Increment the point counter. ---*/ - + jPoint++; } - + } @@ -20831,7 +20831,7 @@ void COutputLegacy::PrepareOffsets(CConfig *config, CGeometry *geometry) { nPointCumulative[ii] = nPointCumulative[ii-1] + nPointLinear[ii-1]; } nPointCumulative[size] = nGlobalPoint_Sort; - + } void COutputLegacy::SortConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short val_iZone) { @@ -20885,7 +20885,7 @@ void COutputLegacy::SortConnectivity_FEM(CConfig *config, CGeometry *geometry, u SU2_MPI::Allreduce(&nTotal_Elem, &nGlobal_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); SU2_MPI::Allreduce(&nTotal_Surf_Elem, &nSurf_Elem_Par, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); #endif - + } void COutputLegacy::SortVolumetricConnectivity_FEM(CConfig *config, CGeometry *geometry, unsigned short Elem_Type) { @@ -21035,7 +21035,7 @@ void COutputLegacy::SortSurfaceConnectivity_FEM(CConfig *config, CGeometry *geom default: SU2_MPI::Error("Unrecognized element type", CURRENT_FUNCTION); } - + /*--- Create an object of the class CMeshFEM_DG and retrieve the necessary geometrical information for the FEM DG solver. ---*/ CMeshFEM_DG *DGGeometry = dynamic_cast(geometry); @@ -21462,11 +21462,11 @@ void COutputLegacy::SortOutputData_FEM(CConfig *config, CGeometry *geometry) { delete [] nPoint_Recv; delete [] nPoint_Send; delete [] nPoint_Flag; - + for (iPoint = 0; iPoint < nLocalPoint_Sort; iPoint++) delete [] Local_Data[iPoint]; delete [] Local_Data; - + } void COutputLegacy::SortOutputData_Surface_FEM(CConfig *config, CGeometry *geometry) { diff --git a/SU2_CFD/src/solvers/CAdjEulerSolver.cpp b/SU2_CFD/src/solvers/CAdjEulerSolver.cpp index 2156cfcfab07..02756b69e420 100644 --- a/SU2_CFD/src/solvers/CAdjEulerSolver.cpp +++ b/SU2_CFD/src/solvers/CAdjEulerSolver.cpp @@ -1701,9 +1701,11 @@ void CAdjEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contai } -void CAdjEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, +void CAdjEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { + CNumerics* numerics = numerics_container[CONV_TERM]; + unsigned long iEdge, iPoint, jPoint; bool implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); @@ -1763,17 +1765,20 @@ void CAdjEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_co /*--- Implicit contribution to the residual ---*/ if (implicit) { - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); Jacobian.SubtractBlock(iPoint, jPoint, Jacobian_ij); Jacobian.SubtractBlock(jPoint, iPoint, Jacobian_ji); - Jacobian.SubtractBlock(jPoint, jPoint, Jacobian_jj); + Jacobian.SubtractBlock2Diag(jPoint, Jacobian_jj); } } } -void CAdjEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short iMesh) { +void CAdjEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[CONV_TERM]; su2double **Gradient_i, **Gradient_j, Project_Grad_i, Project_Grad_j, *Limiter_i = NULL, *Limiter_j = NULL, *Psi_i = NULL, *Psi_j = NULL, *V_i, *V_j; @@ -1889,10 +1894,10 @@ void CAdjEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_cont /*--- Implicit contribution to the residual ---*/ if (implicit) { - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); Jacobian.SubtractBlock(iPoint, jPoint, Jacobian_ij); Jacobian.SubtractBlock(jPoint, iPoint, Jacobian_ji); - Jacobian.SubtractBlock(jPoint, jPoint, Jacobian_jj); + Jacobian.SubtractBlock2Diag(jPoint, Jacobian_jj); } } @@ -1910,8 +1915,10 @@ void CAdjEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_cont } -void CAdjEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) { +void CAdjEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[SOURCE_FIRST_TERM]; unsigned short iVar; unsigned long iPoint; @@ -1943,7 +1950,7 @@ void CAdjEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_cont LinSysRes.AddBlock(iPoint, Residual); /*--- Add the implicit Jacobian contribution ---*/ - if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (implicit) Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } } @@ -2002,7 +2009,7 @@ void CAdjEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_cont /*--- Implicit part ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } } @@ -3148,7 +3155,7 @@ void CAdjEulerSolver::BC_Euler_Wall(CGeometry *geometry, Jacobian_ii[nVar-1][nVar-1] -= ProjGridVel; } - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } @@ -3309,7 +3316,7 @@ void CAdjEulerSolver::BC_Sym_Plane(CGeometry *geometry, CSolver **solver_contain /*--- Update jacobian ---*/ - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } @@ -3373,7 +3380,7 @@ void CAdjEulerSolver::BC_Interface_Boundary(CGeometry *geometry, CSolver **solve /*--- Add Residuals and Jacobians ---*/ LinSysRes.SubtractBlock(iPoint, Res_Conv_i); - if (implicit) Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + if (implicit) Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -3472,7 +3479,7 @@ void CAdjEulerSolver::BC_NearField_Boundary(CGeometry *geometry, CSolver **solve /*--- Add Residuals and Jacobians ---*/ LinSysRes.SubtractBlock(iPoint, Res_Conv_i); - if (implicit) Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + if (implicit) Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -3552,7 +3559,7 @@ void CAdjEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_contain /*--- Implicit contribution to the residual ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); /*--- Viscous residual contribution, it doesn't work ---*/ @@ -3581,7 +3588,7 @@ void CAdjEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_contain LinSysRes.SubtractBlock(iPoint, Residual_i); if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } @@ -3661,7 +3668,7 @@ void CAdjEulerSolver::BC_Supersonic_Inlet(CGeometry *geometry, CSolver **solver_ /*--- Implicit contribution to the residual ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); /*--- Viscous residual contribution, it doesn't work ---*/ @@ -3694,7 +3701,7 @@ void CAdjEulerSolver::BC_Supersonic_Inlet(CGeometry *geometry, CSolver **solver_ LinSysRes.SubtractBlock(iPoint, Residual_i); if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -3776,7 +3783,7 @@ void CAdjEulerSolver::BC_Supersonic_Outlet(CGeometry *geometry, CSolver **solver /*--- Implicit contribution to the residual ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); /*--- Viscous residual contribution (check again, Point_Normal was not being initialized before) ---*/ @@ -3809,7 +3816,7 @@ void CAdjEulerSolver::BC_Supersonic_Outlet(CGeometry *geometry, CSolver **solver LinSysRes.SubtractBlock(iPoint, Residual_i); if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -3952,7 +3959,7 @@ void CAdjEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, /*--- Implicit contribution to the residual ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); /*--- Viscous residual contribution, it doesn't work ---*/ @@ -3984,7 +3991,7 @@ void CAdjEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, LinSysRes.SubtractBlock(iPoint, Residual_i); if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -4234,7 +4241,7 @@ void CAdjEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, /*--- Implicit contribution to the residual ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); /*--- Viscous residual contribution, it doesn't work ---*/ @@ -4271,7 +4278,7 @@ void CAdjEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, LinSysRes.SubtractBlock(iPoint, Residual_i); if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -4396,7 +4403,7 @@ void CAdjEulerSolver::BC_Engine_Inflow(CGeometry *geometry, CSolver **solver_con /*--- Implicit contribution to the residual ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -4481,7 +4488,7 @@ void CAdjEulerSolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_co /*--- Implicit contribution to the residual ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -4610,7 +4617,7 @@ void CAdjEulerSolver::BC_ActDisk_Inlet(CGeometry *geometry, CSolver **solver_con /*--- Implicit contribution to the residual ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -4700,7 +4707,7 @@ void CAdjEulerSolver::BC_ActDisk_Outlet(CGeometry *geometry, CSolver **solver_co /*--- Implicit contribution to the residual ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } @@ -4771,7 +4778,7 @@ void CAdjEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver if (config->GetTime_Marching() == DT_STEPPING_2ND) Jacobian_i[iVar][iVar] = (Volume_nP1*3.0)/(2.0*TimeStep); } - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } } @@ -4888,4 +4895,4 @@ void CAdjEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConf if (Restart_Data != NULL) delete [] Restart_Data; Restart_Vars = NULL; Restart_Data = NULL; -} \ No newline at end of file +} diff --git a/SU2_CFD/src/solvers/CAdjNSSolver.cpp b/SU2_CFD/src/solvers/CAdjNSSolver.cpp index 9d3165841fc6..9bfcee1024e1 100644 --- a/SU2_CFD/src/solvers/CAdjNSSolver.cpp +++ b/SU2_CFD/src/solvers/CAdjNSSolver.cpp @@ -416,8 +416,11 @@ void CAdjNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container } -void CAdjNSSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, +void CAdjNSSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { + + CNumerics* numerics = numerics_container[VISC_TERM]; + unsigned long iPoint, jPoint, iEdge; bool implicit = (config->GetKind_TimeIntScheme_AdjFlow() == EULER_IMPLICIT); @@ -453,18 +456,21 @@ void CAdjNSSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_contai LinSysRes.AddBlock(jPoint, Residual_j); if (implicit) { - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); Jacobian.SubtractBlock(iPoint, jPoint, Jacobian_ij); Jacobian.AddBlock(jPoint, iPoint, Jacobian_ji); - Jacobian.AddBlock(jPoint, jPoint, Jacobian_jj); + Jacobian.AddBlock2Diag(jPoint, Jacobian_jj); } } } -void CAdjNSSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) { +void CAdjNSSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[SOURCE_FIRST_TERM]; + CNumerics* second_numerics = numerics_container[SOURCE_SECOND_TERM]; unsigned long iPoint, jPoint, iEdge; @@ -596,7 +602,7 @@ void CAdjNSSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain LinSysRes.AddBlock(iPoint, Residual); /*--- Add the implicit Jacobian contribution ---*/ - if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (implicit) Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } } @@ -1528,7 +1534,7 @@ void CAdjNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_contai modifying the velocity-rows of the Jacobian (1 on the diagonal). ---*/ if (implicit) { - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); for (iVar = 1; iVar <= nDim; iVar++) { total_index = iPoint*nVar+iVar; Jacobian.DeleteValsRowi(total_index); @@ -1890,7 +1896,7 @@ void CAdjNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_cont LinSysRes.AddBlock(iPoint, Res_Conv_i); LinSysRes.SubtractBlock(iPoint, Res_Visc_i); if (implicit) { - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_ii); } } @@ -1908,4 +1914,4 @@ void CAdjNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_cont delete [] GradPhi[iDim]; delete [] GradPhi; delete [] dPoRho2; -} \ No newline at end of file +} diff --git a/SU2_CFD/src/solvers/CAdjTurbSolver.cpp b/SU2_CFD/src/solvers/CAdjTurbSolver.cpp index a0d3841077b5..09bd9a01419e 100644 --- a/SU2_CFD/src/solvers/CAdjTurbSolver.cpp +++ b/SU2_CFD/src/solvers/CAdjTurbSolver.cpp @@ -264,7 +264,7 @@ void CAdjTurbSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_containe /*--- Add Residuals and Jacobians ---*/ conv_numerics->ComputeResidual(Residual, Jacobian_ii, NULL, config); LinSysRes.AddBlock(iPoint, Residual); - Jacobian.AddBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.AddBlock2Diag(iPoint, Jacobian_ii); } @@ -294,7 +294,10 @@ void CAdjTurbSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain } -void CAdjTurbSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short iMesh) { +void CAdjTurbSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[CONV_TERM]; unsigned long iEdge, iPoint, jPoint; su2double *U_i, *U_j, *TurbPsi_i, *TurbPsi_j, **TurbVar_Grad_i, **TurbVar_Grad_j; @@ -331,17 +334,20 @@ void CAdjTurbSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_conta /*--- Add and Subtract Residual ---*/ LinSysRes.AddBlock(iPoint, Residual_i); LinSysRes.AddBlock(jPoint, Residual_j); - Jacobian.AddBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.AddBlock2Diag(iPoint, Jacobian_ii); Jacobian.AddBlock(iPoint, jPoint, Jacobian_ij); Jacobian.AddBlock(jPoint, iPoint, Jacobian_ji); - Jacobian.AddBlock(jPoint, jPoint, Jacobian_jj); + Jacobian.AddBlock2Diag(jPoint, Jacobian_jj); } } -void CAdjTurbSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, - unsigned short iMesh, unsigned short iRKStep) { +void CAdjTurbSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, + CConfig *config, unsigned short iMesh, unsigned short iRKStep) { + + CNumerics* numerics = numerics_container[VISC_TERM]; + unsigned long iEdge, iPoint, jPoint; su2double *Coord_i, *Coord_j; @@ -377,16 +383,21 @@ void CAdjTurbSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_cont LinSysRes.AddBlock(iPoint, Residual_i); LinSysRes.AddBlock(jPoint, Residual_j); - Jacobian.AddBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.AddBlock2Diag(iPoint, Jacobian_ii); Jacobian.AddBlock(iPoint, jPoint, Jacobian_ij); Jacobian.AddBlock(jPoint, iPoint, Jacobian_ji); - Jacobian.AddBlock(jPoint, jPoint, Jacobian_jj); + Jacobian.AddBlock2Diag(jPoint, Jacobian_jj); } } -void CAdjTurbSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, CConfig *config, unsigned short iMesh) { +void CAdjTurbSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[SOURCE_FIRST_TERM]; + //CNumerics* second_numerics = numerics_container[SOURCE_SECOND_TERM]; + unsigned long iPoint; su2double *U_i, **GradPrimVar_i, *TurbVar_i; su2double **TurbVar_Grad_i, *TurbPsi_i, **PsiVar_Grad_i; // Gradients @@ -429,7 +440,7 @@ void CAdjTurbSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta /*--- Add and Subtract Residual ---*/ numerics->ComputeResidual(Residual, Jacobian_ii, NULL, config); LinSysRes.AddBlock(iPoint, Residual); - Jacobian.AddBlock(iPoint, iPoint, Jacobian_ii); + Jacobian.AddBlock2Diag(iPoint, Jacobian_ii); } @@ -460,10 +471,10 @@ void CAdjTurbSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta // second_numerics->ComputeResidual(Residual, Jacobian_ii, Jacobian_jj, config); // LinSysRes.AddBlock(iPoint, Residual); // LinSysRes.SubtractBlock(jPoint, Residual); -// Jacobian.AddBlock(iPoint, iPoint, Jacobian_ii); +// Jacobian.AddBlock2Diag(iPoint, Jacobian_ii); // Jacobian.AddBlock(iPoint, jPoint, Jacobian_jj); // Jacobian.SubtractBlock(jPoint, iPoint, Jacobian_ii); -// Jacobian.SubtractBlock(jPoint, jPoint, Jacobian_jj); +// Jacobian.SubtractBlock2Diag(jPoint, Jacobian_jj); // // } diff --git a/SU2_CFD/src/solvers/CDiscAdjFEASolver.cpp b/SU2_CFD/src/solvers/CDiscAdjFEASolver.cpp index e97c6036397d..5c1da8c9ab66 100644 --- a/SU2_CFD/src/solvers/CDiscAdjFEASolver.cpp +++ b/SU2_CFD/src/solvers/CDiscAdjFEASolver.cpp @@ -29,55 +29,18 @@ #include "../../include/solvers/CDiscAdjFEASolver.hpp" #include "../../include/variables/CDiscAdjFEAVariable.hpp" -CDiscAdjFEASolver::CDiscAdjFEASolver(void) : CSolver (){ +CDiscAdjFEASolver::CDiscAdjFEASolver(void) : CSolver() { } - nMarker = 0; - nMarker_nL = 0; - KindDirect_Solver = 0; +CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config) : CSolver() { } - direct_solver = NULL; - normalLoads = NULL; - Sens_E = NULL; - Sens_Nu = NULL; - Sens_nL = NULL; - CSensitivity = NULL; - - Solution_Vel = NULL; - Solution_Accel= NULL; - - nodes = nullptr; - -} - -CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config) : CSolver(){ - - nMarker = 0; - nMarker_nL = 0; - KindDirect_Solver = 0; - - direct_solver = NULL; - normalLoads = NULL; - Sens_E = NULL; - Sens_Nu = NULL; - Sens_nL = NULL; - CSensitivity = NULL; - - Solution_Vel = NULL; - Solution_Accel= NULL; - - SolRest = NULL; - - nodes = nullptr; - -} - -CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config, CSolver *direct_solver, unsigned short Kind_Solver, unsigned short iMesh) : CSolver(){ +CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config, CSolver *direct_solver, + unsigned short Kind_Solver, unsigned short iMesh) : CSolver() { adjoint = true; - unsigned short iVar, iMarker, iDim; + unsigned short iVar, iMarker; - unsigned long iVertex, iPoint; + unsigned long iPoint; string text_line, mesh_filename; string filename, AdjExt; @@ -94,12 +57,6 @@ CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config, CSolv nPoint = geometry->GetnPoint(); nPointDomain = geometry->GetnPointDomain(); - /*-- Store number of markers with a normal load boundary condition ---*/ - - normalLoads = NULL; - - nMarker_nL = 0; - /*--- Define some auxiliary vectors related to the residual ---*/ Residual = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual[iVar] = 1.0; @@ -108,27 +65,25 @@ CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config, CSolv /*--- 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 = new unsigned long[nVar](); 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; + Point_Max_Coord[iVar] = new su2double[nDim](); } /*--- Define some auxiliary vectors related to the residual for problems with a BGS strategy---*/ - if (config->GetMultizone_Residual()){ + 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]; for (iVar = 0; iVar < nVar; iVar++) Point_Max_BGS[iVar] = 0; + 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]; - for (iDim = 0; iDim < nDim; iDim++) Point_Max_Coord_BGS[iVar][iDim] = 0.0; + Point_Max_Coord_BGS[iVar] = new su2double[nDim](); } } @@ -136,23 +91,14 @@ CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config, CSolv /*--- Define some auxiliary vectors related to the solution ---*/ Solution = new su2double[nVar]; - for (iVar = 0; iVar < nVar; iVar++) Solution[iVar] = 1e-16; - if (dynamic) SolRest = new su2double[3 * nVar]; - else SolRest = new su2double[nVar]; - - Solution_Vel = NULL; - Solution_Accel = NULL; - if (dynamic) { - Solution_Vel = new su2double[nVar]; Solution_Accel = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Solution_Vel[iVar] = 1e-16; for (iVar = 0; iVar < nVar; iVar++) Solution_Accel[iVar] = 1e-16; - } /*--- Sensitivity definition and coefficient in all the markers ---*/ @@ -160,21 +106,12 @@ CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config, CSolv CSensitivity = new su2double* [nMarker]; for (iMarker = 0; iMarker < nMarker; iMarker++) { - CSensitivity[iMarker] = new su2double [geometry->nVertex[iMarker]]; + CSensitivity[iMarker] = new su2double [geometry->nVertex[iMarker]](); } - Sens_E = new su2double[nMarker]; - Sens_Nu = new su2double[nMarker]; - Sens_nL = new su2double[nMarker]; - - for (iMarker = 0; iMarker < nMarker; iMarker++) { - Sens_E[iMarker] = 0.0; - Sens_Nu[iMarker] = 0.0; - Sens_nL[iMarker] = 0.0; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++){ - CSensitivity[iMarker][iVertex] = 0.0; - } - } + Sens_E = new su2double[nMarker](); + Sens_Nu = new su2double[nMarker](); + Sens_nL = new su2double[nMarker](); nodes = new CDiscAdjFEABoundVariable(Solution, Solution_Accel, Solution_Vel, nPoint, nDim, nVar, dynamic, config); SetBaseClassPointerToNodes(); @@ -221,67 +158,46 @@ CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config, CSolv SU2_MPI::Error("WARNING: For a material to be fully defined, E, Nu and Rho need to have the same dimensions.", CURRENT_FUNCTION); } - E_i = new su2double[nMPROP]; - Local_Sens_E = new su2double[nMPROP]; - Global_Sens_E = new su2double[nMPROP]; - Total_Sens_E = new su2double[nMPROP]; - AD_Idx_E_i = new int[nMPROP]; - - Nu_i = new su2double[nMPROP]; - Local_Sens_Nu = new su2double[nMPROP]; - Global_Sens_Nu = new su2double[nMPROP]; - Total_Sens_Nu = new su2double[nMPROP]; - AD_Idx_Nu_i = new int[nMPROP]; - - Rho_i = new su2double[nMPROP]; // For inertial effects - Local_Sens_Rho = new su2double[nMPROP]; - Global_Sens_Rho = new su2double[nMPROP]; - Total_Sens_Rho = new su2double[nMPROP]; - AD_Idx_Rho_i = new int[nMPROP]; - - Rho_DL_i = new su2double[nMPROP]; // For dead loads - Local_Sens_Rho_DL = new su2double[nMPROP]; - Global_Sens_Rho_DL = new su2double[nMPROP]; - Total_Sens_Rho_DL = new su2double[nMPROP]; - AD_Idx_Rho_DL_i = new int[nMPROP]; - - /*--- Initialize the values of the total sensitivities ---*/ - - for (iVar = 0; iVar < nMPROP; iVar++) { - Total_Sens_E[iVar] = 0.0; - Total_Sens_Nu[iVar] = 0.0; - Total_Sens_Rho[iVar] = 0.0; - Total_Sens_Rho_DL[iVar] = 0.0; - } + E_i = new su2double[nMPROP](); + Local_Sens_E = new su2double[nMPROP](); + Global_Sens_E = new su2double[nMPROP](); + Total_Sens_E = new su2double[nMPROP](); + AD_Idx_E_i = new int[nMPROP](); + + Nu_i = new su2double[nMPROP](); + Local_Sens_Nu = new su2double[nMPROP](); + Global_Sens_Nu = new su2double[nMPROP](); + Total_Sens_Nu = new su2double[nMPROP](); + AD_Idx_Nu_i = new int[nMPROP](); + + Rho_i = new su2double[nMPROP](); // For inertial effects + Local_Sens_Rho = new su2double[nMPROP](); + Global_Sens_Rho = new su2double[nMPROP](); + Total_Sens_Rho = new su2double[nMPROP](); + AD_Idx_Rho_i = new int[nMPROP](); + + Rho_DL_i = new su2double[nMPROP](); // For dead loads + Local_Sens_Rho_DL = new su2double[nMPROP](); + Global_Sens_Rho_DL = new su2double[nMPROP](); + Total_Sens_Rho_DL = new su2double[nMPROP](); + AD_Idx_Rho_DL_i = new int[nMPROP](); /*--- Initialize vector structures for multiple electric regions ---*/ de_effects = config->GetDE_Effects(); - EField = NULL; - Local_Sens_EField = NULL; - Global_Sens_EField = NULL; - Total_Sens_EField = NULL; - AD_Idx_EField = NULL; - if (de_effects) { nEField = config->GetnElectric_Field(); - EField = new su2double[nEField]; - Local_Sens_EField = new su2double[nEField]; - Global_Sens_EField = new su2double[nEField]; - Total_Sens_EField = new su2double[nEField]; - AD_Idx_EField = new int[nEField]; - - for (iVar = 0; iVar < nEField; iVar++) { - Total_Sens_EField[iVar] = 0.0; - } + EField = new su2double[nEField](); + Local_Sens_EField = new su2double[nEField](); + Global_Sens_EField = new su2double[nEField](); + Total_Sens_EField = new su2double[nEField](); + AD_Idx_EField = new int[nEField](); } /*--- Initialize vector structures for structural-based design variables ---*/ - nDV = 0; - DV_Val = NULL; switch (config->GetDV_FEA()) { case YOUNG_MODULUS: case POISSON_RATIO: @@ -295,23 +211,12 @@ CDiscAdjFEASolver::CDiscAdjFEASolver(CGeometry *geometry, CConfig *config, CSolv break; } - Local_Sens_DV = NULL; - Global_Sens_DV = NULL; - Total_Sens_DV = NULL; - AD_Idx_DV_Val = NULL; - if (fea_dv) { ReadDV(config); - Local_Sens_DV = new su2double[nDV]; - Global_Sens_DV = new su2double[nDV]; - Total_Sens_DV = new su2double[nDV]; - AD_Idx_DV_Val = new int[nDV]; - - for (iVar = 0; iVar < nDV; iVar++) { - Local_Sens_DV[iVar] = 0.0; - Global_Sens_DV[iVar] = 0.0; - Total_Sens_DV[iVar] = 0.0; - } + Local_Sens_DV = new su2double[nDV](); + Global_Sens_DV = new su2double[nDV](); + Total_Sens_DV = new su2double[nDV](); + AD_Idx_DV_Val = new int[nDV](); } } @@ -320,60 +225,59 @@ CDiscAdjFEASolver::~CDiscAdjFEASolver(void){ unsigned short iMarker; - if (CSensitivity != NULL) { + if (CSensitivity != nullptr) { for (iMarker = 0; iMarker < nMarker; iMarker++) { delete [] CSensitivity[iMarker]; } delete [] CSensitivity; } - if (E_i != NULL) delete [] E_i; - if (Nu_i != NULL) delete [] Nu_i; - if (Rho_i != NULL) delete [] Rho_i; - if (Rho_DL_i != NULL) delete [] Rho_DL_i; - - if (AD_Idx_E_i != NULL) delete [] AD_Idx_E_i; - if (AD_Idx_Nu_i != NULL) delete [] AD_Idx_Nu_i; - if (AD_Idx_Rho_i != NULL) delete [] AD_Idx_Rho_i; - if (AD_Idx_Rho_DL_i != NULL) delete [] AD_Idx_Rho_DL_i; - - if (Local_Sens_E != NULL) delete [] Local_Sens_E; - if (Local_Sens_Nu != NULL) delete [] Local_Sens_Nu; - if (Local_Sens_Rho != NULL) delete [] Local_Sens_Rho; - if (Local_Sens_Rho_DL != NULL) delete [] Local_Sens_Rho_DL; - - if (Global_Sens_E != NULL) delete [] Global_Sens_E; - if (Global_Sens_Nu != NULL) delete [] Global_Sens_Nu; - if (Global_Sens_Rho != NULL) delete [] Global_Sens_Rho; - if (Global_Sens_Rho_DL != NULL) delete [] Global_Sens_Rho_DL; - - if (Total_Sens_E != NULL) delete [] Total_Sens_E; - if (Total_Sens_Nu != NULL) delete [] Total_Sens_Nu; - if (Total_Sens_Rho != NULL) delete [] Total_Sens_Rho; - if (Total_Sens_Rho_DL != NULL) delete [] Total_Sens_Rho_DL; - - if (normalLoads != NULL) delete [] normalLoads; - if (Sens_E != NULL) delete [] Sens_E; - if (Sens_Nu != NULL) delete [] Sens_Nu; - if (Sens_nL != NULL) delete [] Sens_nL; - - if (EField != NULL) delete [] EField; - if (Local_Sens_EField != NULL) delete [] Local_Sens_EField; - if (Global_Sens_EField != NULL) delete [] Global_Sens_EField; - if (Total_Sens_EField != NULL) delete [] Total_Sens_EField; - if (AD_Idx_EField != NULL) delete [] AD_Idx_EField; - - if (DV_Val != NULL) delete [] DV_Val; - if (Local_Sens_DV != NULL) delete [] Local_Sens_DV; - if (Global_Sens_DV != NULL) delete [] Global_Sens_DV; - if (Total_Sens_DV != NULL) delete [] Total_Sens_DV; - if (AD_Idx_DV_Val != NULL) delete [] AD_Idx_DV_Val; - - if (Solution_Vel != NULL) delete [] Solution_Vel; - if (Solution_Accel != NULL) delete [] Solution_Accel; - if (SolRest != NULL) delete [] SolRest; - - if (nodes != nullptr) delete nodes; + delete [] E_i; + delete [] Nu_i; + delete [] Rho_i; + delete [] Rho_DL_i; + + delete [] AD_Idx_E_i; + delete [] AD_Idx_Nu_i; + delete [] AD_Idx_Rho_i; + delete [] AD_Idx_Rho_DL_i; + + delete [] Local_Sens_E; + delete [] Local_Sens_Nu; + delete [] Local_Sens_Rho; + delete [] Local_Sens_Rho_DL; + + delete [] Global_Sens_E; + delete [] Global_Sens_Nu; + delete [] Global_Sens_Rho; + delete [] Global_Sens_Rho_DL; + + delete [] Total_Sens_E; + delete [] Total_Sens_Nu; + delete [] Total_Sens_Rho; + delete [] Total_Sens_Rho_DL; + + delete [] normalLoads; + delete [] Sens_E; + delete [] Sens_Nu; + delete [] Sens_nL; + + delete [] EField; + delete [] Local_Sens_EField; + delete [] Global_Sens_EField; + delete [] Total_Sens_EField; + delete [] AD_Idx_EField; + + delete [] DV_Val; + delete [] Local_Sens_DV; + delete [] Global_Sens_DV; + delete [] Total_Sens_DV; + delete [] AD_Idx_DV_Val; + + delete [] Solution_Vel; + delete [] Solution_Accel; + + delete nodes; } void CDiscAdjFEASolver::SetRecording(CGeometry* geometry, CConfig *config){ @@ -482,9 +386,10 @@ void CDiscAdjFEASolver::RegisterVariables(CGeometry *geometry, CConfig *config, EField[iVar] = config->Get_Electric_Field_Mod(iVar); } -// if (fea_dv) { -// for (iVar = 0; iVar < nDV; iVar++) DV_Val[iVar] = config->GetDV_Value(iVar,0); -// } + /*--- Reset index, otherwise messes up other derivatives ---*/ + if (fea_dv) { + for (iVar = 0; iVar < nDV; iVar++) AD::ResetInput(DV_Val[iVar]); + } if (!reset) { bool local_index = config->GetMultizone_Problem(); @@ -1163,7 +1068,6 @@ void CDiscAdjFEASolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CCo /*--- Read all lines in the restart file ---*/ long iPoint_Local; unsigned long iPoint_Global = 0; unsigned long iPoint_Global_Local = 0; - unsigned short rbuf_NotMatching = 0, sbuf_NotMatching = 0; /*--- Skip coordinates ---*/ @@ -1197,21 +1101,14 @@ void CDiscAdjFEASolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CCo /*--- Detect a wrong solution file ---*/ - if (iPoint_Global_Local < nPointDomain) { sbuf_NotMatching = 1; } - - SU2_MPI::Allreduce(&sbuf_NotMatching, &rbuf_NotMatching, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD); - - if (rbuf_NotMatching != 0) { + if (iPoint_Global_Local < nPointDomain) { SU2_MPI::Error(string("The solution file ") + filename + string(" doesn't match with the mesh file!\n") + string("It could be empty lines at the end of the file."), CURRENT_FUNCTION); } /*--- Delete the class memory that is used to load the restart. ---*/ - if (Restart_Vars != NULL) delete [] Restart_Vars; - if (Restart_Data != NULL) delete [] Restart_Data; - Restart_Vars = NULL; Restart_Data = NULL; + delete [] Restart_Vars; Restart_Vars = nullptr; + delete [] Restart_Data; Restart_Data = nullptr; } - - diff --git a/SU2_CFD/src/solvers/CEulerSolver.cpp b/SU2_CFD/src/solvers/CEulerSolver.cpp index 712b8cab0515..8f2986a2ad74 100644 --- a/SU2_CFD/src/solvers/CEulerSolver.cpp +++ b/SU2_CFD/src/solvers/CEulerSolver.cpp @@ -27,160 +27,69 @@ #include "../../include/solvers/CEulerSolver.hpp" +#include "../../include/variables/CNSVariable.hpp" #include "../../../Common/include/toolboxes/printing_toolbox.hpp" #include "../../include/gradients/computeGradientsGreenGauss.hpp" #include "../../include/gradients/computeGradientsLeastSquares.hpp" #include "../../include/limiters/computeLimiters.hpp" -CEulerSolver::CEulerSolver(void) : CSolver() { - - /*--- Basic array initialization ---*/ - - CD_Inv = NULL; CL_Inv = NULL; CSF_Inv = NULL; CEff_Inv = NULL; - CMx_Inv = NULL; CMy_Inv = NULL; CMz_Inv = NULL; - CFx_Inv = NULL; CFy_Inv = NULL; CFz_Inv = NULL; - CoPx_Inv = NULL; CoPy_Inv = NULL; CoPz_Inv = NULL; - - CD_Mnt = NULL; CL_Mnt = NULL; CSF_Mnt = NULL; CEff_Mnt = NULL; - CMx_Mnt = NULL; CMy_Mnt = NULL; CMz_Mnt = NULL; - CFx_Mnt = NULL; CFy_Mnt = NULL; CFz_Mnt = NULL; - CoPx_Mnt = NULL; CoPy_Mnt = NULL; CoPz_Mnt = NULL; - - CPressure = NULL; CPressureTarget = NULL; HeatFlux = NULL; HeatFluxTarget = NULL; YPlus = NULL; - ForceInviscid = NULL; MomentInviscid = NULL; - ForceMomentum = NULL; MomentMomentum = NULL; - - /*--- Surface based array initialization ---*/ - - Surface_CL_Inv = NULL; Surface_CD_Inv = NULL; Surface_CSF_Inv = NULL; Surface_CEff_Inv = NULL; - Surface_CFx_Inv = NULL; Surface_CFy_Inv = NULL; Surface_CFz_Inv = NULL; - Surface_CMx_Inv = NULL; Surface_CMy_Inv = NULL; Surface_CMz_Inv = NULL; - - Surface_CL_Mnt = NULL; Surface_CD_Mnt = NULL; Surface_CSF_Mnt = NULL; Surface_CEff_Mnt = NULL; - Surface_CFx_Mnt = NULL; Surface_CFy_Mnt = NULL; Surface_CFz_Mnt = NULL; - Surface_CMx_Mnt = NULL; Surface_CMy_Mnt = NULL; Surface_CMz_Mnt = NULL; - - Surface_CL = NULL; Surface_CD = NULL; Surface_CSF = NULL; Surface_CEff = NULL; - Surface_CFx = NULL; Surface_CFy = NULL; Surface_CFz = NULL; - Surface_CMx = NULL; Surface_CMy = NULL; Surface_CMz = NULL; - - /*--- Rotorcraft simulation array initialization ---*/ - - CMerit_Inv = NULL; CT_Inv = NULL; CQ_Inv = NULL; - - CMerit_Mnt = NULL; CT_Mnt = NULL; CQ_Mnt = NULL; - - /*--- Supersonic simulation array initialization ---*/ - - CEquivArea_Inv = NULL; - CNearFieldOF_Inv = NULL; - - /*--- Engine simulation array initialization ---*/ - - Inflow_MassFlow = NULL; Inflow_Pressure = NULL; - Inflow_Mach = NULL; Inflow_Area = NULL; - Exhaust_Pressure = NULL; Exhaust_Temperature = NULL; - Exhaust_MassFlow = NULL; Exhaust_Area = NULL; - - /*--- Numerical methods array initialization ---*/ - - LowMach_Precontioner = NULL; - Primitive = NULL; Primitive_i = NULL; Primitive_j = NULL; - CharacPrimVar = NULL; - - DonorPrimVar = NULL; DonorGlobalIndex = NULL; - ActDisk_DeltaP = NULL; ActDisk_DeltaT = NULL; - - Inlet_Ttotal = NULL; Inlet_Ptotal = NULL; Inlet_FlowDir = NULL; - nVertex = NULL; - - Smatrix = NULL; Cvector = NULL; - - Secondary = NULL; Secondary_i = NULL; Secondary_j = NULL; - - /*--- Fixed CL mode initialization ---*/ - - Start_AoA_FD = false; - End_AoA_FD = false; - Update_AoA = false; - Iter_Update_AoA = 0; - - FluidModel = NULL; - - SlidingState = NULL; - SlidingStateNodes = NULL; - - /*--- Initialize quantities for the average process for internal flow ---*/ - - AverageVelocity = NULL; - AverageTurboVelocity = NULL; - OldAverageTurboVelocity = NULL; - ExtAverageTurboVelocity = NULL; - AverageFlux = NULL; - SpanTotalFlux = NULL; - AveragePressure = NULL; - OldAveragePressure = NULL; - RadialEquilibriumPressure = NULL; - ExtAveragePressure = NULL; - AverageDensity = NULL; - OldAverageDensity = NULL; - ExtAverageDensity = NULL; - AverageNu = NULL; - AverageKine = NULL; - AverageOmega = NULL; - ExtAverageNu = NULL; - ExtAverageKine = NULL; - ExtAverageOmega = NULL; - - - /*--- Initialize primitive quantities for turboperformace ---*/ - - DensityIn = NULL; - PressureIn = NULL; - TurboVelocityIn = NULL; - DensityOut = NULL; - PressureOut = NULL; - TurboVelocityOut = NULL; - KineIn = NULL; - OmegaIn = NULL; - NuIn = NULL; - KineOut = NULL; - OmegaOut = NULL; - NuOut = NULL; +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; +} - /*--- Initialize quantities for Giles BC---*/ +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; +} - CkInflow = NULL; - CkOutflow1 = NULL; - CkOutflow2 = NULL; +CEulerSolver::CEulerSolver(void) : CSolver() { } - nodes = nullptr; -} +CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, + unsigned short iMesh, const bool navier_stokes) : CSolver() { -CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) : CSolver() { + /*--- Based on the navier_stokes boolean, determine if this constructor is + * being called by itself, or by its derived class CNSSolver. ---*/ + string description; + unsigned short nSecVar; + if (navier_stokes) { + description = "Navier-Stokes"; + nSecVar = 8; + } + else { + description = "Euler"; + nSecVar = 2; + } - unsigned long iPoint, counter_local = 0, counter_global = 0, iVertex; + unsigned long iPoint, counter_local = 0, counter_global = 0; unsigned short iVar, iDim, iMarker, nLineLets; su2double StaticEnergy, Density, Velocity2, Pressure, Temperature; unsigned short nZone = geometry->GetnZone(); - bool restart = (config->GetRestart() || config->GetRestart_Flow()); - bool roe_turkel = (config->GetKind_Upwind_Flow() == TURKEL); + bool restart = (config->GetRestart() || config->GetRestart_Flow()); bool rans = (config->GetKind_Turb_Model() != NONE); unsigned short direct_diff = config->GetDirectDiff(); int Unst_RestartIter = 0; - bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || - (config->GetTime_Marching() == DT_STEPPING_2ND)); - bool time_stepping = config->GetTime_Marching() == TIME_STEPPING; + bool dual_time = (config->GetTime_Marching() == DT_STEPPING_1ST) || + (config->GetTime_Marching() == DT_STEPPING_2ND); + bool time_stepping = (config->GetTime_Marching() == TIME_STEPPING); - /* A grid is defined as dynamic if there's rigid grid movement or grid deformation AND the problem is time domain */ + /*--- 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(); - bool low_mach_prec = config->Low_Mach_Preconditioning(); - bool adjoint = (config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint()); - bool fsi = config->GetFSI_Simulation(); - bool multizone = config->GetMultizone_Problem(); string filename_ = "flow"; /*--- Store the multigrid level. ---*/ @@ -216,124 +125,6 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short } - /*--- Array initialization ---*/ - - /*--- Basic array initialization ---*/ - - CD_Inv = NULL; CL_Inv = NULL; CSF_Inv = NULL; CEff_Inv = NULL; - CMx_Inv = NULL; CMy_Inv = NULL; CMz_Inv = NULL; - CFx_Inv = NULL; CFy_Inv = NULL; CFz_Inv = NULL; - CoPx_Inv = NULL; CoPy_Inv = NULL; CoPz_Inv = NULL; - - CD_Mnt= NULL; CL_Mnt= NULL; CSF_Mnt= NULL; CEff_Mnt= NULL; - CMx_Mnt= NULL; CMy_Mnt= NULL; CMz_Mnt= NULL; - CFx_Mnt= NULL; CFy_Mnt= NULL; CFz_Mnt= NULL; - CoPx_Mnt= NULL; CoPy_Mnt= NULL; CoPz_Mnt= NULL; - - CPressure = NULL; CPressureTarget = NULL; HeatFlux = NULL; HeatFluxTarget = NULL; YPlus = NULL; - ForceInviscid = NULL; MomentInviscid = NULL; - ForceMomentum = NULL; MomentMomentum = NULL; - - /*--- Surface based array initialization ---*/ - - Surface_CL_Inv = NULL; Surface_CD_Inv = NULL; Surface_CSF_Inv = NULL; Surface_CEff_Inv = NULL; - Surface_CFx_Inv = NULL; Surface_CFy_Inv = NULL; Surface_CFz_Inv = NULL; - Surface_CMx_Inv = NULL; Surface_CMy_Inv = NULL; Surface_CMz_Inv = NULL; - - Surface_CL_Mnt= NULL; Surface_CD_Mnt= NULL; Surface_CSF_Mnt= NULL; Surface_CEff_Mnt= NULL; - Surface_CFx_Mnt= NULL; Surface_CFy_Mnt= NULL; Surface_CFz_Mnt= NULL; - Surface_CMx_Mnt= NULL; Surface_CMy_Mnt= NULL; Surface_CMz_Mnt = NULL; - - Surface_CL = NULL; Surface_CD = NULL; Surface_CSF = NULL; Surface_CEff = NULL; - Surface_CFx = NULL; Surface_CFy = NULL; Surface_CFz = NULL; - Surface_CMx = NULL; Surface_CMy = NULL; Surface_CMz = NULL; - - /*--- Rotorcraft simulation array initialization ---*/ - - CMerit_Inv = NULL; CT_Inv = NULL; CQ_Inv = NULL; - - CMerit_Mnt = NULL; CT_Mnt = NULL; CQ_Mnt = NULL; - - /*--- Supersonic simulation array initialization ---*/ - - CEquivArea_Inv = NULL; - CNearFieldOF_Inv = NULL; - - /*--- Engine simulation array initialization ---*/ - - Inflow_MassFlow = NULL; Inflow_Pressure = NULL; - Inflow_Mach = NULL; Inflow_Area = NULL; - Exhaust_Pressure = NULL; Exhaust_Temperature = NULL; - Exhaust_MassFlow = NULL; Exhaust_Area = NULL; - - /*--- Numerical methods array initialization ---*/ - - iPoint_UndLapl = NULL; - jPoint_UndLapl = NULL; - LowMach_Precontioner = NULL; - Primitive = NULL; Primitive_i = NULL; Primitive_j = NULL; - CharacPrimVar = NULL; - DonorPrimVar = NULL; DonorGlobalIndex = NULL; - ActDisk_DeltaP = NULL; ActDisk_DeltaT = NULL; - - Smatrix = NULL; Cvector = NULL; - - Secondary=NULL; Secondary_i=NULL; Secondary_j=NULL; - - /*--- Fixed CL mode initialization ---*/ - - Start_AoA_FD = false; - End_AoA_FD = false; - Update_AoA = false; - Iter_Update_AoA = 0; - - FluidModel = NULL; - - /*--- Initialize quantities for the average process for internal flow ---*/ - - AverageVelocity = NULL; - AverageTurboVelocity = NULL; - OldAverageTurboVelocity = NULL; - ExtAverageTurboVelocity = NULL; - AverageFlux = NULL; - SpanTotalFlux = NULL; - AveragePressure = NULL; - OldAveragePressure = NULL; - RadialEquilibriumPressure = NULL; - ExtAveragePressure = NULL; - AverageDensity = NULL; - OldAverageDensity = NULL; - ExtAverageDensity = NULL; - AverageNu = NULL; - AverageKine = NULL; - AverageOmega = NULL; - ExtAverageNu = NULL; - ExtAverageKine = NULL; - ExtAverageOmega = NULL; - - - /*--- Initialize primitive quantities for turboperformace ---*/ - - DensityIn = NULL; - PressureIn = NULL; - TurboVelocityIn = NULL; - DensityOut = NULL; - PressureOut = NULL; - TurboVelocityOut = NULL; - KineIn = NULL; - OmegaIn = NULL; - NuIn = NULL; - KineOut = NULL; - OmegaOut = NULL; - NuOut = NULL; - - - /*--- Initialize quantities for Giles BC---*/ - - CkInflow = NULL; - CkOutflow1 = NULL; - CkOutflow2 = NULL; - /*--- Set the gamma value ---*/ Gamma = config->GetGamma(); @@ -347,7 +138,7 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short nVar = nDim+2; nPrimVar = nDim+9; nPrimVarGrad = nDim+4; - nSecondaryVar = 2; nSecondaryVarGrad = 2; + nSecondaryVar = nSecVar; nSecondaryVarGrad = 2; /*--- Initialize nVarGrad for deallocation ---*/ @@ -376,65 +167,40 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short SetVerificationSolution(nDim, nVar, config); - /*--- Define some auxiliary vectors related to the residual ---*/ + /*--- 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; - Residual_i = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_i[iVar] = 0.0; - Residual_j = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_j[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; + Residual = new su2double[nVar](); + Residual_RMS = new su2double[nVar](); + Residual_Max = new su2double[nVar](); + Residual_i = new su2double[nVar](); + Residual_j = new su2double[nVar](); + Res_Conv = new su2double[nVar](); + Res_Visc = new su2double[nVar](); + Res_Sour = new su2double[nVar](); /*--- 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 = new unsigned long[nVar](); 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; + Point_Max_Coord[iVar] = new su2double[nDim](); } /*--- 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; + Solution = new su2double[nVar](); /*--- 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 auxiliary vectors related to the Secondary solution ---*/ - - Secondary = new su2double[nSecondaryVar]; for (iVar = 0; iVar < nSecondaryVar; iVar++) Secondary[iVar] = 0.0; - Secondary_i = new su2double[nSecondaryVar]; for (iVar = 0; iVar < nSecondaryVar; iVar++) Secondary_i[iVar] = 0.0; - Secondary_j = new su2double[nSecondaryVar]; for (iVar = 0; iVar < nSecondaryVar; iVar++) Secondary_j[iVar] = 0.0; + Vector = new su2double[nDim](); - /*--- Define some auxiliary vectors related to the undivided lapalacian ---*/ + /*--- 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]; } - /*--- Define some auxiliary vectors related to low-speed preconditioning ---*/ - - if (roe_turkel || low_mach_prec) { - LowMach_Precontioner = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar ++) - LowMach_Precontioner[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). ---*/ @@ -453,18 +219,22 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short Jacobian_j[iVar] = new su2double [nVar]; } - if (rank == MASTER_NODE) cout << "Initialize Jacobian structure (Euler). MG level: " << iMesh <<"." << endl; + if (rank == MASTER_NODE) + cout << "Initialize Jacobian structure (" << description << "). 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; + 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; + if (rank == MASTER_NODE) + cout << "Explicit scheme. No Jacobian structure (" << description << "). MG level: " << iMesh <<"." << endl; } /*--- Define some auxiliary vectors for computing flow variable @@ -481,193 +251,73 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short Cvector[iVar] = new su2double [nDim]; } - /*--- Store the value of the characteristic primitive variables at the boundaries ---*/ + /*--- Allocates a 2D array with variable "outer" sizes and init to 0. ---*/ - 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; - } + 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 primitive variables + 2 turb variables at the boundaries, used for IO with a donor cell ---*/ - DonorPrimVar = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - DonorPrimVar[iMarker] = new su2double* [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - if (rans) { - DonorPrimVar[iMarker][iVertex] = new su2double [nPrimVar+2]; - for (iVar = 0; iVar < nPrimVar + 2 ; iVar++) { - DonorPrimVar[iMarker][iVertex][iVar] = 0.0; - } - } - else { - DonorPrimVar[iMarker][iVertex] = new su2double [nPrimVar]; - for (iVar = 0; iVar < nPrimVar ; iVar++) { - DonorPrimVar[iMarker][iVertex][iVar] = 0.0; - } - } - } - } + Alloc3D(nMarker, nVertex, (rans? nPrimVar+2 : nPrimVar), DonorPrimVar); /*--- Store the value of the characteristic primitive variables index at the boundaries ---*/ DonorGlobalIndex = new unsigned long* [nMarker]; for (iMarker = 0; iMarker < nMarker; iMarker++) { - DonorGlobalIndex[iMarker] = new unsigned long [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - DonorGlobalIndex[iMarker][iVertex] = 0; - } + DonorGlobalIndex[iMarker] = new unsigned long [nVertex[iMarker]](); } /*--- Store the value of the Delta P at the Actuator Disk ---*/ - ActDisk_DeltaP = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - ActDisk_DeltaP[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - ActDisk_DeltaP[iMarker][iVertex] = 0; - } - } + Alloc2D(nMarker, nVertex, ActDisk_DeltaP); /*--- Store the value of the Delta T at the Actuator Disk ---*/ - ActDisk_DeltaT = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - ActDisk_DeltaT[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - ActDisk_DeltaT[iMarker][iVertex] = 0; - } - } + Alloc2D(nMarker, nVertex, ActDisk_DeltaT); /*--- 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; - } - } + Alloc2D(nMarker, nVertex, Inlet_Ttotal); /*--- 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; - } - } + Alloc2D(nMarker, nVertex, Inlet_Ptotal); /*--- 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; - } - } - } + Alloc3D(nMarker, nVertex, nDim, Inlet_FlowDir); /*--- 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; - } - } - - /*--- 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]; + 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 ---*/ @@ -686,23 +336,7 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short Exhaust_Temperature = new su2double[nMarker]; Exhaust_Area = 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_CEquivArea = 0.0; Total_CNearFieldOF = 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; - Total_NetThrust = 0.0; - Total_Power = 0.0; AoA_Prev = 0.0; AoA_inc = 0.0; - Total_CL_Prev = 0.0; Total_CD_Prev = 0.0; - Total_CMx_Prev = 0.0; Total_CMy_Prev = 0.0; Total_CMz_Prev = 0.0; - Total_AeroCD = 0.0; Total_SolidCD = 0.0; Total_IDR = 0.0; Total_IDC = 0.0; - - /*--- Read farfield conditions ---*/ + /*--- Read farfield conditions from config ---*/ Density_Inf = config->GetDensity_FreeStreamND(); Pressure_Inf = config->GetPressure_FreeStreamND(); @@ -735,7 +369,6 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short break; } - /*--- Initialize fan face pressure, fan face mach number, and mass flow rate ---*/ for (iMarker = 0; iMarker < nMarker; iMarker++) { @@ -752,26 +385,18 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short /*--- Initializate quantities for SlidingMesh Interface ---*/ - SlidingState = new su2double*** [nMarker]; - SlidingStateNodes = new int* [nMarker]; - - for (iMarker = 0; iMarker < nMarker; iMarker++){ - SlidingState[iMarker] = NULL; - SlidingStateNodes[iMarker] = NULL; + SlidingState = new su2double*** [nMarker](); + SlidingStateNodes = new int* [nMarker](); - if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE){ - - SlidingState[iMarker] = new su2double**[geometry->GetnVertex(iMarker)]; - SlidingStateNodes[iMarker] = new int [geometry->GetnVertex(iMarker)]; + for (iMarker = 0; iMarker < nMarker; iMarker++) { - for (iPoint = 0; iPoint < geometry->GetnVertex(iMarker); iPoint++){ - SlidingState[iMarker][iPoint] = new su2double*[nPrimVar+1]; + if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) { - SlidingStateNodes[iMarker][iPoint] = 0; - for (iVar = 0; iVar < nPrimVar+1; iVar++) - SlidingState[iMarker][iPoint][iVar] = NULL; - } + 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](); } } @@ -788,9 +413,39 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short /*--- Initialize the solution to the far-field state everywhere. ---*/ - nodes = new CEulerVariable(Density_Inf, Velocity_Inf, Energy_Inf, nPoint, nDim, nVar, config); + if (navier_stokes) { + nodes = new CNSVariable(Density_Inf, Velocity_Inf, Energy_Inf, nPoint, nDim, nVar, config); + } else { + nodes = new CEulerVariable(Density_Inf, Velocity_Inf, Energy_Inf, nPoint, nDim, nVar, config); + } SetBaseClassPointerToNodes(); +#ifdef HAVE_OMP + /*--- Get the edge coloring, on coarse grids (which are difficult to color) setup the reducer strategy, + * if required (i.e. in parallel). 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. ---*/ + + const auto& coloring = geometry->GetEdgeColoring(); + + if (!coloring.empty()) { + auto nColor = coloring.getOuterSize(); + EdgeColoring.reserve(nColor); + + for(auto iColor = 0ul; iColor < nColor; ++iColor) { + EdgeColoring.emplace_back(coloring.innerIdx(iColor), coloring.getNumNonZeros(iColor)); + } + } + ColorGroupSize = geometry->GetEdgeColorGroupSize(); + + if ((MGLevel != MESH_0) && (omp_get_max_threads() > 1)) { + 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 + /*--- Check that the initial solution is physical, report any non-physical nodes ---*/ counter_local = 0; @@ -805,9 +460,9 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short StaticEnergy= nodes->GetEnergy(iPoint) - 0.5*Velocity2; - FluidModel->SetTDState_rhoe(Density, StaticEnergy); - Pressure= FluidModel->GetPressure(); - Temperature= FluidModel->GetTemperature(); + GetFluidModel()->SetTDState_rhoe(Density, StaticEnergy); + Pressure= GetFluidModel()->GetPressure(); + Temperature= GetFluidModel()->GetTemperature(); /*--- Use the values at the infinity ---*/ @@ -823,43 +478,35 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, unsigned short } - /*--- Initialize the BGS residuals in FSI problems. ---*/ - if (fsi || multizone){ - 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]; 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; - } - } - /*--- Warning message about non-physical points ---*/ if (config->GetComm_Level() == COMM_FULL) { -#ifdef HAVE_MPI + SU2_MPI::Reduce(&counter_local, &counter_global, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD); -#else - counter_global = counter_local; -#endif + if ((rank == MASTER_NODE) && (counter_global != 0)) cout << "Warning. The original solution contains "<< counter_global << " points that are not physical." << endl; } - /*--- Define solver parameters needed for execution of destructor ---*/ + /*--- 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 ---*/ - if (config->GetKind_ConvNumScheme_Flow() == SPACE_CENTERED ) space_centered = true; - else space_centered = false; + 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](); + } + } - if (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT) euler_implicit = true; - else euler_implicit = false; + /*--- Define solver parameters needed for execution of destructor ---*/ - if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) least_squares = true; - else least_squares = false; + 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. ---*/ @@ -901,101 +548,18 @@ CEulerSolver::~CEulerSolver(void) { /*--- Array deallocation ---*/ - if (CD_Inv != NULL) delete [] CD_Inv; - if (CL_Inv != NULL) delete [] CL_Inv; - if (CSF_Inv != NULL) delete [] CSF_Inv; - if (CMx_Inv != NULL) delete [] CMx_Inv; - if (CMy_Inv != NULL) delete [] CMy_Inv; - if (CMz_Inv != NULL) delete [] CMz_Inv; - if (CFx_Inv != NULL) delete [] CFx_Inv; - if (CFy_Inv != NULL) delete [] CFy_Inv; - if (CFz_Inv != NULL) delete [] CFz_Inv; - if (CoPx_Inv != NULL) delete [] CoPx_Inv; - if (CoPy_Inv != NULL) delete [] CoPy_Inv; - if (CoPz_Inv != NULL) delete [] CoPz_Inv; - if (Surface_CL_Inv != NULL) delete[] Surface_CL_Inv; - if (Surface_CD_Inv != NULL) delete[] Surface_CD_Inv; - if (Surface_CSF_Inv != NULL) delete[] Surface_CSF_Inv; - if (Surface_CEff_Inv != NULL) delete[] Surface_CEff_Inv; - if (Surface_CFx_Inv != NULL) delete [] Surface_CFx_Inv; - if (Surface_CFy_Inv != NULL) delete [] Surface_CFy_Inv; - if (Surface_CFz_Inv != NULL) delete [] Surface_CFz_Inv; - if (Surface_CMx_Inv != NULL) delete [] Surface_CMx_Inv; - if (Surface_CMy_Inv != NULL) delete [] Surface_CMy_Inv; - if (Surface_CMz_Inv != NULL) delete [] Surface_CMz_Inv; - - if (CD_Mnt != NULL) delete [] CD_Mnt; - if (CL_Mnt != NULL) delete [] CL_Mnt; - if (CSF_Mnt != NULL) delete [] CSF_Mnt; - if (CFx_Mnt != NULL) delete [] CFx_Mnt; - if (CFy_Mnt != NULL) delete [] CFy_Mnt; - if (CFz_Mnt != NULL) delete [] CFz_Mnt; - if (CMx_Mnt != NULL) delete [] CMx_Mnt; - if (CMy_Mnt != NULL) delete [] CMy_Mnt; - if (CMz_Mnt != NULL) delete [] CMz_Mnt; - if (CoPx_Mnt != NULL) delete [] CoPx_Mnt; - if (CoPy_Mnt != NULL) delete [] CoPy_Mnt; - if (CoPz_Mnt != NULL) delete [] CoPz_Mnt; - if (Surface_CL_Mnt != NULL) delete[] Surface_CL_Mnt; - if (Surface_CD_Mnt != NULL) delete[] Surface_CD_Mnt; - if (Surface_CSF_Mnt != NULL) delete[] Surface_CSF_Mnt; - if (Surface_CEff_Mnt != NULL) delete[] Surface_CEff_Mnt; - if (Surface_CFx_Mnt != NULL) delete [] Surface_CFx_Mnt; - if (Surface_CFy_Mnt != NULL) delete [] Surface_CFy_Mnt; - if (Surface_CFz_Mnt != NULL) delete [] Surface_CFz_Mnt; - if (Surface_CMx_Mnt != NULL) delete [] Surface_CMx_Mnt; - if (Surface_CMy_Mnt != NULL) delete [] Surface_CMy_Mnt; - if (Surface_CMz_Mnt != NULL) delete [] Surface_CMz_Mnt; - - if (Surface_CL != NULL) delete [] Surface_CL; - if (Surface_CD != NULL) delete [] Surface_CD; - if (Surface_CSF != NULL) delete [] Surface_CSF; - if (Surface_CEff != NULL) delete [] Surface_CEff; - if (Surface_CFx != NULL) delete [] Surface_CFx; - if (Surface_CFy != NULL) delete [] Surface_CFy; - if (Surface_CFz != NULL) delete [] Surface_CFz; - if (Surface_CMx != NULL) delete [] Surface_CMx; - if (Surface_CMy != NULL) delete [] Surface_CMy; - if (Surface_CMz != NULL) delete [] Surface_CMz; - if (CEff_Inv != NULL) delete [] CEff_Inv; - if (CMerit_Inv != NULL) delete [] CMerit_Inv; - if (CT_Inv != NULL) delete [] CT_Inv; - if (CQ_Inv != NULL) delete [] CQ_Inv; - if (CEquivArea_Inv != NULL) delete [] CEquivArea_Inv; - if (CNearFieldOF_Inv != NULL) delete [] CNearFieldOF_Inv; - - if (CEff_Mnt != NULL) delete [] CEff_Mnt; - if (CMerit_Mnt != NULL) delete [] CMerit_Mnt; - if (CT_Mnt != NULL) delete [] CT_Mnt; - if (CQ_Mnt != NULL) delete [] CQ_Mnt; - - if (ForceInviscid != NULL) delete [] ForceInviscid; - if (MomentInviscid != NULL) delete [] MomentInviscid; - if (ForceMomentum != NULL) delete [] ForceMomentum; - if (MomentMomentum != NULL) delete [] MomentMomentum; - if (Inflow_MassFlow != NULL) delete [] Inflow_MassFlow; - if (Exhaust_MassFlow != NULL) delete [] Exhaust_MassFlow; - if (Exhaust_Area != NULL) delete [] Exhaust_Area; - if (Inflow_Pressure != NULL) delete [] Inflow_Pressure; - if (Inflow_Mach != NULL) delete [] Inflow_Mach; - if (Inflow_Area != NULL) delete [] Inflow_Area; - - if (Exhaust_Pressure != NULL) delete [] Exhaust_Pressure; - if (Exhaust_Temperature != NULL) delete [] Exhaust_Temperature; - - if (Primitive != NULL) delete [] Primitive; - if (Primitive_i != NULL) delete [] Primitive_i; - if (Primitive_j != NULL) delete [] Primitive_j; - - if (Secondary != NULL) delete [] Secondary; - if (Secondary_i != NULL) delete [] Secondary_i; - if (Secondary_j != NULL) delete [] Secondary_j; - - if (LowMach_Precontioner != NULL) { - for (iVar = 0; iVar < nVar; iVar ++) - delete [] LowMach_Precontioner[iVar]; - delete [] LowMach_Precontioner; - } + delete [] CEquivArea_Inv; + delete [] CNearFieldOF_Inv; + + delete [] Inflow_MassFlow; + delete [] Exhaust_MassFlow; + delete [] Exhaust_Area; + delete [] Inflow_Pressure; + delete [] Inflow_Mach; + delete [] Inflow_Area; + + delete [] Exhaust_Pressure; + delete [] Exhaust_Temperature; if (CPressure != NULL) { for (iMarker = 0; iMarker < nMarker; iMarker++) @@ -1114,7 +678,7 @@ CEulerSolver::~CEulerSolver(void) { delete [] YPlus; } - if (FluidModel != NULL) delete FluidModel; + for(auto& model : FluidModel) delete model; if(AverageVelocity !=NULL){ for (iMarker = 0; iMarker < nMarker; iMarker++) { @@ -1152,7 +716,6 @@ CEulerSolver::~CEulerSolver(void) { delete [] ExtAverageTurboVelocity; } - if(AverageFlux !=NULL){ for (iMarker = 0; iMarker < nMarker; iMarker++) { for(iSpan = 0; iSpan < nSpanWiseSections + 1; iSpan++) @@ -1356,11 +919,11 @@ CEulerSolver::~CEulerSolver(void) { delete [] CkOutflow2; } - if (nodes != nullptr) delete nodes; + delete nodes; } void CEulerSolver::InitTurboContainers(CGeometry *geometry, CConfig *config){ - unsigned short iMarker, iSpan, iDim, iVar; + unsigned short iMarker, iSpan, iVar; nSpanMax = config->GetnSpanMaxAllZones(); @@ -1395,56 +958,30 @@ void CEulerSolver::InitTurboContainers(CGeometry *geometry, CConfig *config){ ExtAverageTurboVelocity[iMarker] = new su2double* [nSpanWiseSections + 1]; AverageFlux[iMarker] = new su2double* [nSpanWiseSections + 1]; SpanTotalFlux[iMarker] = new su2double* [nSpanWiseSections + 1]; - AveragePressure[iMarker] = new su2double [nSpanWiseSections + 1]; - OldAveragePressure[iMarker] = new su2double [nSpanWiseSections + 1]; - RadialEquilibriumPressure[iMarker] = new su2double [nSpanWiseSections + 1]; - ExtAveragePressure[iMarker] = new su2double [nSpanWiseSections + 1]; - AverageDensity[iMarker] = new su2double [nSpanWiseSections + 1]; - OldAverageDensity[iMarker] = new su2double [nSpanWiseSections + 1]; - ExtAverageDensity[iMarker] = new su2double [nSpanWiseSections + 1]; - AverageNu[iMarker] = new su2double [nSpanWiseSections + 1]; - AverageKine[iMarker] = new su2double [nSpanWiseSections + 1]; - AverageOmega[iMarker] = new su2double [nSpanWiseSections + 1]; - ExtAverageNu[iMarker] = new su2double [nSpanWiseSections + 1]; - ExtAverageKine[iMarker] = new su2double [nSpanWiseSections + 1]; - ExtAverageOmega[iMarker] = new su2double [nSpanWiseSections + 1]; + AveragePressure[iMarker] = new su2double [nSpanWiseSections + 1](); + OldAveragePressure[iMarker] = new su2double [nSpanWiseSections + 1](); + RadialEquilibriumPressure[iMarker] = new su2double [nSpanWiseSections + 1](); + ExtAveragePressure[iMarker] = new su2double [nSpanWiseSections + 1](); + AverageDensity[iMarker] = new su2double [nSpanWiseSections + 1](); + OldAverageDensity[iMarker] = new su2double [nSpanWiseSections + 1](); + ExtAverageDensity[iMarker] = new su2double [nSpanWiseSections + 1](); + AverageNu[iMarker] = new su2double [nSpanWiseSections + 1](); + AverageKine[iMarker] = new su2double [nSpanWiseSections + 1](); + AverageOmega[iMarker] = new su2double [nSpanWiseSections + 1](); + ExtAverageNu[iMarker] = new su2double [nSpanWiseSections + 1](); + ExtAverageKine[iMarker] = new su2double [nSpanWiseSections + 1](); + ExtAverageOmega[iMarker] = new su2double [nSpanWiseSections + 1](); for(iSpan = 0; iSpan < nSpanWiseSections + 1; iSpan++){ - AverageVelocity[iMarker][iSpan] = new su2double [nDim]; - AverageTurboVelocity[iMarker][iSpan] = new su2double [nDim]; - OldAverageTurboVelocity[iMarker][iSpan] = new su2double [nDim]; - ExtAverageTurboVelocity[iMarker][iSpan] = new su2double [nDim]; - AverageFlux[iMarker][iSpan] = new su2double [nVar]; - SpanTotalFlux[iMarker][iSpan] = new su2double [nVar]; - AveragePressure[iMarker][iSpan] = 0.0; - OldAveragePressure[iMarker][iSpan] = 0.0; - RadialEquilibriumPressure[iMarker][iSpan] = 0.0; - ExtAveragePressure[iMarker][iSpan] = 0.0; - AverageDensity[iMarker][iSpan] = 0.0; - OldAverageDensity[iMarker][iSpan] = 0.0; - ExtAverageDensity[iMarker][iSpan] = 0.0; - AverageNu[iMarker][iSpan] = 0.0; - AverageKine[iMarker][iSpan] = 0.0; - AverageOmega[iMarker][iSpan] = 0.0; - ExtAverageNu[iMarker][iSpan] = 0.0; - ExtAverageKine[iMarker][iSpan] = 0.0; - ExtAverageOmega[iMarker][iSpan] = 0.0; - - for (iDim = 0; iDim < nDim; iDim++) { - AverageVelocity[iMarker][iSpan][iDim] = 0.0; - AverageTurboVelocity[iMarker][iSpan][iDim] = 0.0; - OldAverageTurboVelocity[iMarker][iSpan][iDim] = 0.0; - ExtAverageTurboVelocity[iMarker][iSpan][iDim] = 0.0; - } - - for (iVar = 0; iVar < nVar; iVar++) { - AverageFlux[iMarker][iSpan][iVar] = 0.0; - SpanTotalFlux[iMarker][iSpan][iVar] = 0.0; - } + AverageVelocity[iMarker][iSpan] = new su2double [nDim](); + AverageTurboVelocity[iMarker][iSpan] = new su2double [nDim](); + OldAverageTurboVelocity[iMarker][iSpan] = new su2double [nDim](); + ExtAverageTurboVelocity[iMarker][iSpan] = new su2double [nDim](); + AverageFlux[iMarker][iSpan] = new su2double [nVar](); + SpanTotalFlux[iMarker][iSpan] = new su2double [nVar](); } } - /*--- Initialize primitive quantities for turboperformace ---*/ nMarkerTurboPerf = config->GetnMarker_TurboPerformance(); @@ -1462,40 +999,23 @@ void CEulerSolver::InitTurboContainers(CGeometry *geometry, CConfig *config){ OmegaOut = new su2double*[nMarkerTurboPerf]; NuOut = new su2double*[nMarkerTurboPerf]; - for (iMarker = 0; iMarker < nMarkerTurboPerf; iMarker++){ - DensityIn[iMarker] = new su2double [nSpanMax + 1]; - PressureIn[iMarker] = new su2double [nSpanMax + 1]; - TurboVelocityIn[iMarker] = new su2double*[nSpanMax + 1]; - DensityOut[iMarker] = new su2double [nSpanMax + 1]; - PressureOut[iMarker] = new su2double [nSpanMax + 1]; - TurboVelocityOut[iMarker] = new su2double*[nSpanMax + 1]; - KineIn[iMarker] = new su2double [nSpanMax + 1]; - OmegaIn[iMarker] = new su2double [nSpanMax + 1]; - NuIn[iMarker] = new su2double [nSpanMax + 1]; - KineOut[iMarker] = new su2double [nSpanMax + 1]; - OmegaOut[iMarker] = new su2double [nSpanMax + 1]; - NuOut[iMarker] = new su2double [nSpanMax + 1]; - + for (iMarker = 0; iMarker < nMarkerTurboPerf; iMarker++) { + DensityIn[iMarker] = new su2double [nSpanMax + 1](); + PressureIn[iMarker] = new su2double [nSpanMax + 1](); + TurboVelocityIn[iMarker] = new su2double*[nSpanMax + 1](); + DensityOut[iMarker] = new su2double [nSpanMax + 1](); + PressureOut[iMarker] = new su2double [nSpanMax + 1](); + TurboVelocityOut[iMarker] = new su2double*[nSpanMax + 1](); + KineIn[iMarker] = new su2double [nSpanMax + 1](); + OmegaIn[iMarker] = new su2double [nSpanMax + 1](); + NuIn[iMarker] = new su2double [nSpanMax + 1](); + KineOut[iMarker] = new su2double [nSpanMax + 1](); + OmegaOut[iMarker] = new su2double [nSpanMax + 1](); + NuOut[iMarker] = new su2double [nSpanMax + 1](); - - for (iSpan = 0; iSpan < nSpanMax + 1; iSpan++){ - DensityIn[iMarker][iSpan] = 0.0; - PressureIn[iMarker][iSpan] = 0.0; - TurboVelocityIn[iMarker][iSpan] = new su2double[nDim]; - DensityOut[iMarker][iSpan] = 0.0; - PressureOut[iMarker][iSpan] = 0.0; - TurboVelocityOut [iMarker][iSpan] = new su2double[nDim]; - KineIn[iMarker][iSpan] = 0.0; - OmegaIn[iMarker][iSpan] = 0.0; - NuIn[iMarker][iSpan] = 0.0; - KineOut[iMarker][iSpan] = 0.0; - OmegaOut[iMarker][iSpan] = 0.0; - NuOut[iMarker][iSpan] = 0.0; - - for (iDim = 0; iDim < nDim; iDim++){ - TurboVelocityIn [iMarker][iSpan][iDim] = 0.0; - TurboVelocityOut [iMarker][iSpan][iDim] = 0.0; - } + for (iSpan = 0; iSpan < nSpanMax + 1; iSpan++) { + TurboVelocityIn[iMarker][iSpan] = new su2double[nDim](); + TurboVelocityOut [iMarker][iSpan] = new su2double[nDim](); } } @@ -1541,7 +1061,7 @@ void CEulerSolver::Set_MPI_ActDisk(CSolver **solver_container, CGeometry *geomet unsigned short iVar, iMarker, jMarker; long nDomain = 0, iDomain, jDomain; //bool ActDisk_Perimeter; - bool rans = (config->GetKind_Turb_Model() != NONE); + bool rans = (config->GetKind_Turb_Model() != NONE) && (solver_container[TURB_SOL] != nullptr); unsigned short nPrimVar_ = nPrimVar; if (rans) nPrimVar_ += 2; // Add two extra variables for the turbulence. @@ -1905,15 +1425,14 @@ void CEulerSolver::Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) { unsigned long *nPointTotal_s = new unsigned long[size]; unsigned long *nPointTotal_r = new unsigned long[size]; - su2double *iPrimVar = new su2double [nPrimVar]; - - unsigned long Buffer_Size_PrimVar = 0; + su2double *iPrimVar = new su2double [nPrimVar]; + unsigned long Buffer_Size_PrimVar = 0; unsigned long PointTotal_Counter = 0; /*--- Allocate the memory that we only need if we have MPI support ---*/ - su2double *Buffer_Receive_PrimVar = NULL; + su2double* Buffer_Receive_PrimVar = NULL; /*--- Basic dimensionalization ---*/ @@ -1950,13 +1469,13 @@ void CEulerSolver::Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) { /*--- Total counts for allocating send buffers below ---*/ - Buffer_Size_PrimVar += nPointTotal_s[iDomain]*(nPrimVar+3); + Buffer_Size_PrimVar += nPointTotal_s[iDomain]*(nPrimVar+3); } /*--- Allocate the buffer vectors in the appropiate domain (master, iDomain) ---*/ - Buffer_Send_PrimVar = new su2double[Buffer_Size_PrimVar]; + Buffer_Send_PrimVar = new su2double[Buffer_Size_PrimVar]; /*--- Now that we know the sizes of the point, we can allocate and send the information in large chunks to all processors. ---*/ @@ -2044,9 +1563,9 @@ void CEulerSolver::Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) { for (iVar = 0; iVar < nPrimVar; iVar++) { Buffer_Send_PrimVar[(nPrimVar+3)*(PointTotal_Counter+iPointTotal)+iVar] = nodes->GetPrimitive(iPoint,iVar); } - Buffer_Send_PrimVar[(nPrimVar+3)*(PointTotal_Counter+iPointTotal)+(nPrimVar+0)] = su2double(iGlobalIndex); + Buffer_Send_PrimVar[(nPrimVar+3)*(PointTotal_Counter+iPointTotal)+(nPrimVar+0)] = su2double(iGlobalIndex); Buffer_Send_PrimVar[(nPrimVar+3)*(PointTotal_Counter+iPointTotal)+(nPrimVar+1)] = su2double(jVertex); - Buffer_Send_PrimVar[(nPrimVar+3)*(PointTotal_Counter+iPointTotal)+(nPrimVar+2)] = su2double(jMarker); + Buffer_Send_PrimVar[(nPrimVar+3)*(PointTotal_Counter+iPointTotal)+(nPrimVar+2)] = su2double(jMarker); iPointTotal++; @@ -2079,7 +1598,7 @@ void CEulerSolver::Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) { /*--- Allocate local memory for the local recv of the elements ---*/ - Buffer_Receive_PrimVar = new su2double[nPointTotal_s[iDomain]*(nPrimVar+3)]; + Buffer_Receive_PrimVar = new su2double[nPointTotal_s[iDomain]*(nPrimVar+3)]; for (iter = 0; iter < nPointTotal_s[iDomain]*(nPrimVar+3); iter++) Buffer_Receive_PrimVar[iter] = Buffer_Send_PrimVar[PointTotal_Counter*(nPrimVar+3)+iter]; @@ -2088,8 +1607,8 @@ void CEulerSolver::Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) { for (iPoint = 0; iPoint < nPointTotal_r[iDomain]; iPoint++) { - iGlobal = SU2_TYPE::Int(Buffer_Receive_PrimVar[iPoint*(nPrimVar+3)+(nPrimVar+0)]); - iVertex = SU2_TYPE::Int(Buffer_Receive_PrimVar[iPoint*(nPrimVar+3)+(nPrimVar+1)]); + iGlobal = SU2_TYPE::Int(Buffer_Receive_PrimVar[iPoint*(nPrimVar+3)+(nPrimVar+0)]); + iVertex = SU2_TYPE::Int(Buffer_Receive_PrimVar[iPoint*(nPrimVar+3)+(nPrimVar+1)]); iMarker = SU2_TYPE::Int(Buffer_Receive_PrimVar[iPoint*(nPrimVar+3)+(nPrimVar+2)]); for (iVar = 0; iVar < nPrimVar; iVar++) iPrimVar[iVar] = Buffer_Receive_PrimVar[iPoint*(nPrimVar+3)+iVar]; @@ -2140,7 +1659,7 @@ void CEulerSolver::Set_MPI_Nearfield(CGeometry *geometry, CConfig *config) { /*--- Allocate the receive buffer vector. Send the colors so that we know whether what we recv is an owned or halo node. ---*/ - Buffer_Receive_PrimVar = new su2double [nPointTotal_r[iDomain]*(nPrimVar+3)]; + Buffer_Receive_PrimVar = new su2double [nPointTotal_r[iDomain]*(nPrimVar+3)]; /*--- Receive the buffers with the coords, global index, and colors ---*/ @@ -2220,10 +1739,10 @@ void CEulerSolver::SetNondimensionalization(CConfig *config, unsigned short iMes /*--- Local variables ---*/ - su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; - su2double Beta = config->GetAoS()*PI_NUMBER/180.0; - su2double Mach = config->GetMach(); - su2double Reynolds = config->GetReynolds(); + su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; + su2double Beta = config->GetAoS()*PI_NUMBER/180.0; + su2double Mach = config->GetMach(); + su2double Reynolds = config->GetReynolds(); bool unsteady = (config->GetTime_Marching() != NO); bool viscous = config->GetViscous(); bool gravity = config->GetGravityForce(); @@ -2249,82 +1768,61 @@ void CEulerSolver::SetNondimensionalization(CConfig *config, unsigned short iMes Pressure_FreeStream = config->GetPressure_FreeStream(); Density_FreeStream = config->GetDensity_FreeStream(); - Temperature_FreeStream = config->GetTemperature_FreeStream(); + Temperature_FreeStream = config->GetTemperature_FreeStream(); + + CFluidModel* auxFluidModel = nullptr; switch (config->GetKind_FluidModel()) { case STANDARD_AIR: - if (config->GetSystemMeasurements() == SI) config->SetGas_Constant(287.058); - else if (config->GetSystemMeasurements() == US) config->SetGas_Constant(1716.49); - - FluidModel = new CIdealGas(1.4, config->GetGas_Constant()); - if (free_stream_temp) { - if (aeroelastic) { - Temperature_FreeStream = TgammaR / (config->GetGas_Constant()*1.4); - config->SetTemperature_FreeStream(Temperature_FreeStream); - } - FluidModel->SetTDState_PT(Pressure_FreeStream, Temperature_FreeStream); - Density_FreeStream = FluidModel->GetDensity(); - config->SetDensity_FreeStream(Density_FreeStream); + switch (config->GetSystemMeasurements()) { + case SI: config->SetGas_Constant(287.058); break; + case US: config->SetGas_Constant(1716.49); break; } - else { - FluidModel->SetTDState_Prho(Pressure_FreeStream, Density_FreeStream ); - Temperature_FreeStream = FluidModel->GetTemperature(); + + auxFluidModel = new CIdealGas(1.4, config->GetGas_Constant()); + + if (free_stream_temp && aeroelastic) { + Temperature_FreeStream = TgammaR / (config->GetGas_Constant()*1.4); config->SetTemperature_FreeStream(Temperature_FreeStream); } break; case IDEAL_GAS: - FluidModel = new CIdealGas(Gamma, config->GetGas_Constant()); - if (free_stream_temp) { - FluidModel->SetTDState_PT(Pressure_FreeStream, Temperature_FreeStream); - Density_FreeStream = FluidModel->GetDensity(); - config->SetDensity_FreeStream(Density_FreeStream); - } - else { - FluidModel->SetTDState_Prho(Pressure_FreeStream, Density_FreeStream ); - Temperature_FreeStream = FluidModel->GetTemperature(); - config->SetTemperature_FreeStream(Temperature_FreeStream); - } + auxFluidModel = new CIdealGas(Gamma, config->GetGas_Constant()); break; case VW_GAS: - FluidModel = new CVanDerWaalsGas(Gamma, config->GetGas_Constant(), - config->GetPressure_Critical(), config->GetTemperature_Critical()); - if (free_stream_temp) { - FluidModel->SetTDState_PT(Pressure_FreeStream, Temperature_FreeStream); - Density_FreeStream = FluidModel->GetDensity(); - config->SetDensity_FreeStream(Density_FreeStream); - } - else { - FluidModel->SetTDState_Prho(Pressure_FreeStream, Density_FreeStream ); - Temperature_FreeStream = FluidModel->GetTemperature(); - config->SetTemperature_FreeStream(Temperature_FreeStream); - } + auxFluidModel = new CVanDerWaalsGas(Gamma, config->GetGas_Constant(), + config->GetPressure_Critical(), config->GetTemperature_Critical()); break; case PR_GAS: - FluidModel = new CPengRobinson(Gamma, config->GetGas_Constant(), config->GetPressure_Critical(), - config->GetTemperature_Critical(), config->GetAcentric_Factor()); - if (free_stream_temp) { - FluidModel->SetTDState_PT(Pressure_FreeStream, Temperature_FreeStream); - Density_FreeStream = FluidModel->GetDensity(); - config->SetDensity_FreeStream(Density_FreeStream); - } - else { - FluidModel->SetTDState_Prho(Pressure_FreeStream, Density_FreeStream ); - Temperature_FreeStream = FluidModel->GetTemperature(); - config->SetTemperature_FreeStream(Temperature_FreeStream); - } + auxFluidModel = new CPengRobinson(Gamma, config->GetGas_Constant(), config->GetPressure_Critical(), + config->GetTemperature_Critical(), config->GetAcentric_Factor()); + break; + + default: + SU2_MPI::Error("Unknown fluid model.", CURRENT_FUNCTION); break; + } + if (free_stream_temp) { + auxFluidModel->SetTDState_PT(Pressure_FreeStream, Temperature_FreeStream); + Density_FreeStream = auxFluidModel->GetDensity(); + config->SetDensity_FreeStream(Density_FreeStream); + } + else { + auxFluidModel->SetTDState_Prho(Pressure_FreeStream, Density_FreeStream ); + Temperature_FreeStream = auxFluidModel->GetTemperature(); + config->SetTemperature_FreeStream(Temperature_FreeStream); } - Mach2Vel_FreeStream = FluidModel->GetSoundSpeed(); + Mach2Vel_FreeStream = auxFluidModel->GetSoundSpeed(); /*--- Compute the Free Stream velocity, using the Mach number ---*/ @@ -2373,17 +1871,17 @@ void CEulerSolver::SetNondimensionalization(CConfig *config, unsigned short iMes from the dimensional version of Sutherland's law or the constant viscosity, depending on the input option.---*/ - FluidModel->SetLaminarViscosityModel(config); + auxFluidModel->SetLaminarViscosityModel(config); - Viscosity_FreeStream = FluidModel->GetLaminarViscosity(); + Viscosity_FreeStream = auxFluidModel->GetLaminarViscosity(); config->SetViscosity_FreeStream(Viscosity_FreeStream); Density_FreeStream = Reynolds*Viscosity_FreeStream/(Velocity_Reynolds*config->GetLength_Reynolds()); config->SetDensity_FreeStream(Density_FreeStream); - FluidModel->SetTDState_rhoT(Density_FreeStream, Temperature_FreeStream); - Pressure_FreeStream = FluidModel->GetPressure(); + auxFluidModel->SetTDState_rhoT(Density_FreeStream, Temperature_FreeStream); + Pressure_FreeStream = auxFluidModel->GetPressure(); config->SetPressure_FreeStream(Pressure_FreeStream); - Energy_FreeStream = FluidModel->GetStaticEnergy() + 0.5*ModVel_FreeStream*ModVel_FreeStream; + Energy_FreeStream = auxFluidModel->GetStaticEnergy() + 0.5*ModVel_FreeStream*ModVel_FreeStream; } @@ -2391,10 +1889,10 @@ void CEulerSolver::SetNondimensionalization(CConfig *config, unsigned short iMes else { - FluidModel->SetLaminarViscosityModel(config); - Viscosity_FreeStream = FluidModel->GetLaminarViscosity(); + auxFluidModel->SetLaminarViscosityModel(config); + Viscosity_FreeStream = auxFluidModel->GetLaminarViscosity(); config->SetViscosity_FreeStream(Viscosity_FreeStream); - Energy_FreeStream = FluidModel->GetStaticEnergy() + 0.5*ModVel_FreeStream*ModVel_FreeStream; + Energy_FreeStream = auxFluidModel->GetStaticEnergy() + 0.5*ModVel_FreeStream*ModVel_FreeStream; } @@ -2408,7 +1906,7 @@ void CEulerSolver::SetNondimensionalization(CConfig *config, unsigned short iMes /*--- For inviscid flow, energy is calculated from the specified FreeStream quantities using the proper gas law. ---*/ - Energy_FreeStream = FluidModel->GetStaticEnergy() + 0.5*ModVel_FreeStream*ModVel_FreeStream; + Energy_FreeStream = auxFluidModel->GetStaticEnergy() + 0.5*ModVel_FreeStream*ModVel_FreeStream; } @@ -2488,58 +1986,71 @@ void CEulerSolver::SetNondimensionalization(CConfig *config, unsigned short iMes /*--- Initialize the dimensionless Fluid Model that will be used to solve the dimensionless problem ---*/ - /*--- Delete the original (dimensional) FluidModel object before replacing. ---*/ + /*--- Auxilary (dimensional) FluidModel no longer needed. ---*/ + delete auxFluidModel; - delete FluidModel; + /*--- Set viscosity ND constants before defining the visc. model of the fluid models. ---*/ - switch (config->GetKind_FluidModel()) { + if (viscous) { + /*--- Constant viscosity model. ---*/ + config->SetMu_ConstantND(config->GetMu_Constant()/Viscosity_Ref); - case STANDARD_AIR: - FluidModel = new CIdealGas(1.4, Gas_ConstantND); - FluidModel->SetEnergy_Prho(Pressure_FreeStreamND, Density_FreeStreamND); - break; + /*--- Sutherland's model. ---*/ + config->SetMu_RefND(config->GetMu_Ref()/Viscosity_Ref); + config->SetMu_SND(config->GetMu_S()/config->GetTemperature_Ref()); + config->SetMu_Temperature_RefND(config->GetMu_Temperature_Ref()/config->GetTemperature_Ref()); - case IDEAL_GAS: - FluidModel = new CIdealGas(Gamma, Gas_ConstantND); - FluidModel->SetEnergy_Prho(Pressure_FreeStreamND, Density_FreeStreamND); - break; + /*--- Constant thermal conductivity model. ---*/ + config->SetKt_ConstantND(config->GetKt_Constant()/Conductivity_Ref); + } - case VW_GAS: - FluidModel = new CVanDerWaalsGas(Gamma, Gas_ConstantND, config->GetPressure_Critical() /config->GetPressure_Ref(), - config->GetTemperature_Critical()/config->GetTemperature_Ref()); - FluidModel->SetEnergy_Prho(Pressure_FreeStreamND, Density_FreeStreamND); - break; + /*--- Create one final fluid model object per OpenMP thread to be able to use them in parallel. + * GetFluidModel() should be used to automatically access the "right" object of each thread. ---*/ - case PR_GAS: - FluidModel = new CPengRobinson(Gamma, Gas_ConstantND, config->GetPressure_Critical() /config->GetPressure_Ref(), - config->GetTemperature_Critical()/config->GetTemperature_Ref(), config->GetAcentric_Factor()); - FluidModel->SetEnergy_Prho(Pressure_FreeStreamND, Density_FreeStreamND); - break; + assert(FluidModel.empty() && "Potential memory leak!"); + FluidModel.resize(omp_get_max_threads()); - } + SU2_OMP_PARALLEL + { + const int thread = omp_get_thread_num(); - Energy_FreeStreamND = FluidModel->GetStaticEnergy() + 0.5*ModVel_FreeStreamND*ModVel_FreeStreamND; + switch (config->GetKind_FluidModel()) { - if (viscous) { + case STANDARD_AIR: + FluidModel[thread] = new CIdealGas(1.4, Gas_ConstantND); + break; - /*--- Constant viscosity model ---*/ - config->SetMu_ConstantND(config->GetMu_Constant()/Viscosity_Ref); + case IDEAL_GAS: + FluidModel[thread] = new CIdealGas(Gamma, Gas_ConstantND); + break; - /*--- Sutherland's model ---*/ + case VW_GAS: + FluidModel[thread] = new CVanDerWaalsGas(Gamma, Gas_ConstantND, + config->GetPressure_Critical() / config->GetPressure_Ref(), + config->GetTemperature_Critical() / config->GetTemperature_Ref()); + break; - config->SetMu_RefND(config->GetMu_Ref()/Viscosity_Ref); - config->SetMu_SND(config->GetMu_S()/config->GetTemperature_Ref()); - config->SetMu_Temperature_RefND(config->GetMu_Temperature_Ref()/config->GetTemperature_Ref()); + case PR_GAS: + FluidModel[thread] = new CPengRobinson(Gamma, Gas_ConstantND, + config->GetPressure_Critical() / config->GetPressure_Ref(), + config->GetTemperature_Critical() / config->GetTemperature_Ref(), + config->GetAcentric_Factor()); + break; + } - /* constant thermal conductivity model */ - config->SetKt_ConstantND(config->GetKt_Constant()/Conductivity_Ref); + GetFluidModel()->SetEnergy_Prho(Pressure_FreeStreamND, Density_FreeStreamND); + if (viscous) { + GetFluidModel()->SetLaminarViscosityModel(config); + GetFluidModel()->SetThermalConductivityModel(config); + } - FluidModel->SetLaminarViscosityModel(config); - FluidModel->SetThermalConductivityModel(config); + } // end SU2_OMP_PARALLEL - } + Energy_FreeStreamND = GetFluidModel()->GetStaticEnergy() + 0.5*ModVel_FreeStreamND*ModVel_FreeStreamND; + + if (tkeNeeded) Energy_FreeStreamND += Tke_FreeStreamND; - if (tkeNeeded) { Energy_FreeStreamND += Tke_FreeStreamND; }; config->SetEnergy_FreeStreamND(Energy_FreeStreamND); + config->SetEnergy_FreeStreamND(Energy_FreeStreamND); Energy_Ref = Energy_FreeStream/Energy_FreeStreamND; config->SetEnergy_Ref(Energy_Ref); @@ -2758,26 +2269,31 @@ void CEulerSolver::SetNondimensionalization(CConfig *config, unsigned short iMes void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_container, CConfig *config, unsigned long TimeIter) { + 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)); + const bool SubsonicEngine = config->GetSubsonicEngine(); + + /*--- Start OpenMP parallel region. ---*/ + + SU2_OMP_PARALLEL + { + unsigned long iPoint; unsigned short iMesh, iDim; su2double X0[3] = {0.0,0.0,0.0}, X1[3] = {0.0,0.0,0.0}, X2[3] = {0.0,0.0,0.0}, X1_X0[3] = {0.0,0.0,0.0}, X2_X0[3] = {0.0,0.0,0.0}, X2_X1[3] = {0.0,0.0,0.0}, CP[3] = {0.0,0.0,0.0}, Distance, DotCheck, Radius; - unsigned short nDim = geometry[MESH_0]->GetnDim(); - bool restart = (config->GetRestart() || config->GetRestart_Flow()); - bool rans = (config->GetKind_Turb_Model() != NONE); - bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || - (config->GetTime_Marching() == DT_STEPPING_2ND)); - bool SubsonicEngine = config->GetSubsonicEngine(); - /*--- Check if a verification solution is to be computed. ---*/ - if ((VerificationSolution) && (TimeIter == 0) && !restart) { + if ((VerificationSolution) && (TimeIter == 0) && !restart) { /*--- Loop over the multigrid levels. ---*/ for (iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { /*--- Loop over all grid points. ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < geometry[iMesh]->GetnPoint(); iPoint++) { /* Set the pointers to the coordinates and solution of this DOF. */ @@ -2803,7 +2319,8 @@ void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_c su2double Velocity_Cyl[3] = {0.0, 0.0, 0.0}, Velocity_CylND[3] = {0.0, 0.0, 0.0}, Viscosity_Cyl, Density_Cyl, Density_CylND, Pressure_CylND, ModVel_Cyl, ModVel_CylND, Energy_CylND, - T_ref = 0.0, S = 0.0, Mu_ref = 0.0, *Coord, *SubsonicEngine_Cyl, *SubsonicEngine_Values; + T_ref = 0.0, S = 0.0, Mu_ref = 0.0; + const su2double *Coord, *SubsonicEngine_Cyl, *SubsonicEngine_Values; SubsonicEngine_Values = config->GetSubsonicEngine_Values(); su2double Mach_Cyl = SubsonicEngine_Values[0]; @@ -2822,6 +2339,7 @@ void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_c for (iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { + SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < geometry[iMesh]->GetnPoint(); iPoint++) { Velocity_Cyl[0] = cos(Alpha)*cos(Beta)*Mach_Cyl*Mach2Vel_Cyl; @@ -2868,9 +2386,9 @@ void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_c SubsonicEngine_Cyl = config->GetSubsonicEngine_Cyl(); - X0[0] = Coord[0]; X0[1] = Coord[1]; X0[2] = Coord[2]; - X1[0] = SubsonicEngine_Cyl[0]; X1[1] = SubsonicEngine_Cyl[1]; X1[2] = SubsonicEngine_Cyl[2]; - X2[0] = SubsonicEngine_Cyl[3]; X2[1] = SubsonicEngine_Cyl[4]; X2[2] = SubsonicEngine_Cyl[5]; + X0[0] = Coord[0]; X0[1] = Coord[1]; X0[2] = Coord[2]; + X1[0] = SubsonicEngine_Cyl[0]; X1[1] = SubsonicEngine_Cyl[1]; X1[2] = SubsonicEngine_Cyl[2]; + X2[0] = SubsonicEngine_Cyl[3]; X2[1] = SubsonicEngine_Cyl[4]; X2[2] = SubsonicEngine_Cyl[5]; Radius = SubsonicEngine_Cyl[6]; for (iDim = 0; iDim < nDim; iDim++) { @@ -2909,11 +2427,15 @@ void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_c /*--- Set the MPI communication ---*/ - solver_container[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION); - solver_container[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION); + SU2_OMP_MASTER + { + solver_container[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION); + solver_container[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION); - solver_container[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION_OLD); - solver_container[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION_OLD); + solver_container[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION_OLD); + solver_container[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION_OLD); + } + SU2_OMP_BARRIER } @@ -2924,12 +2446,12 @@ void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_c /*--- Make sure that the solution is well initialized for unsteady calculations with dual time-stepping (load additional restarts for 2nd-order). ---*/ - if (dual_time && (TimeIter == 0 || (restart && (long)TimeIter == (long)config->GetRestart_Iter()))) { + 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 (iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { + 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) { @@ -2938,20 +2460,23 @@ void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_c } } - if ((restart && (long)TimeIter == (long)config->GetRestart_Iter()) && - (config->GetTime_Marching() == DT_STEPPING_2ND)) { + if (restart && (TimeIter == config->GetRestart_Iter()) && (config->GetTime_Marching() == DT_STEPPING_2ND)) { - /*--- Load an additional restart file for a 2nd-order restart ---*/ + SU2_OMP_MASTER + { + /*--- 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); + 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, SU2_TYPE::Int(config->GetRestart_Iter()-1), false); + /*--- 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); + } + SU2_OMP_BARRIER /*--- Push back this new solution to time level N. ---*/ - for (iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) { + 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(); @@ -2960,11 +2485,12 @@ void CEulerSolver::SetInitialCondition(CGeometry **geometry, CSolver ***solver_c } } -} + } // end SU2_OMP_PARALLEL -void CEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { +} - unsigned long ErrorCounter = 0; +void CEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, + unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { unsigned long InnerIter = config->GetInnerIter(); bool cont_adjoint = config->GetContinuous_Adjoint(); @@ -2987,28 +2513,59 @@ void CEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container /*--- Update the angle of attack at the far-field for fixed CL calculations (only direct problem). ---*/ - if ((fixed_cl) && (!disc_adjoint) && (!cont_adjoint)) { SetFarfield_AoA(geometry, solver_container, config, iMesh, Output); } + if (fixed_cl && !disc_adjoint && !cont_adjoint) { + SU2_OMP_MASTER + SetFarfield_AoA(geometry, solver_container, config, iMesh, Output); + SU2_OMP_BARRIER + } /*--- Set the primitive variables ---*/ - ErrorCounter = SetPrimitive_Variables(solver_container, config, Output); + SU2_OMP_MASTER + ErrorCounter = 0; + SU2_OMP_BARRIER + + SU2_OMP_ATOMIC + ErrorCounter += SetPrimitive_Variables(solver_container, config, Output); + + if ((iMesh == MESH_0) && (config->GetComm_Level() == COMM_FULL)) { + SU2_OMP_BARRIER + SU2_OMP_MASTER + { + unsigned long tmp = ErrorCounter; + SU2_MPI::Allreduce(&tmp, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); + config->SetNonphysical_Points(ErrorCounter); + } + SU2_OMP_BARRIER + } /*--- Compute the engine properties ---*/ - if (engine) { GetPower_Properties(geometry, config, iMesh, Output); } + if (engine) { + SU2_OMP_MASTER + GetPower_Properties(geometry, config, iMesh, Output); + SU2_OMP_BARRIER + } /*--- Compute the actuator disk properties and distortion levels ---*/ if (actuator_disk) { - Set_MPI_ActDisk(solver_container, geometry, config); - GetPower_Properties(geometry, config, iMesh, Output); - SetActDisk_BCThrust(geometry, solver_container, config, iMesh, Output); + SU2_OMP_MASTER + { + Set_MPI_ActDisk(solver_container, geometry, config); + GetPower_Properties(geometry, config, iMesh, Output); + SetActDisk_BCThrust(geometry, solver_container, config, iMesh, Output); + } + SU2_OMP_BARRIER } /*--- Compute NearField MPI ---*/ - if (nearfield) { Set_MPI_Nearfield(geometry, config); } - + if (nearfield) { + SU2_OMP_MASTER + Set_MPI_Nearfield(geometry, config); + SU2_OMP_BARRIER + } /*--- Upwind second order reconstruction ---*/ @@ -3025,9 +2582,8 @@ void CEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container /*--- Limiter computation ---*/ - if (limiter && (iMesh == MESH_0) - && !Output && !van_albada) { SetPrimitive_Limiter(geometry, config); } - + if (limiter && (iMesh == MESH_0) && !Output && !van_albada) + SetPrimitive_Limiter(geometry, config); } /*--- Artificial dissipation ---*/ @@ -3042,7 +2598,7 @@ void CEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container /*--- Roe Low Dissipation Sensor ---*/ - if (roe_low_dissipation){ + if (roe_low_dissipation) { SetRoe_Dissipation(geometry, config); if (kind_row_dissipation == FD_DUCROS || kind_row_dissipation == NTS_DUCROS){ SetUpwind_Ducros_Sensor(geometry, config); @@ -3053,32 +2609,21 @@ void CEulerSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container if (implicit && !disc_adjoint) Jacobian.SetValZero(); - /*--- Error message ---*/ - - if (config->GetComm_Level() == COMM_FULL) { -#ifdef HAVE_MPI - unsigned long MyErrorCounter = ErrorCounter; ErrorCounter = 0; - SU2_MPI::Allreduce(&MyErrorCounter, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); -#endif - if (iMesh == MESH_0) config->SetNonphysical_Points(ErrorCounter); - } - } -void CEulerSolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, - unsigned short iMesh) { } - unsigned long CEulerSolver::SetPrimitive_Variables(CSolver **solver_container, CConfig *config, bool Output) { - unsigned long iPoint, nonPhysicalPoints = 0; - bool physical = true; + /*--- Number of non-physical points, local to the thread, needs + * further reduction if function is called in parallel ---*/ + unsigned long nonPhysicalPoints = 0; - for (iPoint = 0; iPoint < nPoint; iPoint ++) { + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { /*--- Compressible flow, primitive variables nDim+5, (T, vx, vy, vz, P, rho, h, c, lamMu, eddyMu, ThCond, Cp) ---*/ - physical = nodes->SetPrimVar(iPoint, FluidModel); - nodes->SetSecondaryVar(iPoint, FluidModel); + bool physical = nodes->SetPrimVar(iPoint, GetFluidModel()); + nodes->SetSecondaryVar(iPoint, GetFluidModel()); /* Check for non-realizable states for reporting. */ @@ -3092,60 +2637,95 @@ unsigned long CEulerSolver::SetPrimitive_Variables(CSolver **solver_container, C return nonPhysicalPoints; } + void CEulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned long Iteration) { - su2double *Normal, Area, Vol, Mean_SoundSpeed = 0.0, Mean_ProjVel = 0.0, Lambda, Local_Delta_Time, - Global_Delta_Time = 1E6, Global_Delta_UnstTimeND, ProjVel, ProjVel_i, ProjVel_j; + const bool viscous = config->GetViscous(); + const bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + const bool time_stepping = (config->GetTime_Marching() == TIME_STEPPING); + const bool dual_time = (config->GetTime_Marching() == DT_STEPPING_1ST) || + (config->GetTime_Marching() == DT_STEPPING_2ND); + const su2double K_v = 0.25; + + /*--- Init thread-shared variables to compute min/max values. + * Critical sections are used for this instead of reduction + * clauses for compatibility with OpenMP 2.0 (Windows...). ---*/ + + SU2_OMP_MASTER + { + Min_Delta_Time = 1e30; + Max_Delta_Time = 0.0; + Global_Delta_UnstTimeND = 1e30; + } + SU2_OMP_BARRIER + + const su2double *Normal = nullptr; + su2double Area, Vol, Mean_SoundSpeed, Mean_ProjVel, Lambda, Local_Delta_Time, Local_Delta_Time_Visc; + su2double Mean_LaminarVisc, Mean_EddyVisc, Mean_Density, Lambda_1, Lambda_2; unsigned long iEdge, iVertex, iPoint, jPoint; unsigned short iDim, iMarker; - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - bool time_stepping = config->GetTime_Marching() == TIME_STEPPING; - bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || - (config->GetTime_Marching() == DT_STEPPING_2ND)); + /*--- Loop domain points. ---*/ - Min_Delta_Time = 1.E30; Max_Delta_Time = 0.0; + SU2_OMP_FOR_DYN(omp_chunk_size) + for (iPoint = 0; iPoint < nPointDomain; ++iPoint) { - /*--- Set maximum inviscid eigenvalue to zero, and compute sound speed ---*/ + auto node_i = geometry->node[iPoint]; + + /*--- Set maximum eigenvalues to zero. ---*/ - for (iPoint = 0; iPoint < nPointDomain; iPoint++) nodes->SetMax_Lambda_Inv(iPoint,0.0); - /*--- Loop interior edges ---*/ - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { + if (viscous) + nodes->SetMax_Lambda_Visc(iPoint,0.0); - /*--- Point identification, Normal vector and area ---*/ + /*--- Loop over the neighbors of point i. ---*/ - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); + for (unsigned short iNeigh = 0; iNeigh < node_i->GetnPoint(); ++iNeigh) + { + jPoint = node_i->GetPoint(iNeigh); + auto node_j = geometry->node[jPoint]; - Normal = geometry->edge[iEdge]->GetNormal(); - Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); + iEdge = node_i->GetEdge(iNeigh); + Normal = geometry->edge[iEdge]->GetNormal(); + Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += pow(Normal[iDim],2); Area = sqrt(Area); - /*--- Mean Values ---*/ + /*--- Mean Values ---*/ - Mean_ProjVel = 0.5 * (nodes->GetProjVel(iPoint,Normal) + nodes->GetProjVel(jPoint,Normal)); - Mean_SoundSpeed = 0.5 * (nodes->GetSoundSpeed(iPoint) + nodes->GetSoundSpeed(jPoint)) * Area; + Mean_ProjVel = 0.5 * (nodes->GetProjVel(iPoint,Normal) + nodes->GetProjVel(jPoint,Normal)); + Mean_SoundSpeed = 0.5 * (nodes->GetSoundSpeed(iPoint) + nodes->GetSoundSpeed(jPoint)) * Area; - /*--- Adjustment for grid movement ---*/ + /*--- Adjustment for grid movement ---*/ - if (dynamic_grid) { - su2double *GridVel_i = geometry->node[iPoint]->GetGridVel(); - su2double *GridVel_j = geometry->node[jPoint]->GetGridVel(); - ProjVel_i = 0.0; ProjVel_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjVel_i += GridVel_i[iDim]*Normal[iDim]; - ProjVel_j += GridVel_j[iDim]*Normal[iDim]; + if (dynamic_grid) { + const su2double *GridVel_i = node_i->GetGridVel(); + const su2double *GridVel_j = node_j->GetGridVel(); + + for (iDim = 0; iDim < nDim; iDim++) + Mean_ProjVel -= 0.5 * (GridVel_i[iDim] + GridVel_j[iDim]) * Normal[iDim]; } - Mean_ProjVel -= 0.5 * (ProjVel_i + ProjVel_j); - } - /*--- Inviscid contribution ---*/ + /*--- Inviscid contribution ---*/ + + Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed ; + nodes->AddMax_Lambda_Inv(iPoint,Lambda); + + /*--- Viscous contribution ---*/ + + if (!viscous) continue; - Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed; - if (geometry->node[iPoint]->GetDomain()) nodes->AddMax_Lambda_Inv(iPoint,Lambda); - if (geometry->node[jPoint]->GetDomain()) nodes->AddMax_Lambda_Inv(jPoint,Lambda); + Mean_LaminarVisc = 0.5*(nodes->GetLaminarViscosity(iPoint) + nodes->GetLaminarViscosity(jPoint)); + Mean_EddyVisc = 0.5*(nodes->GetEddyViscosity(iPoint) + nodes->GetEddyViscosity(jPoint)); + Mean_Density = 0.5*(nodes->GetDensity(iPoint) + nodes->GetDensity(jPoint)); + + Lambda_1 = (4.0/3.0)*(Mean_LaminarVisc + Mean_EddyVisc); + //TODO (REAL_GAS) removing Gamma it cannot work with FLUIDPROP + Lambda_2 = (1.0 + (Prandtl_Lam/Prandtl_Turb)*(Mean_EddyVisc/Mean_LaminarVisc))*(Gamma*Mean_LaminarVisc/Prandtl_Lam); + + Lambda = (Lambda_1 + Lambda_2)*Area*Area/Mean_Density; + nodes->AddMax_Lambda_Visc(iPoint, Lambda); + } } @@ -3154,151 +2734,199 @@ void CEulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container, for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) { if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) { - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - /*--- Point identification, Normal vector and area ---*/ + SU2_OMP_FOR_STAT(OMP_MIN_SIZE) + for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); + /*--- Point identification, Normal vector and area ---*/ - /*--- Mean Values ---*/ + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - Mean_ProjVel = nodes->GetProjVel(iPoint,Normal); - Mean_SoundSpeed = nodes->GetSoundSpeed(iPoint) * Area; + if (!geometry->node[iPoint]->GetDomain()) continue; - /*--- Adjustment for grid movement ---*/ + Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); + Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); - if (dynamic_grid) { - su2double *GridVel = geometry->node[iPoint]->GetGridVel(); - ProjVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjVel += GridVel[iDim]*Normal[iDim]; - Mean_ProjVel -= ProjVel; - } + /*--- Mean Values ---*/ - /*--- Inviscid contribution ---*/ - Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed; - if (geometry->node[iPoint]->GetDomain()) { + Mean_ProjVel = nodes->GetProjVel(iPoint,Normal); + Mean_SoundSpeed = nodes->GetSoundSpeed(iPoint) * Area; + + /*--- Adjustment for grid movement ---*/ + + if (dynamic_grid) { + const su2double *GridVel = geometry->node[iPoint]->GetGridVel(); + + for (iDim = 0; iDim < nDim; iDim++) + Mean_ProjVel -= GridVel[iDim]*Normal[iDim]; + } + + /*--- Inviscid contribution ---*/ + + Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed; nodes->AddMax_Lambda_Inv(iPoint,Lambda); + + /*--- Viscous contribution ---*/ + + if (!viscous) continue; + + Mean_LaminarVisc = nodes->GetLaminarViscosity(iPoint); + Mean_EddyVisc = nodes->GetEddyViscosity(iPoint); + Mean_Density = nodes->GetDensity(iPoint); + + Lambda_1 = (4.0/3.0)*(Mean_LaminarVisc + Mean_EddyVisc); + Lambda_2 = (1.0 + (Prandtl_Lam/Prandtl_Turb)*(Mean_EddyVisc/Mean_LaminarVisc))*(Gamma*Mean_LaminarVisc/Prandtl_Lam); + Lambda = (Lambda_1 + Lambda_2)*Area*Area/Mean_Density; + + nodes->AddMax_Lambda_Visc(iPoint, Lambda); + } } - } } - /*--- Each element uses their own speed, steady state simulation ---*/ + /*--- Each element uses their own speed, steady state simulation. ---*/ + { + /*--- Thread-local variables for min/max reduction. ---*/ + su2double minDt = 1e30, maxDt = 0.0; - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + SU2_OMP(for schedule(static,omp_chunk_size) nowait) + for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - Vol = geometry->node[iPoint]->GetVolume(); + Vol = geometry->node[iPoint]->GetVolume(); - if (Vol != 0.0) { - Local_Delta_Time = nodes->GetLocalCFL(iPoint)*Vol / nodes->GetMax_Lambda_Inv(iPoint); - Global_Delta_Time = min(Global_Delta_Time, Local_Delta_Time); - Min_Delta_Time = min(Min_Delta_Time, Local_Delta_Time); - Max_Delta_Time = max(Max_Delta_Time, Local_Delta_Time); - if (Local_Delta_Time > config->GetMax_DeltaTime()) - Local_Delta_Time = config->GetMax_DeltaTime(); - nodes->SetDelta_Time(iPoint,Local_Delta_Time); + if (Vol != 0.0) { + Local_Delta_Time = nodes->GetLocalCFL(iPoint)*Vol / nodes->GetMax_Lambda_Inv(iPoint); + + if(viscous) { + Local_Delta_Time_Visc = nodes->GetLocalCFL(iPoint)*K_v*Vol*Vol/ nodes->GetMax_Lambda_Visc(iPoint); + Local_Delta_Time = min(Local_Delta_Time, Local_Delta_Time_Visc); + } + + minDt = min(minDt, Local_Delta_Time); + maxDt = max(maxDt, Local_Delta_Time); + + nodes->SetDelta_Time(iPoint, min(Local_Delta_Time, config->GetMax_DeltaTime())); + } + else { + nodes->SetDelta_Time(iPoint,0.0); + } } - else { - nodes->SetDelta_Time(iPoint,0.0); + /*--- Min/max over threads. ---*/ + SU2_OMP_CRITICAL + { + Min_Delta_Time = min(Min_Delta_Time, minDt); + Max_Delta_Time = max(Max_Delta_Time, maxDt); + Global_Delta_Time = Min_Delta_Time; } - + SU2_OMP_BARRIER } + /*--- Compute the min/max dt (in parallel, now over mpi ranks). ---*/ - /*--- Compute the max and the min dt (in parallel) ---*/ + SU2_OMP_MASTER if (config->GetComm_Level() == COMM_FULL) { -#ifdef HAVE_MPI - su2double rbuf_time, sbuf_time; - sbuf_time = Min_Delta_Time; - SU2_MPI::Reduce(&sbuf_time, &rbuf_time, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, MPI_COMM_WORLD); - SU2_MPI::Bcast(&rbuf_time, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); + su2double rbuf_time; + SU2_MPI::Allreduce(&Min_Delta_Time, &rbuf_time, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); Min_Delta_Time = rbuf_time; - sbuf_time = Max_Delta_Time; - SU2_MPI::Reduce(&sbuf_time, &rbuf_time, 1, MPI_DOUBLE, MPI_MAX, MASTER_NODE, MPI_COMM_WORLD); - SU2_MPI::Bcast(&rbuf_time, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); + SU2_MPI::Allreduce(&Max_Delta_Time, &rbuf_time, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); Max_Delta_Time = rbuf_time; -#endif } + SU2_OMP_BARRIER - /*--- For exact time solution use the minimum delta time of the whole mesh ---*/ - + /*--- For exact time solution use the minimum delta time of the whole mesh. ---*/ if (time_stepping) { -#ifdef HAVE_MPI - su2double rbuf_time, sbuf_time; - sbuf_time = Global_Delta_Time; - SU2_MPI::Reduce(&sbuf_time, &rbuf_time, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, MPI_COMM_WORLD); - SU2_MPI::Bcast(&rbuf_time, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); - Global_Delta_Time = rbuf_time; -#endif - /*--- If the unsteady CFL is set to zero, it uses the defined - unsteady time step, otherwise it computes the time step based - on the unsteady CFL ---*/ - if (config->GetUnst_CFL() == 0.0) { - Global_Delta_Time = config->GetDelta_UnstTime(); + /*--- If the unsteady CFL is set to zero, it uses the defined unsteady time step, + * otherwise it computes the time step based on the unsteady CFL. ---*/ + + SU2_OMP_MASTER + { + if (config->GetUnst_CFL() == 0.0) { + Global_Delta_Time = config->GetDelta_UnstTime(); + } + else { + Global_Delta_Time = Min_Delta_Time; + } + Max_Delta_Time = Global_Delta_Time; + + config->SetDelta_UnstTimeND(Global_Delta_Time); } - config->SetDelta_UnstTimeND(Global_Delta_Time); - for (iPoint = 0; iPoint < nPointDomain; iPoint++){ + SU2_OMP_BARRIER - /*--- Sets the regular CFL equal to the unsteady CFL ---*/ + /*--- Sets the regular CFL equal to the unsteady CFL. ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) + for (iPoint = 0; iPoint < nPointDomain; iPoint++) { nodes->SetLocalCFL(iPoint, config->GetUnst_CFL()); nodes->SetDelta_Time(iPoint, Global_Delta_Time); - Min_Delta_Time = Global_Delta_Time; - Max_Delta_Time = Global_Delta_Time; - } + } - /*--- Recompute the unsteady time step for the dual time strategy - if the unsteady CFL is diferent from 0 ---*/ + /*--- Recompute the unsteady time step for the dual time strategy if the unsteady CFL is diferent from 0. ---*/ if ((dual_time) && (Iteration == 0) && (config->GetUnst_CFL() != 0.0) && (iMesh == MESH_0)) { - Global_Delta_UnstTimeND = 1e30; - for (iPoint = 0; iPoint < nPointDomain; iPoint++){ - Global_Delta_UnstTimeND = min(Global_Delta_UnstTimeND,config->GetUnst_CFL()*Global_Delta_Time/nodes->GetLocalCFL(iPoint)); + /*--- Thread-local variable for reduction. ---*/ + su2double glbDtND = 1e30; + + SU2_OMP(for schedule(static,omp_chunk_size) nowait) + for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + glbDtND = min(glbDtND, config->GetUnst_CFL()*Global_Delta_Time / nodes->GetLocalCFL(iPoint)); } + SU2_OMP_CRITICAL + Global_Delta_UnstTimeND = min(Global_Delta_UnstTimeND, glbDtND); + SU2_OMP_BARRIER -#ifdef HAVE_MPI - su2double rbuf_time, sbuf_time; - sbuf_time = Global_Delta_UnstTimeND; - SU2_MPI::Reduce(&sbuf_time, &rbuf_time, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, MPI_COMM_WORLD); - SU2_MPI::Bcast(&rbuf_time, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); - Global_Delta_UnstTimeND = rbuf_time; -#endif - config->SetDelta_UnstTimeND(Global_Delta_UnstTimeND); + SU2_OMP_MASTER + { + SU2_MPI::Allreduce(&Global_Delta_UnstTimeND, &glbDtND, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); + Global_Delta_UnstTimeND = glbDtND; + + config->SetDelta_UnstTimeND(Global_Delta_UnstTimeND); + } + SU2_OMP_BARRIER } /*--- The pseudo local time (explicit integration) cannot be greater than the physical time ---*/ - if (dual_time) + if (dual_time && !implicit) { + SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - if (!implicit) { - Local_Delta_Time = min((2.0/3.0)*config->GetDelta_UnstTimeND(), nodes->GetDelta_Time(iPoint)); - nodes->SetDelta_Time(iPoint,Local_Delta_Time); - } + Local_Delta_Time = min((2.0/3.0)*config->GetDelta_UnstTimeND(), nodes->GetDelta_Time(iPoint)); + nodes->SetDelta_Time(iPoint, Local_Delta_Time); } + } } -void CEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, +void CEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { - unsigned long iEdge, iPoint, jPoint; + const bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + const bool jst_scheme = (config->GetKind_Centered_Flow() == JST) && (iMesh == MESH_0); - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - bool jst_scheme = ((config->GetKind_Centered_Flow() == JST) && (iMesh == MESH_0)); + /*--- Pick one numerics object per thread. ---*/ + CNumerics* numerics = numerics_container[CONV_TERM + omp_get_thread_num()*MAX_TERMS]; + + /*--- Determine if using the reducer strategy is necessary, see CEulerSolver::SumEdgeFluxes(). ---*/ + const bool reducer_strategy = (MGLevel != MESH_0) && (omp_get_num_threads() > 1); + + /*--- Loop over edge colors. ---*/ + for (auto color : EdgeColoring) + { + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) + for(auto k = 0ul; k < color.size; ++k) { - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { + auto iEdge = color.indices[k]; /*--- Points in edge, set normal vectors, and number of neighbors ---*/ - iPoint = geometry->edge[iEdge]->GetNode(0); jPoint = geometry->edge[iEdge]->GetNode(1); + auto iPoint = geometry->edge[iEdge]->GetNode(0); + auto jPoint = geometry->edge[iEdge]->GetNode(1); + numerics->SetNormal(geometry->edge[iEdge]->GetNormal()); numerics->SetNeighbor(geometry->node[iPoint]->GetnNeighbor(), geometry->node[jPoint]->GetnNeighbor()); @@ -3313,8 +2941,10 @@ void CEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_conta /*--- Set undivided laplacian an pressure based sensor ---*/ if (jst_scheme) { - numerics->SetUndivided_Laplacian(nodes->GetUndivided_Laplacian(iPoint), nodes->GetUndivided_Laplacian(jPoint)); - numerics->SetSensor(nodes->GetSensor(iPoint), nodes->GetSensor(jPoint)); + numerics->SetUndivided_Laplacian(nodes->GetUndivided_Laplacian(iPoint), + nodes->GetUndivided_Laplacian(jPoint)); + numerics->SetSensor(nodes->GetSensor(iPoint), + nodes->GetSensor(jPoint)); } /*--- Grid movement ---*/ @@ -3325,83 +2955,136 @@ void CEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_conta /*--- Compute residuals, and Jacobians ---*/ - numerics->ComputeResidual(Res_Conv, Jacobian_i, Jacobian_j, config); + auto residual = numerics->ComputeResidual(config); - /*--- Update convective and artificial dissipation residuals ---*/ + /*--- Update convective and artificial dissipation residuals. ---*/ - LinSysRes.AddBlock(iPoint, Res_Conv); - LinSysRes.SubtractBlock(jPoint, Res_Conv); + if (reducer_strategy) { + EdgeFluxes.SetBlock(iEdge, residual); + if (implicit) + Jacobian.UpdateBlocks(iEdge, residual.jacobian_i, residual.jacobian_j); + } + else { + LinSysRes.AddBlock(iPoint, residual); + LinSysRes.SubtractBlock(jPoint, residual); - /*--- Set implicit computation ---*/ - if (implicit) { - Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, Jacobian_i, Jacobian_j); + /*--- Set implicit computation ---*/ + if (implicit) + Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, residual.jacobian_i, residual.jacobian_j); } + + /*--- Viscous contribution. ---*/ + + Viscous_Residual(iEdge, geometry, solver_container, + numerics_container[VISC_TERM + omp_get_thread_num()*MAX_TERMS], config); + } + } // end color loop + + if (reducer_strategy) { + SumEdgeFluxes(geometry); + if (implicit) + Jacobian.SetDiagonalAsColumnSum(); } } -void CEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, - CConfig *config, unsigned short iMesh) { +void CEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { - su2double **Gradient_i, **Gradient_j, Project_Grad_i, Project_Grad_j, RoeVelocity[3] = {0.0,0.0,0.0}, R, sq_vel, RoeEnthalpy, - *V_i, *V_j, *S_i, *S_j, *Limiter_i = NULL, *Limiter_j = NULL, sqvel, Sensor_i, Sensor_j, Dissipation_i, Dissipation_j, *Coord_i, *Coord_j; + assert(nDim <= MAXNDIM && nPrimVar <= MAXNVAR && nSecondaryVar <= MAXNVAR && + "Oops! The CEulerSolver static array sizes are not large enough."); - su2double z, velocity2_i, velocity2_j, mach_i, mach_j, vel_i_corr[3], vel_j_corr[3]; + const auto InnerIter = config->GetInnerIter(); + const bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + const bool ideal_gas = (config->GetKind_FluidModel() == STANDARD_AIR) || + (config->GetKind_FluidModel() == IDEAL_GAS); - unsigned long iEdge, iPoint, jPoint, counter_local = 0, counter_global = 0; - unsigned short iDim, iVar; + const bool roe_turkel = (config->GetKind_Upwind_Flow() == TURKEL); + const bool low_mach_corr = config->Low_Mach_Correction(); + const auto kind_dissipation = config->GetKind_RoeLowDiss(); - bool neg_density_i = false, neg_density_j = false, neg_pressure_i = false, neg_pressure_j = false, neg_sound_speed = false; + const bool muscl = (config->GetMUSCL_Flow() && (iMesh == MESH_0)); + const bool limiter = (config->GetKind_SlopeLimit_Flow() != NO_LIMITER) && + (InnerIter <= config->GetLimiterIter()); + const bool van_albada = (config->GetKind_SlopeLimit_Flow() == VAN_ALBADA_EDGE); - unsigned long InnerIter = config->GetInnerIter(); - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - bool muscl = (config->GetMUSCL_Flow() && (iMesh == MESH_0)); - bool limiter = (config->GetKind_SlopeLimit_Flow() != NO_LIMITER) && (InnerIter <= config->GetLimiterIter()); - bool roe_turkel = (config->GetKind_Upwind_Flow() == TURKEL); - bool ideal_gas = (config->GetKind_FluidModel() == STANDARD_AIR || config->GetKind_FluidModel() == IDEAL_GAS ); - bool van_albada = config->GetKind_SlopeLimit_Flow() == VAN_ALBADA_EDGE; - bool low_mach_corr = config->Low_Mach_Correction(); - unsigned short kind_dissipation = config->GetKind_RoeLowDiss(); + /*--- Non-physical counter. ---*/ + unsigned long counter_local = 0; + SU2_OMP_MASTER + ErrorCounter = 0; + + /*--- Pick one numerics object per thread. ---*/ + CNumerics* numerics = numerics_container[CONV_TERM + omp_get_thread_num()*MAX_TERMS]; - /*--- Loop over all the edges ---*/ + /*--- Static arrays of MUSCL-reconstructed primitives and secondaries (thread safety). ---*/ + su2double Primitive_i[MAXNVAR] = {0.0}, Primitive_j[MAXNVAR] = {0.0}; + su2double Secondary_i[MAXNVAR] = {0.0}, Secondary_j[MAXNVAR] = {0.0}; - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { + /*--- Determine if using the reducer strategy is necessary, see CEulerSolver::SumEdgeFluxes(). ---*/ + const bool reducer_strategy = (MGLevel != MESH_0) && (omp_get_num_threads() > 1); + + /*--- Loop over edge colors. ---*/ + for (auto color : EdgeColoring) + { + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) + for(auto k = 0ul; k < color.size; ++k) { + + auto iEdge = color.indices[k]; + + unsigned short iDim, iVar; /*--- Points in edge and normal vectors ---*/ - iPoint = geometry->edge[iEdge]->GetNode(0); jPoint = geometry->edge[iEdge]->GetNode(1); + auto iPoint = geometry->edge[iEdge]->GetNode(0); + auto jPoint = geometry->edge[iEdge]->GetNode(1); + numerics->SetNormal(geometry->edge[iEdge]->GetNormal()); + auto Coord_i = geometry->node[iPoint]->GetCoord(); + auto Coord_j = geometry->node[jPoint]->GetCoord(); + /*--- Roe Turkel preconditioning ---*/ if (roe_turkel) { - sqvel = 0.0; + su2double sqvel = 0.0; for (iDim = 0; iDim < nDim; iDim ++) - sqvel += config->GetVelocity_FreeStream()[iDim]*config->GetVelocity_FreeStream()[iDim]; + sqvel += pow(config->GetVelocity_FreeStream()[iDim], 2); numerics->SetVelocity2_Inf(sqvel); } /*--- Grid movement ---*/ - if (dynamic_grid) - numerics->SetGridVel(geometry->node[iPoint]->GetGridVel(), geometry->node[jPoint]->GetGridVel()); + if (dynamic_grid) { + numerics->SetGridVel(geometry->node[iPoint]->GetGridVel(), + geometry->node[jPoint]->GetGridVel()); + } - /*--- Get primitive variables ---*/ + /*--- Get primitive and secondary variables ---*/ - V_i = nodes->GetPrimitive(iPoint); V_j = nodes->GetPrimitive(jPoint); - S_i = nodes->GetSecondary(iPoint); S_j = nodes->GetSecondary(jPoint); + auto V_i = nodes->GetPrimitive(iPoint); auto V_j = nodes->GetPrimitive(jPoint); + auto S_i = nodes->GetSecondary(iPoint); auto S_j = nodes->GetSecondary(jPoint); - /*--- High order reconstruction using MUSCL strategy ---*/ + /*--- Set them with or without high order reconstruction using MUSCL strategy. ---*/ - if (muscl) { + if (!muscl) { + numerics->SetPrimitive(V_i, V_j); + numerics->SetSecondary(S_i, S_j); + + } + else { + /*--- Reconstruction ---*/ + + su2double Vector_ij[MAXNDIM] = {0.0}; for (iDim = 0; iDim < nDim; iDim++) { - Vector_i[iDim] = 0.5*(geometry->node[jPoint]->GetCoord(iDim) - geometry->node[iPoint]->GetCoord(iDim)); - Vector_j[iDim] = 0.5*(geometry->node[iPoint]->GetCoord(iDim) - geometry->node[jPoint]->GetCoord(iDim)); + Vector_ij[iDim] = 0.5*(Coord_j[iDim] - Coord_i[iDim]); } - Gradient_i = nodes->GetGradient_Reconstruction(iPoint); - Gradient_j = nodes->GetGradient_Reconstruction(jPoint); + auto Gradient_i = nodes->GetGradient_Reconstruction(iPoint); + auto Gradient_j = nodes->GetGradient_Reconstruction(jPoint); + + su2double *Limiter_i = nullptr, *Limiter_j = nullptr; if (limiter) { Limiter_i = nodes->GetLimiter_Primitive(iPoint); @@ -3409,15 +3092,20 @@ void CEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_contain } for (iVar = 0; iVar < nPrimVarGrad; iVar++) { - Project_Grad_i = 0.0; Project_Grad_j = 0.0; + + su2double Project_Grad_i = 0.0; + su2double Project_Grad_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { - Project_Grad_i += Vector_i[iDim]*Gradient_i[iVar][iDim]; - Project_Grad_j += Vector_j[iDim]*Gradient_j[iVar][iDim]; + Project_Grad_i += Vector_ij[iDim]*Gradient_i[iVar][iDim]; + Project_Grad_j -= Vector_ij[iDim]*Gradient_j[iVar][iDim]; } + if (limiter) { - if (van_albada){ - Limiter_i[iVar] = (V_j[iVar]-V_i[iVar])*(2.0*Project_Grad_i + V_j[iVar]-V_i[iVar])/(4*Project_Grad_i*Project_Grad_i+(V_j[iVar]-V_i[iVar])*(V_j[iVar]-V_i[iVar])+EPS); - Limiter_j[iVar] = (V_j[iVar]-V_i[iVar])*(-2.0*Project_Grad_j + V_j[iVar]-V_i[iVar])/(4*Project_Grad_j*Project_Grad_j+(V_j[iVar]-V_i[iVar])*(V_j[iVar]-V_i[iVar])+EPS); + if (van_albada) { + su2double V_ij = V_j[iVar] - V_i[iVar]; + Limiter_i[iVar] = V_ij*( 2.0*Project_Grad_i + V_ij) / (4*pow(Project_Grad_i, 2) + pow(V_ij, 2) + EPS); + Limiter_j[iVar] = V_ij*(-2.0*Project_Grad_j + V_ij) / (4*pow(Project_Grad_j, 2) + pow(V_ij, 2) + EPS); } Primitive_i[iVar] = V_i[iVar] + Limiter_i[iVar]*Project_Grad_i; Primitive_j[iVar] = V_j[iVar] + Limiter_j[iVar]*Project_Grad_j; @@ -3426,238 +3114,229 @@ void CEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_contain Primitive_i[iVar] = V_i[iVar] + Project_Grad_i; Primitive_j[iVar] = V_j[iVar] + Project_Grad_j; } + } - /*--- Recompute the extrapolated quantities in a - thermodynamic consistent way ---*/ + /*--- Recompute the reconstructed quantities in a thermodynamically consistent way. ---*/ - if (!ideal_gas || low_mach_corr) { ComputeConsExtrapolation(config); } + if (!ideal_gas || low_mach_corr) { + ComputeConsistentExtrapolation(GetFluidModel(), nDim, Primitive_i, Secondary_i); + ComputeConsistentExtrapolation(GetFluidModel(), nDim, Primitive_j, Secondary_j); + } - /*--- Low-Mach number correction ---*/ + /*--- Low-Mach number correction. ---*/ if (low_mach_corr) { + LowMachPrimitiveCorrection(GetFluidModel(), nDim, Primitive_i, Primitive_j); + } - velocity2_i = 0.0; - velocity2_j = 0.0; + /*--- Check for non-physical solutions after reconstruction. If found, use the + cell-average value of the solution. This is a locally 1st order approximation, + which is typically only active during the start-up of a calculation. ---*/ - for (iDim = 0; iDim < nDim; iDim++) { - velocity2_i += Primitive_i[iDim+1]*Primitive_i[iDim+1]; - velocity2_j += Primitive_j[iDim+1]*Primitive_j[iDim+1]; - } - mach_i = sqrt(velocity2_i)/Primitive_i[nDim+4]; - mach_j = sqrt(velocity2_j)/Primitive_j[nDim+4]; + bool neg_pres_or_rho_i = (Primitive_i[nDim+1] < 0.0) || (Primitive_i[nDim+2] < 0.0); + bool neg_pres_or_rho_j = (Primitive_j[nDim+1] < 0.0) || (Primitive_j[nDim+2] < 0.0); - z = min(max(mach_i,mach_j),1.0); - velocity2_i = 0.0; - velocity2_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - vel_i_corr[iDim] = ( Primitive_i[iDim+1] + Primitive_j[iDim+1] )/2.0 \ - + z * ( Primitive_i[iDim+1] - Primitive_j[iDim+1] )/2.0; - vel_j_corr[iDim] = ( Primitive_i[iDim+1] + Primitive_j[iDim+1] )/2.0 \ - + z * ( Primitive_j[iDim+1] - Primitive_i[iDim+1] )/2.0; + su2double R = sqrt(fabs(Primitive_j[nDim+2]/Primitive_i[nDim+2])); + su2double sq_vel = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + su2double RoeVelocity = (R*Primitive_j[iDim+1]+Primitive_i[iDim+1])/(R+1); + sq_vel += pow(RoeVelocity, 2); + } + su2double RoeEnthalpy = (R*Primitive_j[nDim+3]+Primitive_i[nDim+3])/(R+1); - velocity2_j += vel_j_corr[iDim]*vel_j_corr[iDim]; - velocity2_i += vel_i_corr[iDim]*vel_i_corr[iDim]; + bool neg_sound_speed = ((Gamma-1)*(RoeEnthalpy-0.5*sq_vel) < 0.0); - Primitive_i[iDim+1] = vel_i_corr[iDim]; - Primitive_j[iDim+1] = vel_j_corr[iDim]; - } + bool bad_i = neg_sound_speed || neg_pres_or_rho_i; + bool bad_j = neg_sound_speed || neg_pres_or_rho_j; - FluidModel->SetEnergy_Prho(Primitive_i[nDim+1],Primitive_i[nDim+2]); - Primitive_i[nDim+3]= FluidModel->GetStaticEnergy() + Primitive_i[nDim+1]/Primitive_i[nDim+2] + 0.5*velocity2_i; + nodes->SetNon_Physical(iPoint, bad_i); + nodes->SetNon_Physical(jPoint, bad_j); - FluidModel->SetEnergy_Prho(Primitive_j[nDim+1],Primitive_j[nDim+2]); - Primitive_j[nDim+3]= FluidModel->GetStaticEnergy() + Primitive_j[nDim+1]/Primitive_j[nDim+2] + 0.5*velocity2_j; + /*--- Get updated state, in case the point recovered after the set. ---*/ + bad_i = nodes->GetNon_Physical(iPoint); + bad_j = nodes->GetNon_Physical(jPoint); - } + counter_local += bad_i+bad_j; - /*--- Check for non-physical solutions after reconstruction. If found, - use the cell-average value of the solution. This results in a locally - first-order approximation, but this is typically only active - during the start-up of a calculation. If non-physical, use the - cell-averaged state. ---*/ + numerics->SetPrimitive(bad_i? V_i : Primitive_i, bad_j? V_j : Primitive_j); + numerics->SetSecondary(bad_i? S_i : Secondary_i, bad_j? S_j : Secondary_j); - neg_pressure_i = (Primitive_i[nDim+1] < 0.0); neg_pressure_j = (Primitive_j[nDim+1] < 0.0); - neg_density_i = (Primitive_i[nDim+2] < 0.0); neg_density_j = (Primitive_j[nDim+2] < 0.0); + } - R = sqrt(fabs(Primitive_j[nDim+2]/Primitive_i[nDim+2])); - sq_vel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - RoeVelocity[iDim] = (R*Primitive_j[iDim+1]+Primitive_i[iDim+1])/(R+1); - sq_vel += RoeVelocity[iDim]*RoeVelocity[iDim]; - } - RoeEnthalpy = (R*Primitive_j[nDim+3]+Primitive_i[nDim+3])/(R+1); - neg_sound_speed = ((Gamma-1)*(RoeEnthalpy-0.5*sq_vel) < 0.0); + /*--- Roe Low Dissipation Scheme ---*/ - if (neg_sound_speed) { - for (iVar = 0; iVar < nPrimVar; iVar++) { - Primitive_i[iVar] = V_i[iVar]; - Primitive_j[iVar] = V_j[iVar]; - } - nodes->SetNon_Physical(iPoint, true); - nodes->SetNon_Physical(iPoint, true); - Secondary_i[0] = S_i[0]; Secondary_i[1] = S_i[1]; - Secondary_j[0] = S_i[0]; Secondary_j[1] = S_i[1]; - } + if (kind_dissipation != NO_ROELOWDISS) { - if (neg_density_i || neg_pressure_i) { - for (iVar = 0; iVar < nPrimVar; iVar++) Primitive_i[iVar] = V_i[iVar]; - nodes->SetNon_Physical(iPoint, true); - Secondary_i[0] = S_i[0]; Secondary_i[1] = S_i[1]; - } + numerics->SetDissipation(nodes->GetRoe_Dissipation(iPoint), + nodes->GetRoe_Dissipation(jPoint)); - if (neg_density_j || neg_pressure_j) { - for (iVar = 0; iVar < nPrimVar; iVar++) Primitive_j[iVar] = V_j[iVar]; - nodes->SetNon_Physical(jPoint, true); - Secondary_j[0] = S_j[0]; Secondary_j[1] = S_j[1]; + if (kind_dissipation == FD_DUCROS || kind_dissipation == NTS_DUCROS){ + numerics->SetSensor(nodes->GetSensor(iPoint), + nodes->GetSensor(jPoint)); } + if (kind_dissipation == NTS || kind_dissipation == NTS_DUCROS){ + numerics->SetCoord(Coord_i, Coord_j); + } + } - if (!neg_sound_speed && !neg_density_i && !neg_pressure_i) - nodes->SetNon_Physical(iPoint, false); + /*--- Compute the residual ---*/ - if (!neg_sound_speed && !neg_density_j && !neg_pressure_j) - nodes->SetNon_Physical(jPoint, false); + auto residual = numerics->ComputeResidual(config); - /* Lastly, check for existing first-order points still active - from previous iterations. */ + /*--- Set the final value of the Roe dissipation coefficient ---*/ - if (nodes->GetNon_Physical(iPoint)) { - counter_local++; - for (iVar = 0; iVar < nPrimVar; iVar++) - Primitive_i[iVar] = V_i[iVar]; - } - if (nodes->GetNon_Physical(jPoint)) { - counter_local++; - for (iVar = 0; iVar < nPrimVar; iVar++) - Primitive_j[iVar] = V_j[iVar]; - } + if ((kind_dissipation != NO_ROELOWDISS) && (MGLevel != MESH_0)) { + nodes->SetRoe_Dissipation(iPoint,numerics->GetDissipation()); + nodes->SetRoe_Dissipation(jPoint,numerics->GetDissipation()); + } - numerics->SetPrimitive(Primitive_i, Primitive_j); - numerics->SetSecondary(Secondary_i, Secondary_j); + /*--- Update residual value ---*/ + if (reducer_strategy) { + EdgeFluxes.SetBlock(iEdge, residual); + if (implicit) + Jacobian.UpdateBlocks(iEdge, residual.jacobian_i, residual.jacobian_j); } else { + LinSysRes.AddBlock(iPoint, residual); + LinSysRes.SubtractBlock(jPoint, residual); - /*--- Set conservative variables without reconstruction ---*/ + /*--- Set implicit computation ---*/ + if (implicit) + Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, residual.jacobian_i, residual.jacobian_j); + } - numerics->SetPrimitive(V_i, V_j); - numerics->SetSecondary(S_i, S_j); + /*--- Viscous contribution. ---*/ - } + Viscous_Residual(iEdge, geometry, solver_container, + numerics_container[VISC_TERM + omp_get_thread_num()*MAX_TERMS], config); + } + } // end color loop - /*--- Roe Low Dissipation Scheme ---*/ + if (reducer_strategy) { + SumEdgeFluxes(geometry); + if (implicit) + Jacobian.SetDiagonalAsColumnSum(); + } - if (kind_dissipation != NO_ROELOWDISS){ + /*--- Warning message about non-physical reconstructions. ---*/ - Dissipation_i = nodes->GetRoe_Dissipation(iPoint); - Dissipation_j = nodes->GetRoe_Dissipation(jPoint); - numerics->SetDissipation(Dissipation_i, Dissipation_j); + if ((iMesh == MESH_0) && (config->GetComm_Level() == COMM_FULL)) { + /*--- Add counter results for all threads. ---*/ + SU2_OMP_ATOMIC + ErrorCounter += counter_local; + SU2_OMP_BARRIER - if (kind_dissipation == FD_DUCROS || kind_dissipation == NTS_DUCROS){ - Sensor_i = nodes->GetSensor(iPoint); - Sensor_j = nodes->GetSensor(jPoint); - numerics->SetSensor(Sensor_i, Sensor_j); - } - if (kind_dissipation == NTS || kind_dissipation == NTS_DUCROS){ - Coord_i = geometry->node[iPoint]->GetCoord(); - Coord_j = geometry->node[jPoint]->GetCoord(); - numerics->SetCoord(Coord_i, Coord_j); - } + /*--- Add counter results for all ranks. ---*/ + SU2_OMP_MASTER + { + counter_local = ErrorCounter; + SU2_MPI::Reduce(&counter_local, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD); + config->SetNonphysical_Reconstr(ErrorCounter); } + SU2_OMP_BARRIER + } - /*--- Compute the residual ---*/ +} - numerics->ComputeResidual(Res_Conv, Jacobian_i, Jacobian_j, config); +void CEulerSolver::SumEdgeFluxes(CGeometry* geometry) { - /*--- Update residual value ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; ++iPoint) { - LinSysRes.AddBlock(iPoint, Res_Conv); - LinSysRes.SubtractBlock(jPoint, Res_Conv); + for (unsigned short iNeigh = 0; iNeigh < geometry->node[iPoint]->GetnPoint(); ++iNeigh) { - /*--- Set implicit Jacobians ---*/ + auto iEdge = geometry->node[iPoint]->GetEdge(iNeigh); - if (implicit) { - Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, Jacobian_i, Jacobian_j); + if (iPoint == geometry->edge[iEdge]->GetNode(0)) + LinSysRes.AddBlock(iPoint, EdgeFluxes.GetBlock(iEdge)); + else + LinSysRes.SubtractBlock(iPoint, EdgeFluxes.GetBlock(iEdge)); } + } - /*--- Set the final value of the Roe dissipation coefficient ---*/ +} - if (kind_dissipation != NO_ROELOWDISS){ - nodes->SetRoe_Dissipation(iPoint,numerics->GetDissipation()); - nodes->SetRoe_Dissipation(jPoint,numerics->GetDissipation()); - } +void CEulerSolver::ComputeConsistentExtrapolation(CFluidModel *fluidModel, unsigned short nDim, + su2double *primitive, su2double *secondary) { - } + su2double density = primitive[nDim+2]; + su2double pressure = primitive[nDim+1]; - /*--- Warning message about non-physical reconstructions ---*/ + su2double velocity2 = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + velocity2 += pow(primitive[iDim+1], 2); - if (config->GetComm_Level() == COMM_FULL) { -#ifdef HAVE_MPI - SU2_MPI::Reduce(&counter_local, &counter_global, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD); -#else - counter_global = counter_local; -#endif - if (iMesh == MESH_0) config->SetNonphysical_Reconstr(counter_global); - } -} + fluidModel->SetTDState_Prho(pressure, density); -void CEulerSolver::ComputeConsExtrapolation(CConfig *config) { + primitive[0] = fluidModel->GetTemperature(); + primitive[nDim+3] = fluidModel->GetStaticEnergy() + primitive[nDim+1]/primitive[nDim+2] + 0.5*velocity2; + primitive[nDim+4] = fluidModel->GetSoundSpeed(); + secondary[0] = fluidModel->GetdPdrho_e(); + secondary[1] = fluidModel->GetdPde_rho(); +} + +void CEulerSolver::LowMachPrimitiveCorrection(CFluidModel *fluidModel, unsigned short nDim, + su2double *primitive_i, su2double *primitive_j) { unsigned short iDim; - su2double density_i = Primitive_i[nDim+2]; - su2double pressure_i = Primitive_i[nDim+1]; su2double velocity2_i = 0.0; + su2double velocity2_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { - velocity2_i += Primitive_i[iDim+1]*Primitive_i[iDim+1]; + velocity2_i += pow(primitive_i[iDim+1], 2); + velocity2_j += pow(primitive_j[iDim+1], 2); } + su2double mach_i = sqrt(velocity2_i)/primitive_i[nDim+4]; + su2double mach_j = sqrt(velocity2_j)/primitive_j[nDim+4]; - FluidModel->SetTDState_Prho(pressure_i, density_i); - - Primitive_i[0]= FluidModel->GetTemperature(); - Primitive_i[nDim+3]= FluidModel->GetStaticEnergy() + Primitive_i[nDim+1]/Primitive_i[nDim+2] + 0.5*velocity2_i; - Primitive_i[nDim+4]= FluidModel->GetSoundSpeed(); - Secondary_i[0]=FluidModel->GetdPdrho_e(); - Secondary_i[1]=FluidModel->GetdPde_rho(); + su2double z = min(max(mach_i,mach_j),1.0); + velocity2_i = 0.0; + velocity2_j = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + su2double vel_i_corr = ( primitive_i[iDim+1] + primitive_j[iDim+1] )/2.0 + + z * ( primitive_i[iDim+1] - primitive_j[iDim+1] )/2.0; + su2double vel_j_corr = ( primitive_i[iDim+1] + primitive_j[iDim+1] )/2.0 + + z * ( primitive_j[iDim+1] - primitive_i[iDim+1] )/2.0; + velocity2_i += pow(vel_i_corr, 2); + velocity2_j += pow(vel_j_corr, 2); - su2double density_j = Primitive_j[nDim+2]; - su2double pressure_j = Primitive_j[nDim+1]; - su2double velocity2_j = 0.0; - for (iDim = 0; iDim < nDim; iDim++) { - velocity2_j += Primitive_j[iDim+1]*Primitive_j[iDim+1]; + primitive_i[iDim+1] = vel_i_corr; + primitive_j[iDim+1] = vel_j_corr; } - FluidModel->SetTDState_Prho(pressure_j, density_j); + fluidModel->SetEnergy_Prho(primitive_i[nDim+1], primitive_i[nDim+2]); + primitive_i[nDim+3]= fluidModel->GetStaticEnergy() + primitive_i[nDim+1]/primitive_i[nDim+2] + 0.5*velocity2_i; - Primitive_j[0]= FluidModel->GetTemperature(); - Primitive_j[nDim+3]= FluidModel->GetStaticEnergy() + Primitive_j[nDim+1]/Primitive_j[nDim+2] + 0.5*velocity2_j; - Primitive_j[nDim+4]=FluidModel->GetSoundSpeed(); - Secondary_j[0]=FluidModel->GetdPdrho_e(); - Secondary_j[1]=FluidModel->GetdPde_rho(); + fluidModel->SetEnergy_Prho(primitive_j[nDim+1], primitive_j[nDim+2]); + primitive_j[nDim+3]= fluidModel->GetStaticEnergy() + primitive_j[nDim+1]/primitive_j[nDim+2] + 0.5*velocity2_j; } -void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) { +void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { - unsigned short iVar; - unsigned long iPoint; - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - bool rotating_frame = config->GetRotating_Frame(); - bool axisymmetric = config->GetAxisymmetric(); - bool gravity = (config->GetGravityForce() == YES); - bool harmonic_balance = (config->GetTime_Marching() == HARMONIC_BALANCE); - bool windgust = config->GetWind_Gust(); - bool body_force = config->GetBody_Force(); + const bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + const bool rotating_frame = config->GetRotating_Frame(); + const bool axisymmetric = config->GetAxisymmetric(); + const bool gravity = (config->GetGravityForce() == YES); + const bool harmonic_balance = (config->GetTime_Marching() == HARMONIC_BALANCE); + const bool windgust = config->GetWind_Gust(); + const bool body_force = config->GetBody_Force(); - /*--- Initialize the source residual to zero ---*/ + /*--- Pick one numerics object per thread. ---*/ + CNumerics* numerics = numerics_container[SOURCE_FIRST_TERM + omp_get_thread_num()*MAX_TERMS]; - for (iVar = 0; iVar < nVar; iVar++) Residual[iVar] = 0.0; + unsigned short iVar; + unsigned long iPoint; if (body_force) { /*--- Loop over all points ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Load the conservative variables ---*/ @@ -3668,10 +3347,10 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain numerics->SetVolume(geometry->node[iPoint]->GetVolume()); /*--- Compute the rotating frame source residual ---*/ - numerics->ComputeResidual(Residual, config); + auto residual = numerics->ComputeResidual(config); /*--- Add the source residual to the total ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); } } @@ -3681,9 +3360,12 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain /*--- Include the residual contribution from GCL due to the static mesh movement that is set for rotating frame. ---*/ + SU2_OMP_MASTER SetRotatingFrame_GCL(geometry, config); + SU2_OMP_BARRIER /*--- Loop over all points ---*/ + SU2_OMP_FOR_DYN(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Load the conservative variables ---*/ @@ -3694,27 +3376,21 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain numerics->SetVolume(geometry->node[iPoint]->GetVolume()); /*--- Compute the rotating frame source residual ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, config); + auto residual = numerics->ComputeResidual(config); /*--- Add the source residual to the total ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Add the implicit Jacobian contribution ---*/ - if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } } if (axisymmetric) { - /*--- Zero out Jacobian structure ---*/ - if (implicit) { - for (iVar = 0; iVar < nVar; iVar ++) - for (unsigned short jVar = 0; jVar < nVar; jVar ++) - Jacobian_i[iVar][jVar] = 0.0; - } - /*--- loop over points ---*/ + SU2_OMP_FOR_DYN(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Set solution ---*/ @@ -3727,20 +3403,21 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain numerics->SetCoord(geometry->node[iPoint]->GetCoord(), geometry->node[iPoint]->GetCoord()); /*--- Compute Source term Residual ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, config); + auto residual = numerics->ComputeResidual(config); /*--- Add Residual ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Implicit part ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } } if (gravity) { /*--- loop over points ---*/ + SU2_OMP_FOR_DYN(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Set solution ---*/ @@ -3750,10 +3427,10 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain numerics->SetVolume(geometry->node[iPoint]->GetVolume()); /*--- Compute Source term Residual ---*/ - numerics->ComputeResidual(Residual, config); + auto residual = numerics->ComputeResidual(config); /*--- Add Residual ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); } @@ -3761,29 +3438,24 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain if (harmonic_balance) { - su2double Volume, Source; - /*--- loop over points ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Get control volume ---*/ - Volume = geometry->node[iPoint]->GetVolume(); + su2double Volume = geometry->node[iPoint]->GetVolume(); - /*--- Get stored time spectral source term ---*/ + /*--- Get stored time spectral source term and add to residual ---*/ for (iVar = 0; iVar < nVar; iVar++) { - Source = nodes->GetHarmonicBalance_Source(iPoint,iVar); - Residual[iVar] = Source*Volume; + LinSysRes(iPoint,iVar) += Volume * nodes->GetHarmonicBalance_Source(iPoint,iVar); } - - /*--- Add Residual ---*/ - LinSysRes.AddBlock(iPoint, Residual); - } } if (windgust) { /*--- Loop over all points ---*/ + SU2_OMP_FOR_DYN(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Load the wind gust ---*/ @@ -3799,13 +3471,13 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain numerics->SetVolume(geometry->node[iPoint]->GetVolume()); /*--- Compute the rotating frame source residual ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, config); + auto residual = numerics->ComputeResidual(config); /*--- Add the source residual to the total ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Add the implicit Jacobian contribution ---*/ - if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } } @@ -3820,6 +3492,7 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain if (config->GetTime_Marching()) time = config->GetPhysicalTime(); /*--- Loop over points ---*/ + SU2_OMP_FOR_DYN(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Get control volume size. ---*/ @@ -3832,14 +3505,10 @@ void CEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_contain vector sourceMan(nVar,0.0); VerificationSolution->GetMMSSourceTerm(coor, time, sourceMan.data()); - /*--- Compute the residual for this control volume. ---*/ + /*--- Compute the residual for this control volume and subtract. ---*/ for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] = sourceMan[iVar]*Volume; + LinSysRes(iPoint,iVar) -= sourceMan[iVar]*Volume; } - - /*--- Subtract Residual ---*/ - LinSysRes.SubtractBlock(iPoint, Residual); - } } } @@ -3862,86 +3531,82 @@ void CEulerSolver::Source_Template(CGeometry *geometry, CSolver **solver_contain void CEulerSolver::SetMax_Eigenvalue(CGeometry *geometry, CConfig *config) { - su2double *Normal, Area, Mean_SoundSpeed = 0.0, Mean_ProjVel = 0.0, Lambda, - ProjVel, ProjVel_i, ProjVel_j, *GridVel, *GridVel_i, *GridVel_j; - unsigned long iEdge, iVertex, iPoint, jPoint; - unsigned short iDim, iMarker; + /*--- Loop domain points. ---*/ - /*--- Set maximum inviscid eigenvalue to zero, and compute sound speed ---*/ + SU2_OMP_FOR_DYN(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; ++iPoint) { - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + /*--- Set eigenvalues to zero. ---*/ nodes->SetLambda(iPoint,0.0); - } - /*--- Loop interior edges ---*/ + /*--- Loop over the neighbors of point i. ---*/ + for (unsigned short iNeigh = 0; iNeigh < geometry->node[iPoint]->GetnPoint(); ++iNeigh) + { + auto jPoint = geometry->node[iPoint]->GetPoint(iNeigh); - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { - - /*--- Point identification, Normal vector and area ---*/ - - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); + auto iEdge = geometry->node[iPoint]->GetEdge(iNeigh); + auto Normal = geometry->edge[iEdge]->GetNormal(); + su2double Area = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) Area += pow(Normal[iDim],2); + Area = sqrt(Area); - Normal = geometry->edge[iEdge]->GetNormal(); - Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); + /*--- Mean Values ---*/ - /*--- Mean Values ---*/ + su2double Mean_ProjVel = 0.5 * (nodes->GetProjVel(iPoint,Normal) + nodes->GetProjVel(jPoint,Normal)); + su2double Mean_SoundSpeed = 0.5 * (nodes->GetSoundSpeed(iPoint) + nodes->GetSoundSpeed(jPoint)) * Area; - Mean_ProjVel = 0.5 * (nodes->GetProjVel(iPoint,Normal) + nodes->GetProjVel(jPoint,Normal)); - Mean_SoundSpeed = 0.5 * (nodes->GetSoundSpeed(iPoint) + nodes->GetSoundSpeed(jPoint)) * Area; + /*--- Adjustment for grid movement ---*/ - /*--- Adjustment for grid movement ---*/ + if (dynamic_grid) { + const su2double *GridVel_i = geometry->node[iPoint]->GetGridVel(); + const su2double *GridVel_j = geometry->node[jPoint]->GetGridVel(); - if (dynamic_grid) { - GridVel_i = geometry->node[iPoint]->GetGridVel(); - GridVel_j = geometry->node[jPoint]->GetGridVel(); - ProjVel_i = 0.0; ProjVel_j =0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjVel_i += GridVel_i[iDim]*Normal[iDim]; - ProjVel_j += GridVel_j[iDim]*Normal[iDim]; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Mean_ProjVel -= 0.5 * (GridVel_i[iDim] + GridVel_j[iDim]) * Normal[iDim]; } - Mean_ProjVel -= 0.5 * (ProjVel_i + ProjVel_j); - } - /*--- Inviscid contribution ---*/ + /*--- Inviscid contribution ---*/ - Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed; - if (geometry->node[iPoint]->GetDomain()) nodes->AddLambda(iPoint, Lambda); - if (geometry->node[jPoint]->GetDomain()) nodes->AddLambda(jPoint, Lambda); + su2double Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed ; + nodes->AddLambda(iPoint, Lambda); + } } /*--- Loop boundary edges ---*/ - for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) { + for (unsigned short iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) { if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) { - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { + + SU2_OMP_FOR_STAT(OMP_MIN_SIZE) + for (unsigned long iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { /*--- Point identification, Normal vector and area ---*/ - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); + auto iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + auto Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); + su2double Area = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Area += pow(Normal[iDim],2); + Area = sqrt(Area); /*--- Mean Values ---*/ - Mean_ProjVel = nodes->GetProjVel(iPoint,Normal); - Mean_SoundSpeed = nodes->GetSoundSpeed(iPoint) * Area; + su2double Mean_ProjVel = nodes->GetProjVel(iPoint,Normal); + su2double Mean_SoundSpeed = nodes->GetSoundSpeed(iPoint) * Area; /*--- Adjustment for grid movement ---*/ if (dynamic_grid) { - GridVel = geometry->node[iPoint]->GetGridVel(); - ProjVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjVel += GridVel[iDim]*Normal[iDim]; - Mean_ProjVel -= ProjVel; + auto GridVel = geometry->node[iPoint]->GetGridVel(); + for (unsigned short iDim = 0; iDim < nDim; iDim++) + Mean_ProjVel -= GridVel[iDim]*Normal[iDim]; } /*--- Inviscid contribution ---*/ - Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed; + su2double Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed; if (geometry->node[iPoint]->GetDomain()) { nodes->AddLambda(iPoint,Lambda); } @@ -3949,49 +3614,53 @@ void CEulerSolver::SetMax_Eigenvalue(CGeometry *geometry, CConfig *config) { } } - /*--- Correct the eigenvalue values across any periodic boundaries. ---*/ + SU2_OMP_MASTER + { + /*--- Correct the eigenvalue values across any periodic boundaries. ---*/ - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_MAX_EIG); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_MAX_EIG); - } + for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { + InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_MAX_EIG); + CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_MAX_EIG); + } - /*--- MPI parallelization ---*/ + /*--- MPI parallelization ---*/ - InitiateComms(geometry, config, MAX_EIGENVALUE); - CompleteComms(geometry, config, MAX_EIGENVALUE); + InitiateComms(geometry, config, MAX_EIGENVALUE); + CompleteComms(geometry, config, MAX_EIGENVALUE); + } + SU2_OMP_BARRIER } void CEulerSolver::SetUndivided_Laplacian(CGeometry *geometry, CConfig *config) { - unsigned long iPoint, jPoint, iEdge; - su2double Pressure_i = 0, Pressure_j = 0, *Diff; - unsigned short iVar; - bool boundary_i, boundary_j; - - Diff = new su2double[nVar]; - nodes->SetUnd_LaplZero(); - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { + /*--- Loop over edge colors. ---*/ + for (auto color : EdgeColoring) + { + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) + for(auto k = 0ul; k < color.size; ++k) { + + auto iEdge = color.indices[k]; - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); + auto iPoint = geometry->edge[iEdge]->GetNode(0); + auto jPoint = geometry->edge[iEdge]->GetNode(1); /*--- Solution differences ---*/ - for (iVar = 0; iVar < nVar; iVar++) + su2double Diff[MAXNVAR] = {0.0}; + + for (unsigned short iVar = 0; iVar < nVar; iVar++) Diff[iVar] = nodes->GetSolution(iPoint,iVar) - nodes->GetSolution(jPoint,iVar); /*--- Correction for compressible flows which use the enthalpy ---*/ - Pressure_i = nodes->GetPressure(iPoint); - Pressure_j = nodes->GetPressure(jPoint); - Diff[nVar-1] = (nodes->GetSolution(iPoint,nVar-1) + Pressure_i) - (nodes->GetSolution(jPoint,nVar-1) + Pressure_j); + Diff[nVar-1] += nodes->GetPressure(iPoint) - nodes->GetPressure(jPoint); - boundary_i = geometry->node[iPoint]->GetPhysicalBoundary(); - boundary_j = geometry->node[jPoint]->GetPhysicalBoundary(); + bool boundary_i = geometry->node[iPoint]->GetPhysicalBoundary(); + bool boundary_j = geometry->node[jPoint]->GetPhysicalBoundary(); /*--- Both points inside the domain, or both in the boundary ---*/ @@ -4011,48 +3680,53 @@ void CEulerSolver::SetUndivided_Laplacian(CGeometry *geometry, CConfig *config) if (geometry->node[jPoint]->GetDomain()) nodes->AddUnd_Lapl(jPoint, Diff); } + } // end color loop - /*--- Correct the Laplacian values across any periodic boundaries. ---*/ - - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LAPLACIAN); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LAPLACIAN); - } + SU2_OMP_MASTER + { + /*--- Correct the Laplacian values across any periodic boundaries. ---*/ - /*--- MPI parallelization ---*/ + for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { + InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_LAPLACIAN); + CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_LAPLACIAN); + } - InitiateComms(geometry, config, UNDIVIDED_LAPLACIAN); - CompleteComms(geometry, config, UNDIVIDED_LAPLACIAN); + /*--- MPI parallelization ---*/ - delete [] Diff; + InitiateComms(geometry, config, UNDIVIDED_LAPLACIAN); + CompleteComms(geometry, config, UNDIVIDED_LAPLACIAN); + } + SU2_OMP_BARRIER } void CEulerSolver::SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig *config) { - unsigned long iEdge, iPoint, jPoint; - su2double Pressure_i = 0.0, Pressure_j = 0.0; - bool boundary_i, boundary_j; - /*--- Reset variables to store the undivided pressure ---*/ - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { iPoint_UndLapl[iPoint] = 0.0; jPoint_UndLapl[iPoint] = 0.0; } - /*--- Evaluate the pressure sensor ---*/ + /*--- Loop over edge colors. ---*/ + for (auto color : EdgeColoring) + { + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) + for(auto k = 0ul; k < color.size; ++k) { - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { + auto iEdge = color.indices[k]; - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); + auto iPoint = geometry->edge[iEdge]->GetNode(0); + auto jPoint = geometry->edge[iEdge]->GetNode(1); - Pressure_i = nodes->GetPressure(iPoint); - Pressure_j = nodes->GetPressure(jPoint); + su2double Pressure_i = nodes->GetPressure(iPoint); + su2double Pressure_j = nodes->GetPressure(jPoint); - boundary_i = geometry->node[iPoint]->GetPhysicalBoundary(); - boundary_j = geometry->node[jPoint]->GetPhysicalBoundary(); + bool boundary_i = geometry->node[iPoint]->GetPhysicalBoundary(); + bool boundary_j = geometry->node[jPoint]->GetPhysicalBoundary(); /*--- Both points inside the domain, or both on the boundary ---*/ @@ -4070,99 +3744,88 @@ void CEulerSolver::SetCentered_Dissipation_Sensor(CGeometry *geometry, CConfig * if (boundary_i && !boundary_j) if (geometry->node[jPoint]->GetDomain()) { iPoint_UndLapl[jPoint] += (Pressure_i - Pressure_j); jPoint_UndLapl[jPoint] += (Pressure_i + Pressure_j); } - } + } // end color loop /*--- Correct the sensor values across any periodic boundaries. ---*/ - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_SENSOR); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_SENSOR); + SU2_OMP_MASTER + { + for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { + InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_SENSOR); + CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_SENSOR); + } } + SU2_OMP_BARRIER /*--- Set pressure switch for each point ---*/ - for (iPoint = 0; iPoint < nPointDomain; iPoint++) - nodes->SetSensor(iPoint,fabs(iPoint_UndLapl[iPoint]) / jPoint_UndLapl[iPoint]); + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) + nodes->SetSensor(iPoint, fabs(iPoint_UndLapl[iPoint]) / jPoint_UndLapl[iPoint]); /*--- MPI parallelization ---*/ - InitiateComms(geometry, config, SENSOR); - CompleteComms(geometry, config, SENSOR); + SU2_OMP_MASTER + { + InitiateComms(geometry, config, SENSOR); + CompleteComms(geometry, config, SENSOR); + } + SU2_OMP_BARRIER } void CEulerSolver::SetUpwind_Ducros_Sensor(CGeometry *geometry, CConfig *config){ - unsigned long iPoint, jPoint; - unsigned short iNeigh, iDim; - - su2double *Vorticity; - - su2double uixi = 0.0, Ducros_i = 0.0, Ducros_j = 0.0, Omega = 0.0; - - for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++){ + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { - /*---- Dilatation for iPoint ---*/ + /*---- Ducros sensor for iPoint and its neighbor points to avoid lower dissipation near shocks. ---*/ - uixi=0.0; - for(iDim = 0; iDim < nDim; iDim++){ - uixi += nodes->GetGradient_Primitive(iPoint,iDim+1, iDim); - } - - /*--- Compute norm of vorticity ---*/ + su2double Ducros_i = 0.0; + auto nNeigh = geometry->node[iPoint]->GetnNeighbor(); - Vorticity = nodes->GetVorticity(iPoint); - Omega = 0.0; - for (iDim = 0; iDim < nDim; iDim++){ - Omega += Vorticity[iDim]*Vorticity[iDim]; - } - Omega = sqrt(Omega); - - /*---- Ducros sensor for iPoint ---*/ - - if (config->GetKind_RoeLowDiss() == FD_DUCROS){ - Ducros_i = -uixi / (fabs(uixi) + Omega + 1e-20); - } else if (config->GetKind_RoeLowDiss() == NTS_DUCROS){ - Ducros_i = pow(uixi,2.0) /(pow(uixi,2.0)+ pow(Omega,2.0) + 1e-20); - } + for (unsigned short iNeigh = 0; iNeigh <= nNeigh; iNeigh++) { - nodes->SetSensor(iPoint,Ducros_i); - - /*---- Ducros sensor for neighbor points of iPoint to avoid lower the dissipation in regions near the shock ---*/ - - for (iNeigh = 0; iNeigh > geometry->node[iPoint]->GetnNeighbor(); iNeigh++){ - - jPoint = geometry->node[iPoint]->GetPoint(iNeigh); + auto jPoint = iPoint; + if (iNeigh < nNeigh) jPoint = geometry->node[iPoint]->GetPoint(iNeigh); /*---- Dilatation for jPoint ---*/ - uixi=0.0; - for(iDim = 0; iDim < nDim; iDim++){ + su2double uixi=0.0; + for(unsigned short iDim = 0; iDim < nDim; iDim++){ uixi += nodes->GetGradient_Primitive(jPoint,iDim+1, iDim); } /*--- Compute norm of vorticity ---*/ - Vorticity = nodes->GetVorticity(jPoint); - Omega = 0.0; - for (iDim = 0; iDim < nDim; iDim++){ - Omega += Vorticity[iDim]*Vorticity[iDim]; + const su2double* Vorticity = nodes->GetVorticity(jPoint); + su2double Omega = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) { + Omega += pow(Vorticity[iDim], 2); } Omega = sqrt(Omega); - if (config->GetKind_RoeLowDiss() == FD_DUCROS){ + su2double Ducros_j = 0.0; + + if (config->GetKind_RoeLowDiss() == FD_DUCROS) { Ducros_j = -uixi / (fabs(uixi) + Omega + 1e-20); - } else if (config->GetKind_RoeLowDiss() == NTS_DUCROS){ + } + else if (config->GetKind_RoeLowDiss() == NTS_DUCROS) { Ducros_j = pow(uixi,2.0) /(pow(uixi,2.0)+ pow(Omega,2.0) + 1e-20); } - nodes->SetSensor(iPoint, max(nodes->GetSensor(iPoint), Ducros_j)); - + Ducros_i = max(Ducros_i, Ducros_j); } + + nodes->SetSensor(iPoint, Ducros_i); } - InitiateComms(geometry, config, SENSOR); - CompleteComms(geometry, config, SENSOR); + SU2_OMP_MASTER + { + InitiateComms(geometry, config, SENSOR); + CompleteComms(geometry, config, SENSOR); + } + SU2_OMP_BARRIER } @@ -4170,35 +3833,30 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { unsigned long iVertex, iPoint; unsigned short iDim, iMarker, Boundary, Monitoring, iMarker_Monitoring; - su2double Pressure = 0.0, *Normal = NULL, MomentDist[3] = {0.0,0.0,0.0}, *Coord, - factor, NFPressOF, RefVel2, RefTemp, RefDensity, RefPressure, Mach2Vel, Mach_Motion, - Force[3] = {0.0,0.0,0.0}; + 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 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_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, MyAllBound_CNearFieldOF_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 - - su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; - su2double Beta = config->GetAoS()*PI_NUMBER/180.0; - su2double RefArea = config->GetRefArea(); + 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(); - su2double *Origin = NULL; + su2double Gas_Constant = config->GetGas_ConstantND(); + const su2double *Origin = nullptr; if (config->GetnMarker_Monitoring() != 0){ Origin = config->GetRefOriginMoment(0); } - bool axisymmetric = config->GetAxisymmetric(); + 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; + RefTemp = Temperature_Inf; + RefDensity = Density_Inf; RefPressure = Pressure_Inf; if (dynamic_grid) { Mach2Vel = sqrt(Gamma*Gas_Constant*RefTemp); @@ -4215,32 +3873,16 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *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; + TotalCoeff.setZero(); + Total_CNearFieldOF = 0.0; Total_Heat = 0.0; Total_MaxHeat = 0.0; - 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_CNearFieldOF_Inv = 0.0; AllBound_CEff_Inv = 0.0; + AllBoundInvCoeff.setZero(); - 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; - 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; - } + AllBound_CNearFieldOF_Inv = 0.0; + + SurfaceInvCoeff.setZero(); + SurfaceCoeff.setZero(); /*--- Loop over the Euler and Navier-Stokes markers ---*/ @@ -4269,18 +3911,12 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { /*--- Forces initialization at each Marker ---*/ - 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; - CNearFieldOF_Inv[iMarker] = 0.0; CEff_Inv[iMarker] = 0.0; + InvCoeff.setZero(iMarker); + + CNearFieldOF_Inv[iMarker] = 0.0; - 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; + 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; @@ -4307,6 +3943,7 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { 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]; } @@ -4319,6 +3956,7 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { /*--- 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]; @@ -4348,52 +3986,52 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { 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); + 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) { - 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); + 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); } - 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); + 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 ---*/ @@ -4401,16 +4039,16 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { 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]; + 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]; } } @@ -4425,7 +4063,6 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { } - } } @@ -4433,135 +4070,107 @@ void CEulerSolver::Pressure_Forces(CGeometry *geometry, CConfig *config) { /*--- 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; - MyAllBound_CNearFieldOF_Inv = AllBound_CNearFieldOF_Inv; AllBound_CNearFieldOF_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); - SU2_MPI::Allreduce(&MyAllBound_CNearFieldOF_Inv, &AllBound_CNearFieldOF_Inv, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - } - /*--- Add the forces on the surfaces using all the nodes ---*/ + 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); - 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()]; + 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); - 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; } + /*--- Add the forces on the surfaces using all the nodes ---*/ + 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; + + 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++) { - 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]; + 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]; } } @@ -4570,31 +4179,17 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { unsigned long iVertex, iPoint; unsigned short iDim, iMarker, Boundary, Monitoring, iMarker_Monitoring; - su2double *Normal = NULL, MomentDist[3] = {0.0,0.0,0.0}, *Coord, Area, - factor, RefVel2, RefTemp, RefDensity, Mach2Vel, Mach_Motion, - Force[3] = {0.0,0.0,0.0}, Velocity[3], MassFlow, Density; + su2double Area, factor, RefVel2, RefTemp, RefDensity, Mach2Vel, Mach_Motion, MassFlow, Density; + const su2double *Normal = nullptr, *Coord = nullptr; 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 Gas_Constant = config->GetGas_ConstantND(); - su2double *Origin = NULL; + 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); } @@ -4622,20 +4217,8 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { /*-- 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; - } + AllBoundMntCoeff.setZero(); + SurfaceMntCoeff.setZero(); /*--- Loop over the Inlet -Outlet Markers ---*/ @@ -4661,18 +4244,10 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { /*--- Forces initialization at each Marker ---*/ - CD_Mnt[iMarker] = 0.0; CL_Mnt[iMarker] = 0.0; CSF_Mnt[iMarker] = 0.0; - CFx_Mnt[iMarker] = 0.0; CFy_Mnt[iMarker] = 0.0; CFz_Mnt[iMarker] = 0.0; - CMx_Mnt[iMarker] = 0.0; CMy_Mnt[iMarker] = 0.0; CMz_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; + MntCoeff.setZero(iMarker); - 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; + 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 ---*/ @@ -4695,6 +4270,7 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { 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]; @@ -4709,6 +4285,7 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { /*--- 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]; @@ -4738,51 +4315,52 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { 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); - CFx_Mnt[iMarker] = ForceMomentum[0]; - CFy_Mnt[iMarker] = ForceMomentum[1]; - CMz_Mnt[iMarker] = MomentMomentum[2]; - 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); + 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) { - 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); - CFx_Mnt[iMarker] = ForceMomentum[0]; - CFy_Mnt[iMarker] = ForceMomentum[1]; - CFz_Mnt[iMarker] = ForceMomentum[2]; - CMx_Mnt[iMarker] = MomentMomentum[0]; - CMy_Mnt[iMarker] = MomentMomentum[1]; - CMz_Mnt[iMarker] = MomentMomentum[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_CFx_Mnt += CFx_Mnt[iMarker]; - AllBound_CFy_Mnt += CFy_Mnt[iMarker]; - AllBound_CFz_Mnt += CFz_Mnt[iMarker]; - AllBound_CMx_Mnt += CMx_Mnt[iMarker]; - AllBound_CMy_Mnt += CMy_Mnt[iMarker]; - AllBound_CMz_Mnt += CMz_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); + 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 ---*/ @@ -4790,22 +4368,21 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { 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]; + 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]; } } } - } } @@ -4813,338 +4390,291 @@ void CEulerSolver::Momentum_Forces(CGeometry *geometry, CConfig *config) { /*--- 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; - 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_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_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; - 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_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_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_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 ---*/ + 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; + }; - 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()]; + AllBoundMntCoeff.CD = Allreduce(AllBoundMntCoeff.CD); + AllBoundMntCoeff.CL = Allreduce(AllBoundMntCoeff.CL); + AllBoundMntCoeff.CSF = Allreduce(AllBoundMntCoeff.CSF); + AllBoundMntCoeff.CEff = AllBoundMntCoeff.CL / (AllBoundMntCoeff.CD + EPS); - 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; - } + AllBoundMntCoeff.CFx = Allreduce(AllBoundMntCoeff.CFx); + AllBoundMntCoeff.CFy = Allreduce(AllBoundMntCoeff.CFy); + AllBoundMntCoeff.CFz = Allreduce(AllBoundMntCoeff.CFz); - 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; + AllBoundMntCoeff.CMx = Allreduce(AllBoundMntCoeff.CMx); + AllBoundMntCoeff.CMy = Allreduce(AllBoundMntCoeff.CMy); + AllBoundMntCoeff.CMz = Allreduce(AllBoundMntCoeff.CMz); -#endif + AllBoundMntCoeff.CoPx = Allreduce(AllBoundMntCoeff.CoPx); + AllBoundMntCoeff.CoPy = Allreduce(AllBoundMntCoeff.CoPy); + AllBoundMntCoeff.CoPz = Allreduce(AllBoundMntCoeff.CoPz); - /*--- Update the total coefficients (note that all the nodes have the same value) ---*/ + AllBoundMntCoeff.CT = Allreduce(AllBoundMntCoeff.CT); + AllBoundMntCoeff.CQ = Allreduce(AllBoundMntCoeff.CQ); + AllBoundMntCoeff.CMerit = AllBoundMntCoeff.CT / (AllBoundMntCoeff.CQ + EPS); - Total_CD += AllBound_CD_Mnt; - Total_CL += AllBound_CL_Mnt; - Total_CSF += AllBound_CSF_Mnt; - Total_CEff = Total_CL / (Total_CD + EPS); - Total_CFx += AllBound_CFx_Mnt; - Total_CFy += AllBound_CFy_Mnt; - Total_CFz += AllBound_CFz_Mnt; - Total_CMx += AllBound_CMx_Mnt; - Total_CMy += AllBound_CMy_Mnt; - Total_CMz += AllBound_CMz_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)---*/ + /*--- Add the forces on the surfaces using all the nodes ---*/ - 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]; - } + if (config->GetComm_Level() == COMM_FULL) { -} + int nMarkerMon = config->GetnMarker_Monitoring(); -void CEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver_container, - CConfig *config, unsigned short iRKStep) { - su2double *Residual, *Res_TruncError, Vol, Delta, Res; - unsigned short iVar; - unsigned long iPoint; + /*--- 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 RK_AlphaCoeff = config->Get_Alpha_RKStep(iRKStep); - bool adjoint = config->GetContinuous_Adjoint(); + su2double* buffer = new su2double [nMarkerMon]; - for (iVar = 0; iVar < nVar; iVar++) { - SetRes_RMS(iVar, 0.0); - SetRes_Max(iVar, 0.0, 0); - } + 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; inode[iPoint]->GetVolume() + - geometry->node[iPoint]->GetPeriodicVolume()); - Delta = nodes->GetDelta_Time(iPoint) / Vol; + for (iMarker_Monitoring = 0; iMarker_Monitoring < nMarkerMon; iMarker_Monitoring++) + SurfaceMntCoeff.CEff[iMarker_Monitoring] = SurfaceMntCoeff.CL[iMarker_Monitoring] / (SurfaceMntCoeff.CD[iMarker_Monitoring] + EPS); - Res_TruncError = nodes->GetResTruncError(iPoint); - Residual = LinSysRes.GetBlock(iPoint); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CFx); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CFy); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CFz); - if (!adjoint) { - for (iVar = 0; iVar < nVar; iVar++) { - Res = Residual[iVar] + Res_TruncError[iVar]; - nodes->AddSolution(iPoint,iVar, -Res*Delta*RK_AlphaCoeff); - AddRes_RMS(iVar, Res*Res); - AddRes_Max(iVar, fabs(Res), geometry->node[iPoint]->GetGlobalIndex(), geometry->node[iPoint]->GetCoord()); - } - } + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CMx); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CMy); + Allreduce_inplace(nMarkerMon, SurfaceMntCoeff.CMz); - } + delete [] buffer; - /*--- MPI solution ---*/ + } - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); +#endif - /*--- Compute the root mean square residual ---*/ + /*--- Update the total coefficients (note that all the nodes have the same value) ---*/ - SetResidual_RMS(geometry, config); + 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); - /*--- For verification cases, compute the global error metrics. ---*/ + /*--- Update the total coefficients per surface (note that all the nodes have the same value)---*/ - ComputeVerificationError(geometry, config); + 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]; + } } -void CEulerSolver::ClassicalRK4_Iteration(CGeometry *geometry, CSolver **solver_container, - CConfig *config, unsigned short iRKStep) { - su2double *Residual, *Res_TruncError, Vol, Delta, Res, tmp_time, tmp_func; - unsigned short iVar; - unsigned long iPoint; +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. ---*/ - su2double RK_FuncCoeff[4] = {1.0/6.0, 1.0/3.0, 1.0/3.0, 1.0/6.0}; - su2double RK_TimeCoeff[4] = {0.5, 0.5, 1.0, 1.0}; + 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}; - bool adjoint = config->GetContinuous_Adjoint(); + /*--- Set shared residual variables to 0 and declare + * local ones for current thread to work on. ---*/ - for (iVar = 0; iVar < nVar; iVar++) { + 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 - /*--- Update the solution ---*/ + su2double resMax[MAXNVAR] = {0.0}, resRMS[MAXNVAR] = {0.0}; + const su2double* coordMax[MAXNVAR] = {nullptr}; + unsigned long idxMax[MAXNVAR] = {0}; - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + /*--- Update the solution and residuals ---*/ - Vol = (geometry->node[iPoint]->GetVolume() + - geometry->node[iPoint]->GetPeriodicVolume()); - Delta = nodes->GetDelta_Time(iPoint) / Vol; + SU2_OMP(for schedule(static,omp_chunk_size) nowait) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - Res_TruncError = nodes->GetResTruncError(iPoint); - Residual = LinSysRes.GetBlock(iPoint); + su2double Vol = geometry->node[iPoint]->GetVolume() + geometry->node[iPoint]->GetPeriodicVolume(); + su2double Delta = nodes->GetDelta_Time(iPoint) / Vol; - tmp_time = -1.0*RK_TimeCoeff[iRKStep]*Delta; - tmp_func = -1.0*RK_FuncCoeff[iRKStep]*Delta; + const su2double* Res_TruncError = nodes->GetResTruncError(iPoint); + const su2double* Residual = LinSysRes.GetBlock(iPoint); if (!adjoint) { - for (iVar = 0; iVar < nVar; iVar++) { - Res = Residual[iVar] + Res_TruncError[iVar]; - 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); - } - - AddRes_RMS(iVar, Res*Res); - AddRes_Max(iVar, fabs(Res), geometry->node[iPoint]->GetGlobalIndex(), geometry->node[iPoint]->GetCoord()); - } - } - - } - - /*--- MPI solution ---*/ - - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); + for (unsigned short iVar = 0; iVar < nVar; iVar++) { - /*--- Compute the root mean square residual ---*/ + su2double Res = Residual[iVar] + Res_TruncError[iVar]; - SetResidual_RMS(geometry, config); + /*--- "Static" switch which should be optimized at compile time. ---*/ + switch(IntegrationType) { - /*--- For verification cases, compute the global error metrics. ---*/ + case EULER_EXPLICIT: + nodes->AddSolution(iPoint,iVar, -Res*Delta); + break; - ComputeVerificationError(geometry, config); + 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; -void CEulerSolver::ExplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - su2double *local_Residual, *local_Res_TruncError, Vol, Delta, Res; - unsigned short iVar; - unsigned long iPoint; + if (iRKStep < 3) { + /* Base Solution Update */ + nodes->AddSolution(iPoint,iVar, tmp_time*Res); - bool adjoint = config->GetContinuous_Adjoint(); + /* 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; + } - for (iVar = 0; iVar < nVar; iVar++) { - SetRes_RMS(iVar, 0.0); - SetRes_Max(iVar, 0.0, 0); + /*--- 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->node[iPoint]->GetCoord(); + } + } + } + } + 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->node[idxMax[iVar]]->GetGlobalIndex(), coordMax[iVar]); + } } + SU2_OMP_BARRIER - /*--- Update the solution ---*/ + SU2_OMP_MASTER + { + /*--- MPI solution ---*/ - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - Vol = (geometry->node[iPoint]->GetVolume() + - geometry->node[iPoint]->GetPeriodicVolume()); - Delta = nodes->GetDelta_Time(iPoint) / Vol; + InitiateComms(geometry, config, SOLUTION); + CompleteComms(geometry, config, SOLUTION); - local_Res_TruncError = nodes->GetResTruncError(iPoint); - local_Residual = LinSysRes.GetBlock(iPoint); - if (!adjoint) { - for (iVar = 0; iVar < nVar; iVar++) { - Res = local_Residual[iVar] + local_Res_TruncError[iVar]; - nodes->AddSolution(iPoint,iVar, -Res*Delta); - AddRes_RMS(iVar, Res*Res); - AddRes_Max(iVar, fabs(Res), geometry->node[iPoint]->GetGlobalIndex(), geometry->node[iPoint]->GetCoord()); - } - } + /*--- Compute the root mean square residual ---*/ + + SetResidual_RMS(geometry, config); + /*--- For verification cases, compute the global error metrics. ---*/ + + ComputeVerificationError(geometry, config); } + SU2_OMP_BARRIER - /*--- MPI solution ---*/ +} - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); +void CEulerSolver::ExplicitRK_Iteration(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iRKStep) { - /*--- Compute the root mean square residual ---*/ + Explicit_Iteration(geometry, solver_container, config, iRKStep); +} - SetResidual_RMS(geometry, config); +void CEulerSolver::ClassicalRK4_Iteration(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iRKStep) { - /*--- For verification cases, compute the global error metrics. ---*/ + Explicit_Iteration(geometry, solver_container, config, iRKStep); +} - ComputeVerificationError(geometry, config); +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) { - unsigned short iVar, jVar; - unsigned long iPoint, total_index, IterLinSol = 0; - su2double Delta, *local_Res_TruncError, Vol; + const bool adjoint = config->GetContinuous_Adjoint(); + const bool roe_turkel = config->GetKind_Upwind_Flow() == TURKEL; + const bool low_mach_prec = config->Low_Mach_Preconditioning(); - bool adjoint = config->GetContinuous_Adjoint(); - bool roe_turkel = config->GetKind_Upwind_Flow() == TURKEL; - bool low_mach_prec = config->Low_Mach_Preconditioning(); + /*--- Local matrix for preconditioning. ---*/ + su2double** LowMachPrec = nullptr; + if (roe_turkel || low_mach_prec) { + LowMachPrec = new su2double* [nVar]; + for(unsigned short iVar = 0; iVar < nVar; ++iVar) + LowMachPrec[iVar] = new su2double [nVar]; + } - /*--- Set maximum residual to zero ---*/ + /*--- Set shared residual variables to 0 and declare + * local ones for current thread to work on. ---*/ - for (iVar = 0; iVar < nVar; iVar++) { + 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}; /*--- Build implicit system ---*/ - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + SU2_OMP(for schedule(static,omp_chunk_size) nowait) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Read the residual ---*/ - local_Res_TruncError = nodes->GetResTruncError(iPoint); + su2double* local_Res_TruncError = nodes->GetResTruncError(iPoint); /*--- Read the volume ---*/ - Vol = (geometry->node[iPoint]->GetVolume() + - geometry->node[iPoint]->GetPeriodicVolume()); + su2double Vol = geometry->node[iPoint]->GetVolume() + geometry->node[iPoint]->GetPeriodicVolume(); /*--- Modify matrix diagonal to assure diagonal dominance ---*/ - if (nodes->GetDelta_Time(iPoint) != 0.0) { - Delta = Vol / nodes->GetDelta_Time(iPoint); + + su2double Delta = Vol / nodes->GetDelta_Time(iPoint); + if (roe_turkel || low_mach_prec) { - SetPreconditioner(config, iPoint); - for (iVar = 0; iVar < nVar; iVar ++ ) - for (jVar = 0; jVar < nVar; jVar ++ ) - LowMach_Precontioner[iVar][jVar] = Delta*LowMach_Precontioner[iVar][jVar]; - Jacobian.AddBlock(iPoint, iPoint, LowMach_Precontioner); + SetPreconditioner(config, iPoint, Delta, LowMachPrec); + Jacobian.AddBlock2Diag(iPoint, LowMachPrec); } else { Jacobian.AddVal2Diag(iPoint, Delta); @@ -5152,75 +4682,99 @@ void CEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver } else { Jacobian.SetVal2Diag(iPoint, 1.0); - for (iVar = 0; iVar < nVar; iVar++) { - total_index = iPoint*nVar + iVar; - LinSysRes[total_index] = 0.0; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + LinSysRes(iPoint,iVar) = 0.0; local_Res_TruncError[iVar] = 0.0; } } /*--- Right hand side of the system (-Residual) and initial guess (x = 0) ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - total_index = iPoint*nVar + iVar; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + unsigned long total_index = iPoint*nVar + iVar; LinSysRes[total_index] = - (LinSysRes[total_index] + local_Res_TruncError[iVar]); LinSysSol[total_index] = 0.0; - AddRes_RMS(iVar, LinSysRes[total_index]*LinSysRes[total_index]); - AddRes_Max(iVar, fabs(LinSysRes[total_index]), geometry->node[iPoint]->GetGlobalIndex(), geometry->node[iPoint]->GetCoord()); + + su2double Res = fabs(LinSysRes[total_index]); + resRMS[iVar] += Res*Res; + if (Res > resMax[iVar]) { + resMax[iVar] = Res; + idxMax[iVar] = iPoint; + coordMax[iVar] = geometry->node[iPoint]->GetCoord(); + } } } + SU2_OMP_CRITICAL + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + AddRes_RMS(iVar, resRMS[iVar]); + AddRes_Max(iVar, resMax[iVar], geometry->node[idxMax[iVar]]->GetGlobalIndex(), coordMax[iVar]); + } /*--- Initialize residual and solution at the ghost points ---*/ - for (iPoint = nPointDomain; iPoint < nPoint; iPoint++) { - for (iVar = 0; iVar < nVar; iVar++) { - total_index = iPoint*nVar + iVar; - LinSysRes[total_index] = 0.0; - LinSysSol[total_index] = 0.0; - } - } - - /*--- Solve or smooth the linear system ---*/ + SU2_OMP(sections nowait) + { + SU2_OMP(section) + for (unsigned long iPoint = nPointDomain; iPoint < nPoint; iPoint++) + LinSysRes.SetBlock_Zero(iPoint); - IterLinSol = System.Solve(Jacobian, LinSysRes, LinSysSol, geometry, config); + SU2_OMP(section) + for (unsigned long iPoint = nPointDomain; iPoint < nPoint; iPoint++) + LinSysSol.SetBlock_Zero(iPoint); + } - /*--- Store the value of the residual. ---*/ + /*--- Free local preconditioner. ---*/ + if (LowMachPrec) { + for(unsigned short iVar = 0; iVar < nVar; ++iVar) + delete [] LowMachPrec[iVar]; + delete [] LowMachPrec; + } - SetResLinSolver(System.GetResidual()); + /*--- Solve or smooth the linear system. ---*/ - /*--- The the number of iterations of the linear solver ---*/ + auto iter = System.Solve(Jacobian, LinSysRes, LinSysSol, geometry, config); + SU2_OMP_MASTER + { + SetIterLinSolver(iter); + SetResLinSolver(System.GetResidual()); + } + SU2_OMP_BARRIER - SetIterLinSolver(IterLinSol); ComputeUnderRelaxationFactor(solver_container, config); /*--- Update solution (system written in terms of increments) ---*/ if (!adjoint) { - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - for (iVar = 0; iVar < nVar; iVar++) { + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { + for (unsigned short iVar = 0; iVar < nVar; iVar++) { nodes->AddSolution(iPoint, iVar, nodes->GetUnderRelaxation(iPoint)*LinSysSol[iPoint*nVar+iVar]); } } } - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT); - } + SU2_OMP_MASTER + { + for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { + InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT); + CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT); + } - /*--- MPI solution ---*/ + /*--- MPI solution ---*/ - InitiateComms(geometry, config, SOLUTION); - CompleteComms(geometry, config, SOLUTION); + InitiateComms(geometry, config, SOLUTION); + CompleteComms(geometry, config, SOLUTION); - /*--- Compute the root mean square residual ---*/ + /*--- Compute the root mean square residual ---*/ - SetResidual_RMS(geometry, config); + SetResidual_RMS(geometry, config); - /*--- For verification cases, compute the global error metrics. ---*/ + /*--- For verification cases, compute the global error metrics. ---*/ - ComputeVerificationError(geometry, config); + ComputeVerificationError(geometry, config); + } + SU2_OMP_BARRIER } @@ -5229,11 +4783,13 @@ void CEulerSolver::ComputeUnderRelaxationFactor(CSolver **solver_container, CCon /* Loop over the solution update given by relaxing the linear system for this nonlinear iteration. */ - su2double localUnderRelaxation = 1.0; const su2double allowableRatio = 0.2; + + SU2_OMP_FOR_STAT(omp_chunk_size) for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - localUnderRelaxation = 1.0; + su2double localUnderRelaxation = 1.0; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { /* We impose a limit on the maximum percentage that the @@ -5309,7 +4865,9 @@ void CEulerSolver::SetPrimitive_Limiter(CGeometry *geometry, CConfig *config) { *geometry, *config, 0, nPrimVarGrad, primitives, gradient, primMin, primMax, limiter); } -void CEulerSolver::SetPreconditioner(CConfig *config, unsigned long iPoint) { +void CEulerSolver::SetPreconditioner(const CConfig *config, unsigned long iPoint, + su2double delta, su2double** preconditioner) const { + unsigned short iDim, jDim, iVar, jVar; su2double local_Mach, rho, enthalpy, soundspeed, sq_vel; su2double *U_i = NULL; @@ -5333,30 +4891,32 @@ void CEulerSolver::SetPreconditioner(CConfig *config, unsigned long iPoint) { sq_vel = nodes->GetVelocity2(iPoint); /*---Calculating the inverse of the preconditioning matrix that multiplies the time derivative */ - LowMach_Precontioner[0][0] = 0.5*sq_vel; - LowMach_Precontioner[0][nVar-1] = 1.0; + preconditioner[0][0] = 0.5*sq_vel; + preconditioner[0][nVar-1] = 1.0; for (iDim = 0; iDim < nDim; iDim ++) - LowMach_Precontioner[0][1+iDim] = -1.0*U_i[iDim+1]/rho; + preconditioner[0][1+iDim] = -1.0*U_i[iDim+1]/rho; for (iDim = 0; iDim < nDim; iDim ++) { - LowMach_Precontioner[iDim+1][0] = 0.5*sq_vel*U_i[iDim+1]/rho; - LowMach_Precontioner[iDim+1][nVar-1] = U_i[iDim+1]/rho; + preconditioner[iDim+1][0] = 0.5*sq_vel*U_i[iDim+1]/rho; + preconditioner[iDim+1][nVar-1] = U_i[iDim+1]/rho; for (jDim = 0; jDim < nDim; jDim ++) { - LowMach_Precontioner[iDim+1][1+jDim] = -1.0*U_i[jDim+1]/rho*U_i[iDim+1]/rho; + preconditioner[iDim+1][1+jDim] = -1.0*U_i[jDim+1]/rho*U_i[iDim+1]/rho; } } - LowMach_Precontioner[nVar-1][0] = 0.5*sq_vel*enthalpy; - LowMach_Precontioner[nVar-1][nVar-1] = enthalpy; + preconditioner[nVar-1][0] = 0.5*sq_vel*enthalpy; + preconditioner[nVar-1][nVar-1] = enthalpy; for (iDim = 0; iDim < nDim; iDim ++) - LowMach_Precontioner[nVar-1][1+iDim] = -1.0*U_i[iDim+1]/rho*enthalpy; + preconditioner[nVar-1][1+iDim] = -1.0*U_i[iDim+1]/rho*enthalpy; for (iVar = 0; iVar < nVar; iVar ++ ) { for (jVar = 0; jVar < nVar; jVar ++ ) { - LowMach_Precontioner[iVar][jVar] = (parameter - 1.0) * ((Gamma-1.0)/(soundspeed*soundspeed))*LowMach_Precontioner[iVar][jVar]; + preconditioner[iVar][jVar] = (parameter - 1.0) * ((Gamma-1.0)/(soundspeed*soundspeed))*preconditioner[iVar][jVar]; if (iVar == jVar) - LowMach_Precontioner[iVar][iVar] += 1.0; + preconditioner[iVar][iVar] += 1.0; + + preconditioner[iVar][jVar] *= delta; } } @@ -5376,74 +4936,55 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns NetThrust = 0.0, GrossThrust = 0.0, Power = 0.0, MassFlow = 0.0, Mach = 0.0, Force = 0.0; bool ReverseFlow, Engine = false, Pair = true; - su2double Gas_Constant = config->GetGas_ConstantND(); - su2double Cp = Gas_Constant*Gamma / (Gamma-1.0); - su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; - su2double Beta = config->GetAoS()*PI_NUMBER/180.0; - bool write_heads = ((((config->GetInnerIter() % (config->GetWrt_Con_Freq()*40)) == 0) && (config->GetInnerIter()!= 0)) - || (config->GetInnerIter() == 1)); - bool Evaluate_BC = ((((config->GetInnerIter() % (config->GetWrt_Con_Freq()*40)) == 0)) - || (config->GetInnerIter() == 1) || (config->GetDiscrete_Adjoint())); + su2double Gas_Constant = config->GetGas_ConstantND(); + su2double Cp = Gas_Constant*Gamma / (Gamma-1.0); + su2double Alpha = config->GetAoA()*PI_NUMBER/180.0; + su2double Beta = config->GetAoS()*PI_NUMBER/180.0; + bool write_heads = ((((config->GetInnerIter() % (config->GetWrt_Con_Freq()*40)) == 0) && (config->GetInnerIter()!= 0)) || (config->GetInnerIter() == 1)); + bool Evaluate_BC = ((((config->GetInnerIter() % (config->GetWrt_Con_Freq()*40)) == 0)) || (config->GetInnerIter() == 1) || (config->GetDiscrete_Adjoint())); if ((config->GetnMarker_EngineInflow() != 0) || (config->GetnMarker_EngineExhaust() != 0)) Engine = true; if ((config->GetnMarker_ActDiskInlet() != 0) || (config->GetnMarker_ActDiskOutlet() != 0)) Engine = false; if ((config->GetnMarker_EngineInflow()) != (config->GetnMarker_EngineExhaust())) Pair = false; - if (Engine) { nMarker_Inlet = config->GetnMarker_EngineInflow(); nMarker_Outlet = config->GetnMarker_EngineExhaust(); } - else { nMarker_Inlet = config->GetnMarker_ActDiskInlet(); nMarker_Outlet = config->GetnMarker_ActDiskOutlet(); } + else { nMarker_Inlet = config->GetnMarker_ActDiskInlet(); nMarker_Outlet = config->GetnMarker_ActDiskOutlet(); } /*--- Evaluate the MPI for the actuator disk IO ---*/ if (Evaluate_BC) { - /*--- Allocate memory ---*/ - - su2double *Inlet_MassFlow = new su2double [config->GetnMarker_All()]; - su2double *Inlet_ReverseMassFlow = new su2double [config->GetnMarker_All()]; - su2double *Inlet_Pressure = new su2double [config->GetnMarker_All()]; - su2double *Inlet_Mach = new su2double [config->GetnMarker_All()]; - su2double *Inlet_MaxPressure = new su2double [config->GetnMarker_All()]; - su2double *Inlet_MinPressure = new su2double [config->GetnMarker_All()]; - su2double *Inlet_TotalPressure = new su2double [config->GetnMarker_All()]; - su2double *Inlet_Temperature = new su2double [config->GetnMarker_All()]; - su2double *Inlet_TotalTemperature = new su2double [config->GetnMarker_All()]; - su2double *Inlet_Area = new su2double [config->GetnMarker_All()]; - su2double *Inlet_RamDrag = new su2double [config->GetnMarker_All()]; - su2double *Inlet_Force = new su2double [config->GetnMarker_All()]; - su2double *Inlet_Power = new su2double [config->GetnMarker_All()]; - su2double *Inlet_XCG = new su2double [config->GetnMarker_All()]; - su2double *Inlet_YCG = new su2double [config->GetnMarker_All()]; - su2double *Inlet_ZCG = new su2double [config->GetnMarker_All()]; - - su2double *Outlet_MassFlow = new su2double [config->GetnMarker_All()]; - su2double *Outlet_Pressure = new su2double [config->GetnMarker_All()]; - su2double *Outlet_TotalPressure = new su2double [config->GetnMarker_All()]; - su2double *Outlet_Temperature = new su2double [config->GetnMarker_All()]; - su2double *Outlet_TotalTemperature = new su2double [config->GetnMarker_All()]; - su2double *Outlet_Area = new su2double [config->GetnMarker_All()]; - su2double *Outlet_GrossThrust = new su2double [config->GetnMarker_All()]; - su2double *Outlet_Force = new su2double [config->GetnMarker_All()]; - su2double *Outlet_Power = new su2double [config->GetnMarker_All()]; + su2double *Inlet_MassFlow = new su2double [config->GetnMarker_All()](); + su2double *Inlet_ReverseMassFlow = new su2double [config->GetnMarker_All()](); + su2double *Inlet_Pressure = new su2double [config->GetnMarker_All()](); + su2double *Inlet_Mach = new su2double [config->GetnMarker_All()](); + su2double *Inlet_MaxPressure = new su2double [config->GetnMarker_All()](); + su2double *Inlet_MinPressure = new su2double [config->GetnMarker_All()](); + su2double *Inlet_TotalPressure = new su2double [config->GetnMarker_All()](); + su2double *Inlet_Temperature = new su2double [config->GetnMarker_All()](); + su2double *Inlet_TotalTemperature = new su2double [config->GetnMarker_All()](); + su2double *Inlet_Area = new su2double [config->GetnMarker_All()](); + su2double *Inlet_RamDrag = new su2double [config->GetnMarker_All()](); + su2double *Inlet_Force = new su2double [config->GetnMarker_All()](); + su2double *Inlet_Power = new su2double [config->GetnMarker_All()](); + su2double *Inlet_XCG = new su2double [config->GetnMarker_All()](); + su2double *Inlet_YCG = new su2double [config->GetnMarker_All()](); + su2double *Inlet_ZCG = new su2double [config->GetnMarker_All()](); + + su2double *Outlet_MassFlow = new su2double [config->GetnMarker_All()](); + su2double *Outlet_Pressure = new su2double [config->GetnMarker_All()](); + su2double *Outlet_TotalPressure = new su2double [config->GetnMarker_All()](); + su2double *Outlet_Temperature = new su2double [config->GetnMarker_All()](); + su2double *Outlet_TotalTemperature = new su2double [config->GetnMarker_All()](); + su2double *Outlet_Area = new su2double [config->GetnMarker_All()](); + su2double *Outlet_GrossThrust = new su2double [config->GetnMarker_All()](); + su2double *Outlet_Force = new su2double [config->GetnMarker_All()](); + su2double *Outlet_Power = new su2double [config->GetnMarker_All()](); /*--- Comute MassFlow, average temp, press, etc. ---*/ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - Inlet_MassFlow[iMarker] = 0.0; Inlet_ReverseMassFlow[iMarker] = 0.0; Inlet_MinPressure[iMarker] = 0.0; - Inlet_Pressure[iMarker] = 0.0; Inlet_Mach[iMarker] = 0.0; Inlet_Temperature[iMarker] = 0.0; - Inlet_MinPressure[iMarker] = +1E10; Inlet_MaxPressure[iMarker] = -1E10; Inlet_Power[iMarker] = 0.0; - Inlet_TotalPressure[iMarker] = 0.0; Inlet_TotalTemperature[iMarker] = 0.0; - Inlet_Area[iMarker] = 0.0; - Inlet_RamDrag[iMarker] = 0.0; Inlet_Force[iMarker] = 0.0; - Inlet_XCG[iMarker] = 0.0; Inlet_YCG[iMarker] = 0.0; Inlet_ZCG[iMarker] = 0.0; - - Outlet_MassFlow[iMarker] = 0.0; - Outlet_Pressure[iMarker] = 0.0; Outlet_Temperature[iMarker] = 0.0; - Outlet_TotalPressure[iMarker] = 0.0; Outlet_TotalTemperature[iMarker] = 0.0; - Outlet_Area[iMarker] = 0.0; - Outlet_GrossThrust[iMarker] = 0.0; Outlet_Force[iMarker] = 0.0; Outlet_Power[iMarker] = 0.0; - MinPressure = +1E10; MaxPressure = -1E10; if ((config->GetMarker_All_KindBC(iMarker) == ACTDISK_INLET) || @@ -5459,11 +5000,11 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns geometry->vertex[iMarker][iVertex]->GetNormal(Vector); - Temperature = V_inlet[0]; - Pressure = V_inlet[nDim+1]; + Temperature = V_inlet[0]; + Pressure = V_inlet[nDim+1]; - Density = V_inlet[nDim+2]; - SoundSpeed = sqrt(Gamma*Pressure/Density); + Density = V_inlet[nDim+2]; + SoundSpeed = sqrt(Gamma*Pressure/Density); Velocity2 = 0.0; Area = 0.0; MassFlow = 0.0; Vel_Infty2 =0.0; for (iDim = 0; iDim < nDim; iDim++) { @@ -5478,15 +5019,15 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns for (iDim = 0; iDim < nDim; iDim++) { Vn -= Velocity[iDim]*Vector[iDim]/Area; } if (Vn < 0.0) { ReverseFlow = true; } - Vel_Infty = sqrt (Vel_Infty2); - Area = sqrt (Area); - Mach = sqrt(Velocity2)/SoundSpeed; - TotalPressure = Pressure * pow( 1.0 + Mach * Mach * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0)); - TotalTemperature = Temperature * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0)); - MinPressure = min(MinPressure, TotalPressure); - MaxPressure = max(MaxPressure, TotalPressure); + Vel_Infty = sqrt (Vel_Infty2); + Area = sqrt (Area); + Mach = sqrt(Velocity2)/SoundSpeed; + TotalPressure = Pressure * pow( 1.0 + Mach * Mach * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0)); + TotalTemperature = Temperature * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0)); + MinPressure = min(MinPressure, TotalPressure); + MaxPressure = max(MaxPressure, TotalPressure); - RamDrag = MassFlow * Vel_Infty; + RamDrag = MassFlow * Vel_Infty; Inlet_MassFlow[iMarker] += MassFlow; Inlet_Pressure[iMarker] += Pressure*MassFlow; @@ -5501,14 +5042,14 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns Inlet_Power[iMarker] += MassFlow*Cp*TotalTemperature; if (ReverseFlow) Inlet_ReverseMassFlow[iMarker] += MassFlow; - su2double Inlet_ForceX = -(Pressure - Pressure_Inf)*Vector[0] + MassFlow*Velocity[0]; + su2double Inlet_ForceX = -(Pressure - Pressure_Inf)*Vector[0] + MassFlow*Velocity[0]; su2double Inlet_ForceY = -(Pressure - Pressure_Inf)*Vector[1] + MassFlow*Velocity[1]; su2double Inlet_ForceZ = 0.0; if (nDim == 3) Inlet_ForceZ = -(Pressure - Pressure_Inf)*Vector[2] + MassFlow*Velocity[2]; Inlet_Force[iMarker] += Inlet_ForceX*cos(Alpha)*cos(Beta) + Inlet_ForceY*sin(Beta) +Inlet_ForceZ*sin(Alpha)*cos(Beta); - Inlet_XCG[iMarker] += geometry->node[iPoint]->GetCoord(0)*Area; - Inlet_YCG[iMarker] += geometry->node[iPoint]->GetCoord(1)*Area; + Inlet_XCG[iMarker] += geometry->node[iPoint]->GetCoord(0)*Area; + Inlet_YCG[iMarker] += geometry->node[iPoint]->GetCoord(1)*Area; if (nDim == 3) Inlet_ZCG[iMarker] += geometry->node[iPoint]->GetCoord(2)*Area; } @@ -5529,10 +5070,10 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns geometry->vertex[iMarker][iVertex]->GetNormal(Vector); - Temperature = V_outlet[0]; - Pressure = V_outlet[nDim+1]; + Temperature = V_outlet[0]; + Pressure = V_outlet[nDim+1]; - Density = V_outlet[nDim+2]; + Density = V_outlet[nDim+2]; SoundSpeed = sqrt(Gamma*Pressure/Density); Velocity2 = 0.0; Area = 0.0; MassFlow = 0.0; Vel_Infty2 = 0.0; @@ -5544,26 +5085,26 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns MassFlow += Vector[iDim]*Velocity[iDim]*Density; } - Vel_Infty = sqrt (Vel_Infty2); - Area = sqrt (Area); - Mach = sqrt(Velocity2)/SoundSpeed; - TotalPressure = Pressure * pow( 1.0 + Mach * Mach * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0)); - TotalTemperature = Temperature * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0)); - VelocityJet = sqrt(Velocity2) ; - - GrossThrust = MassFlow * VelocityJet; - - Outlet_MassFlow[iMarker] += MassFlow; - Outlet_Pressure[iMarker] += Pressure*MassFlow; - Outlet_TotalPressure[iMarker] += TotalPressure*MassFlow; - Outlet_Temperature[iMarker] += Temperature*MassFlow; - Outlet_TotalTemperature[iMarker] += TotalTemperature*MassFlow; - Outlet_Area[iMarker] += Area; - Outlet_GrossThrust[iMarker] += GrossThrust; + Vel_Infty = sqrt (Vel_Infty2); + Area = sqrt (Area); + Mach = sqrt(Velocity2)/SoundSpeed; + TotalPressure = Pressure * pow( 1.0 + Mach * Mach * 0.5 * (Gamma - 1.0), Gamma / (Gamma - 1.0)); + TotalTemperature = Temperature * (1.0 + Mach * Mach * 0.5 * (Gamma - 1.0)); + VelocityJet = sqrt(Velocity2) ; + + GrossThrust = MassFlow * VelocityJet; + + Outlet_MassFlow[iMarker] += MassFlow; + Outlet_Pressure[iMarker] += Pressure*MassFlow; + Outlet_TotalPressure[iMarker] += TotalPressure*MassFlow; + Outlet_Temperature[iMarker] += Temperature*MassFlow; + Outlet_TotalTemperature[iMarker] += TotalTemperature*MassFlow; + Outlet_Area[iMarker] += Area; + Outlet_GrossThrust[iMarker] += GrossThrust; Outlet_Power[iMarker] += MassFlow*Cp*TotalTemperature; su2double Outlet_ForceX = -(Pressure - Pressure_Inf)*Vector[0] -MassFlow*Velocity[0]; - su2double Outlet_ForceY = -(Pressure - Pressure_Inf)*Vector[1] -MassFlow*Velocity[1]; + su2double Outlet_ForceY = -(Pressure - Pressure_Inf)*Vector[1] -MassFlow*Velocity[1]; su2double Outlet_ForceZ = 0.0; if (nDim == 3) Outlet_ForceZ = -(Pressure - Pressure_Inf)*Vector[2] -MassFlow*Velocity[2]; @@ -5579,117 +5120,59 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns /*--- Copy to the appropriate structure ---*/ - su2double *Inlet_MassFlow_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_ReverseMassFlow_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_Temperature_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_TotalTemperature_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_Pressure_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_Mach_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_MinPressure_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_MaxPressure_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_Power_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_TotalPressure_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_RamDrag_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_Force_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_Area_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_XCG_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_YCG_Local = new su2double [nMarker_Inlet]; - su2double *Inlet_ZCG_Local = new su2double [nMarker_Inlet]; - - su2double *Inlet_MassFlow_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_ReverseMassFlow_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_Pressure_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_Mach_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_MinPressure_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_MaxPressure_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_Power_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_TotalPressure_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_Temperature_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_TotalTemperature_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_RamDrag_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_Force_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_Area_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_XCG_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_YCG_Total = new su2double [nMarker_Inlet]; - su2double *Inlet_ZCG_Total = new su2double [nMarker_Inlet]; - - for (iMarker_Inlet = 0; iMarker_Inlet < nMarker_Inlet; iMarker_Inlet++) { - Inlet_MassFlow_Local[iMarker_Inlet] = 0.0; - Inlet_ReverseMassFlow_Local[iMarker_Inlet] = 0.0; - Inlet_Pressure_Local[iMarker_Inlet] = 0.0; - Inlet_Mach_Local[iMarker_Inlet] = 0.0; - Inlet_MinPressure_Local[iMarker_Inlet] = 0.0; - Inlet_MaxPressure_Local[iMarker_Inlet] = 0.0; - Inlet_TotalPressure_Local[iMarker_Inlet] = 0.0; - Inlet_Temperature_Local[iMarker_Inlet] = 0.0; - Inlet_TotalTemperature_Local[iMarker_Inlet] = 0.0; - Inlet_RamDrag_Local[iMarker_Inlet] = 0.0; - Inlet_Force_Local[iMarker_Inlet] = 0.0; - Inlet_Power_Local[iMarker_Inlet] = 0.0; - Inlet_Area_Local[iMarker_Inlet] = 0.0; - Inlet_XCG_Local[iMarker_Inlet] = 0.0; - Inlet_YCG_Local[iMarker_Inlet] = 0.0; - Inlet_ZCG_Local[iMarker_Inlet] = 0.0; - - Inlet_MassFlow_Total[iMarker_Inlet] = 0.0; - Inlet_ReverseMassFlow_Total[iMarker_Inlet] = 0.0; - Inlet_Pressure_Total[iMarker_Inlet] = 0.0; - Inlet_Mach_Total[iMarker_Inlet] = 0.0; - Inlet_MinPressure_Total[iMarker_Inlet] = 0.0; - Inlet_MaxPressure_Total[iMarker_Inlet] = 0.0; - Inlet_TotalPressure_Total[iMarker_Inlet] = 0.0; - Inlet_Temperature_Total[iMarker_Inlet] = 0.0; - Inlet_TotalTemperature_Total[iMarker_Inlet] = 0.0; - Inlet_RamDrag_Total[iMarker_Inlet] = 0.0; - Inlet_Force_Total[iMarker_Inlet] = 0.0; - Inlet_Power_Total[iMarker_Inlet] = 0.0; - Inlet_Area_Total[iMarker_Inlet] = 0.0; - Inlet_XCG_Total[iMarker_Inlet] = 0.0; - Inlet_YCG_Total[iMarker_Inlet] = 0.0; - Inlet_ZCG_Total[iMarker_Inlet] = 0.0; - } - - su2double *Outlet_MassFlow_Local = new su2double [nMarker_Outlet]; - su2double *Outlet_Pressure_Local = new su2double [nMarker_Outlet]; - su2double *Outlet_TotalPressure_Local = new su2double [nMarker_Outlet]; - su2double *Outlet_Temperature_Local = new su2double [nMarker_Outlet]; - su2double *Outlet_TotalTemperature_Local = new su2double [nMarker_Outlet]; - su2double *Outlet_GrossThrust_Local = new su2double [nMarker_Outlet]; - su2double *Outlet_Force_Local = new su2double [nMarker_Outlet]; - su2double *Outlet_Power_Local = new su2double [nMarker_Outlet]; - su2double *Outlet_Area_Local = new su2double [nMarker_Outlet]; - - su2double *Outlet_MassFlow_Total = new su2double [nMarker_Outlet]; - su2double *Outlet_Pressure_Total = new su2double [nMarker_Outlet]; - su2double *Outlet_TotalPressure_Total = new su2double [nMarker_Outlet]; - su2double *Outlet_Temperature_Total = new su2double [nMarker_Outlet]; - su2double *Outlet_TotalTemperature_Total = new su2double [nMarker_Outlet]; - su2double *Outlet_GrossThrust_Total = new su2double [nMarker_Outlet]; - su2double *Outlet_Force_Total = new su2double [nMarker_Outlet]; - su2double *Outlet_Power_Total = new su2double [nMarker_Outlet]; - su2double *Outlet_Area_Total = new su2double [nMarker_Outlet]; - - for (iMarker_Outlet = 0; iMarker_Outlet < nMarker_Outlet; iMarker_Outlet++) { - Outlet_MassFlow_Local[iMarker_Outlet] = 0.0; - Outlet_Pressure_Local[iMarker_Outlet] = 0.0; - Outlet_TotalPressure_Local[iMarker_Outlet] = 0.0; - Outlet_Temperature_Local[iMarker_Outlet] = 0.0; - Outlet_TotalTemperature_Local[iMarker_Outlet] = 0.0; - Outlet_GrossThrust_Local[iMarker_Outlet] = 0.0; - Outlet_Force_Local[iMarker_Outlet] = 0.0; - Outlet_Power_Local[iMarker_Outlet] = 0.0; - Outlet_Area_Local[iMarker_Outlet] = 0.0; - - Outlet_MassFlow_Total[iMarker_Outlet] = 0.0; - Outlet_Pressure_Total[iMarker_Outlet] = 0.0; - Outlet_TotalPressure_Total[iMarker_Outlet] = 0.0; - Outlet_Temperature_Total[iMarker_Outlet] = 0.0; - Outlet_TotalTemperature_Total[iMarker_Outlet] = 0.0; - Outlet_GrossThrust_Total[iMarker_Outlet] = 0.0; - Outlet_Force_Total[iMarker_Outlet] = 0.0; - Outlet_Power_Total[iMarker_Outlet] = 0.0; - Outlet_Area_Total[iMarker_Outlet] = 0.0; - } + su2double *Inlet_MassFlow_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_ReverseMassFlow_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_Temperature_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_TotalTemperature_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_Pressure_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_Mach_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_MinPressure_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_MaxPressure_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_Power_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_TotalPressure_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_RamDrag_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_Force_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_Area_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_XCG_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_YCG_Local = new su2double [nMarker_Inlet](); + su2double *Inlet_ZCG_Local = new su2double [nMarker_Inlet](); + + su2double *Inlet_MassFlow_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_ReverseMassFlow_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_Pressure_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_Mach_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_MinPressure_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_MaxPressure_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_Power_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_TotalPressure_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_Temperature_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_TotalTemperature_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_RamDrag_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_Force_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_Area_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_XCG_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_YCG_Total = new su2double [nMarker_Inlet](); + su2double *Inlet_ZCG_Total = new su2double [nMarker_Inlet](); + + su2double *Outlet_MassFlow_Local = new su2double [nMarker_Outlet](); + su2double *Outlet_Pressure_Local = new su2double [nMarker_Outlet](); + su2double *Outlet_TotalPressure_Local = new su2double [nMarker_Outlet](); + su2double *Outlet_Temperature_Local = new su2double [nMarker_Outlet](); + su2double *Outlet_TotalTemperature_Local = new su2double [nMarker_Outlet](); + su2double *Outlet_GrossThrust_Local = new su2double [nMarker_Outlet](); + su2double *Outlet_Force_Local = new su2double [nMarker_Outlet](); + su2double *Outlet_Power_Local = new su2double [nMarker_Outlet](); + su2double *Outlet_Area_Local = new su2double [nMarker_Outlet](); + + su2double *Outlet_MassFlow_Total = new su2double [nMarker_Outlet](); + su2double *Outlet_Pressure_Total = new su2double [nMarker_Outlet](); + su2double *Outlet_TotalPressure_Total = new su2double [nMarker_Outlet](); + su2double *Outlet_Temperature_Total = new su2double [nMarker_Outlet](); + su2double *Outlet_TotalTemperature_Total = new su2double [nMarker_Outlet](); + su2double *Outlet_GrossThrust_Total = new su2double [nMarker_Outlet](); + su2double *Outlet_Force_Total = new su2double [nMarker_Outlet](); + su2double *Outlet_Power_Total = new su2double [nMarker_Outlet](); + su2double *Outlet_Area_Total = new su2double [nMarker_Outlet](); /*--- Copy the values to the local array for MPI ---*/ @@ -5702,22 +5185,22 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns if (config->GetMarker_All_KindBC(iMarker) == ENGINE_INFLOW) Inlet_TagBound = config->GetMarker_EngineInflow_TagBound(iMarker_Inlet); if (config->GetMarker_All_TagBound(iMarker) == Inlet_TagBound) { - Inlet_MassFlow_Local[iMarker_Inlet] += Inlet_MassFlow[iMarker]; - Inlet_ReverseMassFlow_Local[iMarker_Inlet] += Inlet_ReverseMassFlow[iMarker]; - Inlet_Pressure_Local[iMarker_Inlet] += Inlet_Pressure[iMarker]; - Inlet_Mach_Local[iMarker_Inlet] += Inlet_Mach[iMarker]; - Inlet_MinPressure_Local[iMarker_Inlet] += Inlet_MinPressure[iMarker]; + Inlet_MassFlow_Local[iMarker_Inlet] += Inlet_MassFlow[iMarker]; + Inlet_ReverseMassFlow_Local[iMarker_Inlet] += Inlet_ReverseMassFlow[iMarker]; + Inlet_Pressure_Local[iMarker_Inlet] += Inlet_Pressure[iMarker]; + Inlet_Mach_Local[iMarker_Inlet] += Inlet_Mach[iMarker]; + Inlet_MinPressure_Local[iMarker_Inlet] += Inlet_MinPressure[iMarker]; Inlet_MaxPressure_Local[iMarker_Inlet] += Inlet_MaxPressure[iMarker]; - Inlet_TotalPressure_Local[iMarker_Inlet] += Inlet_TotalPressure[iMarker]; - Inlet_Temperature_Local[iMarker_Inlet] += Inlet_Temperature[iMarker]; - Inlet_TotalTemperature_Local[iMarker_Inlet] += Inlet_TotalTemperature[iMarker]; - Inlet_RamDrag_Local[iMarker_Inlet] += Inlet_RamDrag[iMarker]; - Inlet_Force_Local[iMarker_Inlet] += Inlet_Force[iMarker]; - Inlet_Power_Local[iMarker_Inlet] += Inlet_Power[iMarker]; - Inlet_Area_Local[iMarker_Inlet] += Inlet_Area[iMarker]; - Inlet_XCG_Local[iMarker_Inlet] += Inlet_XCG[iMarker]; - Inlet_YCG_Local[iMarker_Inlet] += Inlet_YCG[iMarker]; - if (nDim == 3) Inlet_ZCG_Local[iMarker_Inlet] += Inlet_ZCG[iMarker]; + Inlet_TotalPressure_Local[iMarker_Inlet] += Inlet_TotalPressure[iMarker]; + Inlet_Temperature_Local[iMarker_Inlet] += Inlet_Temperature[iMarker]; + Inlet_TotalTemperature_Local[iMarker_Inlet] += Inlet_TotalTemperature[iMarker]; + Inlet_RamDrag_Local[iMarker_Inlet] += Inlet_RamDrag[iMarker]; + Inlet_Force_Local[iMarker_Inlet] += Inlet_Force[iMarker]; + Inlet_Power_Local[iMarker_Inlet] += Inlet_Power[iMarker]; + Inlet_Area_Local[iMarker_Inlet] += Inlet_Area[iMarker]; + Inlet_XCG_Local[iMarker_Inlet] += Inlet_XCG[iMarker]; + Inlet_YCG_Local[iMarker_Inlet] += Inlet_YCG[iMarker]; + if (nDim == 3) Inlet_ZCG_Local[iMarker_Inlet] += Inlet_ZCG[iMarker]; } } @@ -5730,15 +5213,15 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns if (config->GetMarker_All_KindBC(iMarker) == ENGINE_EXHAUST) Outlet_TagBound = config->GetMarker_EngineExhaust_TagBound(iMarker_Outlet); if (config->GetMarker_All_TagBound(iMarker) == Outlet_TagBound) { - Outlet_MassFlow_Local[iMarker_Outlet] += Outlet_MassFlow[iMarker]; - Outlet_Pressure_Local[iMarker_Outlet] += Outlet_Pressure[iMarker]; + Outlet_MassFlow_Local[iMarker_Outlet] += Outlet_MassFlow[iMarker]; + Outlet_Pressure_Local[iMarker_Outlet] += Outlet_Pressure[iMarker]; Outlet_TotalPressure_Local[iMarker_Outlet] += Outlet_TotalPressure[iMarker]; - Outlet_Temperature_Local[iMarker_Outlet] += Outlet_Temperature[iMarker]; - Outlet_TotalTemperature_Local[iMarker_Outlet] += Outlet_TotalTemperature[iMarker]; - Outlet_GrossThrust_Local[iMarker_Outlet] += Outlet_GrossThrust[iMarker]; - Outlet_Force_Local[iMarker_Outlet] += Outlet_Force[iMarker]; - Outlet_Power_Local[iMarker_Outlet] += Outlet_Power[iMarker]; - Outlet_Area_Local[iMarker_Outlet] += Outlet_Area[iMarker]; + Outlet_Temperature_Local[iMarker_Outlet] += Outlet_Temperature[iMarker]; + Outlet_TotalTemperature_Local[iMarker_Outlet] += Outlet_TotalTemperature[iMarker]; + Outlet_GrossThrust_Local[iMarker_Outlet] += Outlet_GrossThrust[iMarker]; + Outlet_Force_Local[iMarker_Outlet] += Outlet_Force[iMarker]; + Outlet_Power_Local[iMarker_Outlet] += Outlet_Power[iMarker]; + Outlet_Area_Local[iMarker_Outlet] += Outlet_Area[iMarker]; } } @@ -5756,15 +5239,13 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns if (!ActDisk) { for (iMarker_Inlet = 0; iMarker_Inlet < nMarker_Inlet; iMarker_Inlet++) { - Inlet_MinPressure_Local[iMarker_Inlet] = 1E10; + Inlet_MinPressure_Local[iMarker_Inlet] = 1E10; Inlet_MaxPressure_Local[iMarker_Inlet] = -1E10; } } /*--- All the ranks to compute the total value ---*/ -#ifdef HAVE_MPI - SU2_MPI::Allreduce(Inlet_MassFlow_Local, Inlet_MassFlow_Total, nMarker_Inlet, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); SU2_MPI::Allreduce(Inlet_ReverseMassFlow_Local, Inlet_ReverseMassFlow_Total, nMarker_Inlet, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); SU2_MPI::Allreduce(Inlet_Pressure_Local, Inlet_Pressure_Total, nMarker_Inlet, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); @@ -5792,41 +5273,6 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns SU2_MPI::Allreduce(Outlet_Power_Local, Outlet_Power_Total, nMarker_Outlet, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); SU2_MPI::Allreduce(Outlet_Area_Local, Outlet_Area_Total, nMarker_Outlet, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); -#else - - for (iMarker_Inlet = 0; iMarker_Inlet < nMarker_Inlet; iMarker_Inlet++) { - Inlet_MassFlow_Total[iMarker_Inlet] = Inlet_MassFlow_Local[iMarker_Inlet]; - Inlet_ReverseMassFlow_Total[iMarker_Inlet] = Inlet_ReverseMassFlow_Local[iMarker_Inlet]; - Inlet_Pressure_Total[iMarker_Inlet] = Inlet_Pressure_Local[iMarker_Inlet]; - Inlet_Mach_Total[iMarker_Inlet] = Inlet_Mach_Local[iMarker_Inlet]; - Inlet_MinPressure_Total[iMarker_Inlet] = Inlet_MinPressure_Local[iMarker_Inlet]; - Inlet_MaxPressure_Total[iMarker_Inlet] = Inlet_MaxPressure_Local[iMarker_Inlet]; - Inlet_TotalPressure_Total[iMarker_Inlet] = Inlet_TotalPressure_Local[iMarker_Inlet]; - Inlet_Temperature_Total[iMarker_Inlet] = Inlet_Temperature_Local[iMarker_Inlet]; - Inlet_TotalTemperature_Total[iMarker_Inlet] = Inlet_TotalTemperature_Local[iMarker_Inlet]; - Inlet_RamDrag_Total[iMarker_Inlet] = Inlet_RamDrag_Local[iMarker_Inlet]; - Inlet_Force_Total[iMarker_Inlet] = Inlet_Force_Local[iMarker_Inlet]; - Inlet_Power_Total[iMarker_Inlet] = Inlet_Power_Local[iMarker_Inlet]; - Inlet_Area_Total[iMarker_Inlet] = Inlet_Area_Local[iMarker_Inlet]; - Inlet_XCG_Total[iMarker_Inlet] = Inlet_XCG_Local[iMarker_Inlet]; - Inlet_YCG_Total[iMarker_Inlet] = Inlet_YCG_Local[iMarker_Inlet]; - if (nDim == 3) Inlet_ZCG_Total[iMarker_Inlet] = Inlet_ZCG_Local[iMarker_Inlet]; - } - - for (iMarker_Outlet = 0; iMarker_Outlet < nMarker_Outlet; iMarker_Outlet++) { - Outlet_MassFlow_Total[iMarker_Outlet] = Outlet_MassFlow_Local[iMarker_Outlet]; - Outlet_Pressure_Total[iMarker_Outlet] = Outlet_Pressure_Local[iMarker_Outlet]; - Outlet_TotalPressure_Total[iMarker_Outlet] = Outlet_TotalPressure_Local[iMarker_Outlet]; - Outlet_Temperature_Total[iMarker_Outlet] = Outlet_Temperature_Local[iMarker_Outlet]; - Outlet_TotalTemperature_Total[iMarker_Outlet] = Outlet_TotalTemperature_Local[iMarker_Outlet]; - Outlet_GrossThrust_Total[iMarker_Outlet] = Outlet_GrossThrust_Local[iMarker_Outlet]; - Outlet_Force_Total[iMarker_Outlet] = Outlet_Force_Local[iMarker_Outlet]; - Outlet_Power_Total[iMarker_Outlet] = Outlet_Power_Local[iMarker_Outlet]; - Outlet_Area_Total[iMarker_Outlet] = Outlet_Area_Local[iMarker_Outlet]; - } - -#endif - /*--- Compute the value of the average surface temperature and pressure and set the value in the config structure for future use ---*/ @@ -6281,7 +5727,6 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns } - delete [] Outlet_MassFlow_Local; delete [] Outlet_Temperature_Local; delete [] Outlet_TotalTemperature_Local; @@ -6370,7 +5815,8 @@ void CEulerSolver::GetPower_Properties(CGeometry *geometry, CConfig *config, uns void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, bool Output) { - su2double Massflow = 0.0 , Target_Massflow = 0.0, DragMinusThrust = 0.0 , Target_DragMinusThrust = 0.0, Target_NetThrust = 0.0, BCThrust = 0.0, BCThrust_inc = 0.0; + su2double Massflow = 0.0 , Target_Massflow = 0.0, DragMinusThrust = 0.0 , + Target_DragMinusThrust = 0.0, Target_NetThrust = 0.0, BCThrust = 0.0, BCThrust_inc = 0.0; unsigned short iDim, iMarker; unsigned long iVertex, iPoint; su2double *V_inlet = NULL, Pressure, @@ -6803,11 +6249,7 @@ void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_con if (!ActDisk_Info) config->SetInitial_BCThrust(0.0); MyBCThrust = config->GetInitial_BCThrust(); -#ifdef HAVE_MPI SU2_MPI::Allreduce(&MyBCThrust, &BCThrust, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); -#else - BCThrust = MyBCThrust; -#endif config->SetInitial_BCThrust(BCThrust); } @@ -6845,11 +6287,11 @@ void CEulerSolver::SetFarfield_AoA(CGeometry *geometry, CSolver **solver_contain SetCoefficient_Gradients(config); - Total_CD_Prev = Total_CD; - Total_CL_Prev = Total_CL; - Total_CMx_Prev = Total_CMx; - Total_CMy_Prev = Total_CMy; - Total_CMz_Prev = Total_CMz; + Total_CD_Prev = TotalCoeff.CD; + Total_CL_Prev = TotalCoeff.CL; + Total_CMx_Prev = TotalCoeff.CMx; + Total_CMy_Prev = TotalCoeff.CMy; + Total_CMz_Prev = TotalCoeff.CMz; AoA_Prev = AoA; /*--- Compute a new value for AoA on the fine mesh only (degrees)---*/ @@ -6918,7 +6360,7 @@ bool CEulerSolver::FixedCL_Convergence(CConfig* config, bool convergence) { /* --- C_L and solution are converged, start finite differencing --- */ - if (fabs(Total_CL-Target_CL) < (config->GetCauchy_Eps()/2)) { + if (fabs(TotalCoeff.CL-Target_CL) < (config->GetCauchy_Eps()/2)) { /* --- If no finite differencing required --- */ @@ -6941,8 +6383,8 @@ bool CEulerSolver::FixedCL_Convergence(CConfig* config, bool convergence) { else if ((curr_iter - Iter_Update_AoA) > config->GetStartConv_Iter()){ Iter_Update_AoA = curr_iter; fixed_cl_conv = false; - if (fabs(Total_CL-Target_CL) > (config->GetCauchy_Eps()/2)) { - AoA_inc = (1.0/dCL_dAlpha)*(Target_CL - Total_CL); + if (fabs(TotalCoeff.CL-Target_CL) > (config->GetCauchy_Eps()/2)) { + AoA_inc = (1.0/dCL_dAlpha)*(Target_CL - TotalCoeff.CL); } } } @@ -6952,8 +6394,8 @@ bool CEulerSolver::FixedCL_Convergence(CConfig* config, bool convergence) { else if ((curr_iter - Iter_Update_AoA) == config->GetUpdate_AoA_Iter_Limit()) { Iter_Update_AoA = curr_iter; fixed_cl_conv = false; - if (fabs(Total_CL-Target_CL) > (config->GetCauchy_Eps()/2)) { - AoA_inc = (1.0/dCL_dAlpha)*(Target_CL - Total_CL); + if (fabs(TotalCoeff.CL-Target_CL) > (config->GetCauchy_Eps()/2)) { + AoA_inc = (1.0/dCL_dAlpha)*(Target_CL - TotalCoeff.CL); } } @@ -7013,11 +6455,11 @@ void CEulerSolver::SetCoefficient_Gradients(CConfig *config){ if (AoA != AoA_Prev) { /* --- Calculate gradients of coefficients w.r.t. CL --- */ - dCL_dAlpha_ = (Total_CL-Total_CL_Prev)/(AoA - AoA_Prev); - dCD_dCL_ = (Total_CD-Total_CD_Prev)/(Total_CL-Total_CL_Prev); - dCMx_dCL_ = (Total_CMx-Total_CMx_Prev)/(Total_CL-Total_CL_Prev); - dCMy_dCL_ = (Total_CMy-Total_CMy_Prev)/(Total_CL-Total_CL_Prev); - dCMz_dCL_ = (Total_CMz-Total_CMz_Prev)/(Total_CL-Total_CL_Prev); + dCL_dAlpha_ = (TotalCoeff.CL-Total_CL_Prev)/(AoA - AoA_Prev); + dCD_dCL_ = (TotalCoeff.CD-Total_CD_Prev)/(TotalCoeff.CL-Total_CL_Prev); + dCMx_dCL_ = (TotalCoeff.CMx-Total_CMx_Prev)/(TotalCoeff.CL-Total_CL_Prev); + dCMy_dCL_ = (TotalCoeff.CMy-Total_CMy_Prev)/(TotalCoeff.CL-Total_CL_Prev); + dCMz_dCL_ = (TotalCoeff.CMz-Total_CMz_Prev)/(TotalCoeff.CL-Total_CL_Prev); /*--- Set the value of the dOF/dCL in the config file ---*/ @@ -7204,39 +6646,39 @@ void CEulerSolver::Evaluate_ObjFunc(CConfig *config) { switch(Kind_ObjFunc) { case DRAG_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(Surface_CD[iMarker_Monitoring]); - if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCD_dCL()*(Surface_CL[iMarker_Monitoring]); - if (config->GetFixed_CM_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCD_dCMy()*(Surface_CMy[iMarker_Monitoring]); + 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*(Surface_CL[iMarker_Monitoring]); + Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CL[iMarker_Monitoring]); break; case SIDEFORCE_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(Surface_CSF[iMarker_Monitoring]); + Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CSF[iMarker_Monitoring]); break; case EFFICIENCY: - Total_ComboObj+=Weight_ObjFunc*(Surface_CEff[iMarker_Monitoring]); + Total_ComboObj+=Weight_ObjFunc*(SurfaceCoeff.CEff[iMarker_Monitoring]); break; case MOMENT_X_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*(Surface_CMx[iMarker_Monitoring]); - if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCMx_dCL()*(Surface_CL[iMarker_Monitoring]); + 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*(Surface_CMy[iMarker_Monitoring]); - if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCMy_dCL()*(Surface_CL[iMarker_Monitoring]); + 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*(Surface_CMz[iMarker_Monitoring]); - if (config->GetFixed_CL_Mode()) Total_ComboObj -= Weight_ObjFunc*config->GetdCMz_dCL()*(Surface_CL[iMarker_Monitoring]); + 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*Surface_CFx[iMarker_Monitoring]; + Total_ComboObj+=Weight_ObjFunc*SurfaceCoeff.CFx[iMarker_Monitoring]; break; case FORCE_Y_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*Surface_CFy[iMarker_Monitoring]; + Total_ComboObj+=Weight_ObjFunc*SurfaceCoeff.CFy[iMarker_Monitoring]; break; case FORCE_Z_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*Surface_CFz[iMarker_Monitoring]; + Total_ComboObj+=Weight_ObjFunc*SurfaceCoeff.CFz[iMarker_Monitoring]; break; case TOTAL_HEATFLUX: Total_ComboObj+=Weight_ObjFunc*Surface_HF_Visc[iMarker_Monitoring]; @@ -7271,13 +6713,13 @@ void CEulerSolver::Evaluate_ObjFunc(CConfig *config) { Total_ComboObj+=Weight_ObjFunc*Total_HeatFluxDiff; break; case THRUST_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*Total_CT; + Total_ComboObj+=Weight_ObjFunc*TotalCoeff.CT; break; case TORQUE_COEFFICIENT: - Total_ComboObj+=Weight_ObjFunc*Total_CQ; + Total_ComboObj+=Weight_ObjFunc*TotalCoeff.CQ; break; case FIGURE_OF_MERIT: - Total_ComboObj+=Weight_ObjFunc*Total_CMerit; + Total_ComboObj+=Weight_ObjFunc*TotalCoeff.CMerit; break; case SURFACE_TOTAL_PRESSURE: Total_ComboObj+=Weight_ObjFunc*config->GetSurface_TotalPressure(0); @@ -7475,14 +6917,15 @@ void CEulerSolver::BC_Sym_Plane(CGeometry *geometry, nodes->GetSecondary(iPoint)); /*--- Compute the residual using an upwind scheme. ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + + auto residual = conv_numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration. ---*/ if (implicit) { - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } if (viscous) { @@ -7579,13 +7022,13 @@ void CEulerSolver::BC_Sym_Plane(CGeometry *geometry, /*--- Compute and update residual. Note that the viscous shear stress tensor is computed in the following routine based upon the velocity-component gradients. ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = visc_numerics->ComputeResidual(config); - LinSysRes.SubtractBlock(iPoint, Residual); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration. ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); }//if viscous }//if GetDomain }//for iVertex @@ -7800,16 +7243,16 @@ void CEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container, /*--- Compute the convective residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Convective Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); /*--- Viscous residual contribution ---*/ @@ -7844,13 +7287,13 @@ void CEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container, /*--- Compute and update viscous residual ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.SubtractBlock(iPoint, Residual); + auto residual = visc_numerics->ComputeResidual(config); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Viscous Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } @@ -7863,7 +7306,9 @@ void CEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container, } void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, - CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + CNumerics *conv_numerics, CNumerics *visc_numerics, + CConfig *config, unsigned short val_marker) { + unsigned short iDim, iVar, jVar, kVar; unsigned long iVertex, iPoint, Point_Normal; su2double P_Total, T_Total, P_static, T_static, Rho_static, *Mach, *Flow_Dir, Area, UnitNormal[3]; @@ -7946,15 +7391,15 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, Energy_i = nodes->GetEnergy(iPoint); StaticEnergy_i = Energy_i - 0.5*Velocity2_i; - FluidModel->SetTDState_rhoe(Density_i, StaticEnergy_i); + GetFluidModel()->SetTDState_rhoe(Density_i, StaticEnergy_i); - Pressure_i = FluidModel->GetPressure(); + Pressure_i = GetFluidModel()->GetPressure(); Enthalpy_i = Energy_i + Pressure_i/Density_i; - SoundSpeed_i = FluidModel->GetSoundSpeed(); + SoundSpeed_i = GetFluidModel()->GetSoundSpeed(); - Kappa_i = FluidModel->GetdPde_rho() / Density_i; - Chi_i = FluidModel->GetdPdrho_e() - Kappa_i * StaticEnergy_i; + Kappa_i = GetFluidModel()->GetdPde_rho() / Density_i; + Chi_i = GetFluidModel()->GetdPdrho_e() - Kappa_i * StaticEnergy_i; ProjVelocity_i = 0.0; for (iDim = 0; iDim < nDim; iDim++) @@ -7977,9 +7422,9 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, T_Total /= config->GetTemperature_Ref(); /* --- Computes the total state --- */ - FluidModel->SetTDState_PT(P_Total, T_Total); - Enthalpy_e = FluidModel->GetStaticEnergy()+ FluidModel->GetPressure()/FluidModel->GetDensity(); - Entropy_e = FluidModel->GetEntropy(); + GetFluidModel()->SetTDState_PT(P_Total, T_Total); + Enthalpy_e = GetFluidModel()->GetStaticEnergy()+ GetFluidModel()->GetPressure()/GetFluidModel()->GetDensity(); + Entropy_e = GetFluidModel()->GetEntropy(); /* --- Compute the boundary state u_e --- */ Velocity2_e = Velocity2_i; @@ -7993,9 +7438,9 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, Velocity_e[iDim] = sqrt(Velocity2_e)*Flow_Dir[iDim]; } StaticEnthalpy_e = Enthalpy_e - 0.5 * Velocity2_e; - FluidModel->SetTDState_hs(StaticEnthalpy_e, Entropy_e); - Density_e = FluidModel->GetDensity(); - StaticEnergy_e = FluidModel->GetStaticEnergy(); + GetFluidModel()->SetTDState_hs(StaticEnthalpy_e, Entropy_e); + Density_e = GetFluidModel()->GetDensity(); + StaticEnergy_e = GetFluidModel()->GetStaticEnergy(); Energy_e = StaticEnergy_e + 0.5 * Velocity2_e; if (tkeNeeded) Energy_e += GetTke_Inf(); break; @@ -8013,16 +7458,16 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, T_static /= config->GetTemperature_Ref(); /* --- Computes the total state --- */ - FluidModel->SetTDState_PT(P_static, T_static); + GetFluidModel()->SetTDState_PT(P_static, T_static); /* --- Compute the boundary state u_e --- */ Velocity2_e = 0.0; for (iDim = 0; iDim < nDim; iDim++) { - Velocity_e[iDim] = Mach[iDim]*FluidModel->GetSoundSpeed(); + Velocity_e[iDim] = Mach[iDim]*GetFluidModel()->GetSoundSpeed(); Velocity2_e += Velocity_e[iDim]*Velocity_e[iDim]; } - Density_e = FluidModel->GetDensity(); - StaticEnergy_e = FluidModel->GetStaticEnergy(); + Density_e = GetFluidModel()->GetDensity(); + StaticEnergy_e = GetFluidModel()->GetStaticEnergy(); Energy_e = StaticEnergy_e + 0.5 * Velocity2_e; if (tkeNeeded) Energy_e += GetTke_Inf(); break; @@ -8041,16 +7486,16 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, Rho_static /= config->GetDensity_Ref(); /* --- Computes the total state --- */ - FluidModel->SetTDState_Prho(P_static, Rho_static); + GetFluidModel()->SetTDState_Prho(P_static, Rho_static); /* --- Compute the boundary state u_e --- */ Velocity2_e = 0.0; for (iDim = 0; iDim < nDim; iDim++) { - Velocity_e[iDim] = Mach[iDim]*FluidModel->GetSoundSpeed(); + Velocity_e[iDim] = Mach[iDim]*GetFluidModel()->GetSoundSpeed(); Velocity2_e += Velocity_e[iDim]*Velocity_e[iDim]; } - Density_e = FluidModel->GetDensity(); - StaticEnergy_e = FluidModel->GetStaticEnergy(); + Density_e = GetFluidModel()->GetDensity(); + StaticEnergy_e = GetFluidModel()->GetStaticEnergy(); Energy_e = StaticEnergy_e + 0.5 * Velocity2_e; if (tkeNeeded) Energy_e += GetTke_Inf(); break; @@ -8079,13 +7524,13 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, Density_e = Density_i; /* --- Compute the boundary state u_e --- */ - FluidModel->SetTDState_Prho(Pressure_e, Density_e); + GetFluidModel()->SetTDState_Prho(Pressure_e, Density_e); Velocity2_e = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Velocity_e[iDim] = Velocity_i[iDim]; Velocity2_e += Velocity_e[iDim]*Velocity_e[iDim]; } - Energy_e = FluidModel->GetStaticEnergy() + 0.5*Velocity2_e; + Energy_e = GetFluidModel()->GetStaticEnergy() + 0.5*Velocity2_e; break; default: @@ -8162,12 +7607,12 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, } Energy_b = u_b[nVar-1]/Density_b; StaticEnergy_b = Energy_b - 0.5*Velocity2_b; - FluidModel->SetTDState_rhoe(Density_b, StaticEnergy_b); - Pressure_b = FluidModel->GetPressure(); - Temperature_b = FluidModel->GetTemperature(); + GetFluidModel()->SetTDState_rhoe(Density_b, StaticEnergy_b); + Pressure_b = GetFluidModel()->GetPressure(); + Temperature_b = GetFluidModel()->GetTemperature(); Enthalpy_b = Energy_b + Pressure_b/Density_b; - Kappa_b = FluidModel->GetdPde_rho() / Density_b; - Chi_b = FluidModel->GetdPdrho_e() - Kappa_b * StaticEnergy_b; + Kappa_b = GetFluidModel()->GetdPde_rho() / Density_b; + Chi_b = GetFluidModel()->GetdPdrho_e() - Kappa_b * StaticEnergy_b; /*--- Compute the residuals ---*/ conv_numerics->GetInviscidProjFlux(&Density_b, Velocity_b, &Pressure_b, &Enthalpy_b, Normal, Residual); @@ -8260,7 +7705,7 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); /*--- Viscous contribution ---*/ @@ -8277,10 +7722,10 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, /*--- Set laminar and eddy viscosity at the infinity ---*/ - V_boundary[nDim+5] = FluidModel->GetLaminarViscosity(); + V_boundary[nDim+5] = GetFluidModel()->GetLaminarViscosity(); V_boundary[nDim+6] = nodes->GetEddyViscosity(iPoint); - V_boundary[nDim+7] = FluidModel->GetThermalConductivity(); - V_boundary[nDim+8] = FluidModel->GetCp(); + V_boundary[nDim+7] = GetFluidModel()->GetThermalConductivity(); + V_boundary[nDim+8] = GetFluidModel()->GetCp(); /*--- Set the normal vector and the coordinates ---*/ @@ -8298,26 +7743,27 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, /*--- Compute secondary thermodynamic properties (partial derivatives...) ---*/ - S_boundary[0]= FluidModel->GetdPdrho_e(); - S_boundary[1]= FluidModel->GetdPde_rho(); + S_boundary[0]= GetFluidModel()->GetdPdrho_e(); + S_boundary[1]= GetFluidModel()->GetdPde_rho(); - S_boundary[2]= FluidModel->GetdTdrho_e(); - S_boundary[3]= FluidModel->GetdTde_rho(); + S_boundary[2]= GetFluidModel()->GetdTdrho_e(); + S_boundary[3]= GetFluidModel()->GetdTde_rho(); /*--- Compute secondary thermo-physical properties (partial derivatives...) ---*/ - S_boundary[4]= FluidModel->Getdmudrho_T(); - S_boundary[5]= FluidModel->GetdmudT_rho(); + S_boundary[4]= GetFluidModel()->Getdmudrho_T(); + S_boundary[5]= GetFluidModel()->GetdmudT_rho(); - S_boundary[6]= FluidModel->Getdktdrho_T(); - S_boundary[7]= FluidModel->GetdktdT_rho(); + S_boundary[6]= GetFluidModel()->Getdktdrho_T(); + S_boundary[7]= GetFluidModel()->GetdktdT_rho(); visc_numerics->SetSecondary(S_domain, S_boundary); /*--- 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)); + 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) ---*/ @@ -8325,13 +7771,13 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, /*--- Compute and update residual ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.SubtractBlock(iPoint, Residual); + auto residual = visc_numerics->ComputeResidual(config); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } @@ -8365,7 +7811,9 @@ void CEulerSolver::BC_Riemann(CGeometry *geometry, CSolver **solver_container, void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_container, - CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + CNumerics *conv_numerics, CNumerics *visc_numerics, + CConfig *config, unsigned short val_marker) { + unsigned short iDim, iVar, jVar, kVar, iSpan; unsigned long iPoint, Point_Normal, oldVertex, iVertex; su2double P_Total, T_Total, *Flow_Dir; @@ -8377,18 +7825,18 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain su2double *gridVel; su2double *V_boundary, *V_domain, *S_boundary, *S_domain; su2double AverageEnthalpy, AverageEntropy; - unsigned short iZone = config->GetiZone(); - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - string Marker_Tag = config->GetMarker_All_TagBound(val_marker); + unsigned short iZone = config->GetiZone(); + bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + string Marker_Tag = config->GetMarker_All_TagBound(val_marker); unsigned short nSpanWiseSections = geometry->GetnSpanWiseSections(config->GetMarker_All_TurbomachineryFlag(val_marker)); - bool viscous = config->GetViscous(); + bool viscous = config->GetViscous(); bool gravity = (config->GetGravityForce()); bool tkeNeeded = (config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST); su2double *Normal, *turboNormal, *UnitNormal, *FlowDirMix, FlowDirMixMag, *turboVelocity; Normal = new su2double[nDim]; - turboNormal = new su2double[nDim]; - UnitNormal = new su2double[nDim]; + turboNormal = new su2double[nDim]; + UnitNormal = new su2double[nDim]; Velocity_i = new su2double[nDim]; Velocity_b = new su2double[nDim]; @@ -8452,15 +7900,15 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain Energy_i = nodes->GetEnergy(iPoint); StaticEnergy_i = Energy_i - 0.5*Velocity2_i; - FluidModel->SetTDState_rhoe(Density_i, StaticEnergy_i); + GetFluidModel()->SetTDState_rhoe(Density_i, StaticEnergy_i); - Pressure_i = FluidModel->GetPressure(); + Pressure_i = GetFluidModel()->GetPressure(); Enthalpy_i = Energy_i + Pressure_i/Density_i; - SoundSpeed_i = FluidModel->GetSoundSpeed(); + SoundSpeed_i = GetFluidModel()->GetSoundSpeed(); - Kappa_i = FluidModel->GetdPde_rho() / Density_i; - Chi_i = FluidModel->GetdPdrho_e() - Kappa_i * StaticEnergy_i; + Kappa_i = GetFluidModel()->GetdPde_rho() / Density_i; + Chi_i = GetFluidModel()->GetdPdrho_e() - Kappa_i * StaticEnergy_i; ProjVelocity_i = 0.0; for (iDim = 0; iDim < nDim; iDim++) @@ -8486,9 +7934,9 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain T_Total /= config->GetTemperature_Ref(); /* --- Computes the total state --- */ - FluidModel->SetTDState_PT(P_Total, T_Total); - Enthalpy_e = FluidModel->GetStaticEnergy()+ FluidModel->GetPressure()/FluidModel->GetDensity(); - Entropy_e = FluidModel->GetEntropy(); + GetFluidModel()->SetTDState_PT(P_Total, T_Total); + Enthalpy_e = GetFluidModel()->GetStaticEnergy()+ GetFluidModel()->GetPressure()/GetFluidModel()->GetDensity(); + Entropy_e = GetFluidModel()->GetEntropy(); /* --- Compute the boundary state u_e --- */ Velocity2_e = Velocity2_i; @@ -8496,9 +7944,9 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain turboVelocity[iDim] = sqrt(Velocity2_e)*Flow_Dir[iDim]; ComputeBackVelocity(turboVelocity,turboNormal, Velocity_e, config->GetMarker_All_TurbomachineryFlag(val_marker),config->GetKind_TurboMachinery(iZone)); StaticEnthalpy_e = Enthalpy_e - 0.5 * Velocity2_e; - FluidModel->SetTDState_hs(StaticEnthalpy_e, Entropy_e); - Density_e = FluidModel->GetDensity(); - StaticEnergy_e = FluidModel->GetStaticEnergy(); + GetFluidModel()->SetTDState_hs(StaticEnthalpy_e, Entropy_e); + Density_e = GetFluidModel()->GetDensity(); + StaticEnergy_e = GetFluidModel()->GetStaticEnergy(); Energy_e = StaticEnergy_e + 0.5 * Velocity2_e; if (tkeNeeded) Energy_e += GetTke_Inf(); break; @@ -8506,9 +7954,9 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain case MIXING_IN: /* --- compute total averaged quantities ---*/ - FluidModel->SetTDState_Prho(ExtAveragePressure[val_marker][iSpan], ExtAverageDensity[val_marker][iSpan]); - AverageEnthalpy = FluidModel->GetStaticEnergy() + ExtAveragePressure[val_marker][iSpan]/ExtAverageDensity[val_marker][iSpan]; - AverageEntropy = FluidModel->GetEntropy(); + GetFluidModel()->SetTDState_Prho(ExtAveragePressure[val_marker][iSpan], ExtAverageDensity[val_marker][iSpan]); + AverageEnthalpy = GetFluidModel()->GetStaticEnergy() + ExtAveragePressure[val_marker][iSpan]/ExtAverageDensity[val_marker][iSpan]; + AverageEntropy = GetFluidModel()->GetEntropy(); FlowDirMixMag = 0; for (iDim = 0; iDim < nDim; iDim++) @@ -8531,9 +7979,9 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain ComputeBackVelocity(turboVelocity,turboNormal, Velocity_e, config->GetMarker_All_TurbomachineryFlag(val_marker),config->GetKind_TurboMachinery(iZone)); StaticEnthalpy_e = Enthalpy_e - 0.5 * Velocity2_e; - FluidModel->SetTDState_hs(StaticEnthalpy_e, Entropy_e); - Density_e = FluidModel->GetDensity(); - StaticEnergy_e = FluidModel->GetStaticEnergy(); + GetFluidModel()->SetTDState_hs(StaticEnthalpy_e, Entropy_e); + Density_e = GetFluidModel()->GetDensity(); + StaticEnergy_e = GetFluidModel()->GetStaticEnergy(); Energy_e = StaticEnergy_e + 0.5 * Velocity2_e; // if (tkeNeeded) Energy_e += GetTke_Inf(); break; @@ -8546,13 +7994,13 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain Density_e = Density_i; /* --- Compute the boundary state u_e --- */ - FluidModel->SetTDState_Prho(Pressure_e, Density_e); + GetFluidModel()->SetTDState_Prho(Pressure_e, Density_e); Velocity2_e = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Velocity_e[iDim] = Velocity_i[iDim]; Velocity2_e += Velocity_e[iDim]*Velocity_e[iDim]; } - Energy_e = FluidModel->GetStaticEnergy() + 0.5*Velocity2_e; + Energy_e = GetFluidModel()->GetStaticEnergy() + 0.5*Velocity2_e; break; case STATIC_PRESSURE: @@ -8563,13 +8011,13 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain Density_e = Density_i; /* --- Compute the boundary state u_e --- */ - FluidModel->SetTDState_Prho(Pressure_e, Density_e); + GetFluidModel()->SetTDState_Prho(Pressure_e, Density_e); Velocity2_e = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Velocity_e[iDim] = Velocity_i[iDim]; Velocity2_e += Velocity_e[iDim]*Velocity_e[iDim]; } - Energy_e = FluidModel->GetStaticEnergy() + 0.5*Velocity2_e; + Energy_e = GetFluidModel()->GetStaticEnergy() + 0.5*Velocity2_e; break; @@ -8580,13 +8028,13 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain Density_e = Density_i; /* --- Compute the boundary state u_e --- */ - FluidModel->SetTDState_Prho(Pressure_e, Density_e); + GetFluidModel()->SetTDState_Prho(Pressure_e, Density_e); Velocity2_e = 0.0; for (iDim = 0; iDim < nDim; iDim++) { Velocity_e[iDim] = Velocity_i[iDim]; Velocity2_e += Velocity_e[iDim]*Velocity_e[iDim]; } - Energy_e = FluidModel->GetStaticEnergy() + 0.5*Velocity2_e; + Energy_e = GetFluidModel()->GetStaticEnergy() + 0.5*Velocity2_e; break; default: @@ -8663,12 +8111,12 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain } Energy_b = u_b[nVar-1]/Density_b; StaticEnergy_b = Energy_b - 0.5*Velocity2_b; - FluidModel->SetTDState_rhoe(Density_b, StaticEnergy_b); - Pressure_b = FluidModel->GetPressure(); - Temperature_b = FluidModel->GetTemperature(); + GetFluidModel()->SetTDState_rhoe(Density_b, StaticEnergy_b); + Pressure_b = GetFluidModel()->GetPressure(); + Temperature_b = GetFluidModel()->GetTemperature(); Enthalpy_b = Energy_b + Pressure_b/Density_b; - Kappa_b = FluidModel->GetdPde_rho() / Density_b; - Chi_b = FluidModel->GetdPdrho_e() - Kappa_b * StaticEnergy_b; + Kappa_b = GetFluidModel()->GetdPde_rho() / Density_b; + Chi_b = GetFluidModel()->GetdPdrho_e() - Kappa_b * StaticEnergy_b; /*--- Compute the residuals ---*/ conv_numerics->GetInviscidProjFlux(&Density_b, Velocity_b, &Pressure_b, &Enthalpy_b, Normal, Residual); @@ -8761,7 +8209,7 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); /*--- Viscous contribution ---*/ @@ -8778,10 +8226,10 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain /*--- Set laminar and eddy viscosity at the infinity ---*/ - V_boundary[nDim+5] = FluidModel->GetLaminarViscosity(); + V_boundary[nDim+5] = GetFluidModel()->GetLaminarViscosity(); V_boundary[nDim+6] = nodes->GetEddyViscosity(iPoint); - V_boundary[nDim+7] = FluidModel->GetThermalConductivity(); - V_boundary[nDim+8] = FluidModel->GetCp(); + V_boundary[nDim+7] = GetFluidModel()->GetThermalConductivity(); + V_boundary[nDim+8] = GetFluidModel()->GetCp(); /*--- Set the normal vector and the coordinates ---*/ @@ -8799,26 +8247,27 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain /*--- Compute secondary thermodynamic properties (partial derivatives...) ---*/ - S_boundary[0]= FluidModel->GetdPdrho_e(); - S_boundary[1]= FluidModel->GetdPde_rho(); + S_boundary[0]= GetFluidModel()->GetdPdrho_e(); + S_boundary[1]= GetFluidModel()->GetdPde_rho(); - S_boundary[2]= FluidModel->GetdTdrho_e(); - S_boundary[3]= FluidModel->GetdTde_rho(); + S_boundary[2]= GetFluidModel()->GetdTdrho_e(); + S_boundary[3]= GetFluidModel()->GetdTde_rho(); /*--- Compute secondary thermo-physical properties (partial derivatives...) ---*/ - S_boundary[4]= FluidModel->Getdmudrho_T(); - S_boundary[5]= FluidModel->GetdmudT_rho(); + S_boundary[4]= GetFluidModel()->Getdmudrho_T(); + S_boundary[5]= GetFluidModel()->GetdmudT_rho(); - S_boundary[6]= FluidModel->Getdktdrho_T(); - S_boundary[7]= FluidModel->GetdktdT_rho(); + S_boundary[6]= GetFluidModel()->Getdktdrho_T(); + S_boundary[7]= GetFluidModel()->GetdktdT_rho(); visc_numerics->SetSecondary(S_domain, S_boundary); /*--- 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)); + 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) ---*/ @@ -8826,13 +8275,13 @@ void CEulerSolver::BC_TurboRiemann(CGeometry *geometry, CSolver **solver_contain /*--- Compute and update residual ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.SubtractBlock(iPoint, Residual); + auto residual = visc_numerics->ComputeResidual(config); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } } @@ -8930,8 +8379,8 @@ void CEulerSolver::PreprocessBC_Giles(CGeometry *geometry, CConfig *config, CNum deltaprim[4] = Pressure_i - AveragePressure[iMarker][iSpan]; } - FluidModel->SetTDState_Prho(AveragePressure[iMarker][iSpan], AverageDensity[iMarker][iSpan]); - AverageSoundSpeed = FluidModel->GetSoundSpeed(); + GetFluidModel()->SetTDState_Prho(AveragePressure[iMarker][iSpan], AverageDensity[iMarker][iSpan]); + AverageSoundSpeed = GetFluidModel()->GetSoundSpeed(); conv_numerics->GetCharJump(AverageSoundSpeed, AverageDensity[iMarker][iSpan], deltaprim, cj); /*-----this is only valid 2D ----*/ @@ -9022,8 +8471,9 @@ void CEulerSolver::PreprocessBC_Giles(CGeometry *geometry, CConfig *config, CNum } -void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, - CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + unsigned short iDim, iVar, jVar, iSpan; unsigned long iPoint, Point_Normal, oldVertex, k, kend, kend_max, iVertex; su2double *UnitNormal, *turboVelocity, *turboNormal; @@ -9121,8 +8571,8 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, } } - FluidModel->SetTDState_Prho(AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan]); - AverageSoundSpeed = FluidModel->GetSoundSpeed(); + GetFluidModel()->SetTDState_Prho(AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan]); + AverageSoundSpeed = GetFluidModel()->GetSoundSpeed(); AverageTurboMach[0] = AverageTurboVelocity[val_marker][iSpan][0]/AverageSoundSpeed; AverageTurboMach[1] = AverageTurboVelocity[val_marker][iSpan][1]/AverageSoundSpeed; @@ -9156,17 +8606,18 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, T_Total /= config->GetTemperature_Ref(); /* --- Computes the total state --- */ - FluidModel->SetTDState_PT(P_Total, T_Total); - Enthalpy_BC = FluidModel->GetStaticEnergy()+ FluidModel->GetPressure()/FluidModel->GetDensity(); - Entropy_BC = FluidModel->GetEntropy(); + GetFluidModel()->SetTDState_PT(P_Total, T_Total); + Enthalpy_BC = GetFluidModel()->GetStaticEnergy()+ GetFluidModel()->GetPressure()/GetFluidModel()->GetDensity(); + Entropy_BC = GetFluidModel()->GetEntropy(); /* --- Computes the inverse matrix R_c --- */ - conv_numerics->ComputeResJacobianGiles(FluidModel, AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan], AverageTurboVelocity[val_marker][iSpan], alphaIn_BC, gammaIn_BC, R_c, R_c_inv); + conv_numerics->ComputeResJacobianGiles(GetFluidModel(), AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan], + AverageTurboVelocity[val_marker][iSpan], alphaIn_BC, gammaIn_BC, R_c, R_c_inv); - FluidModel->SetTDState_Prho(AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan]); - AverageEnthalpy = FluidModel->GetStaticEnergy() + AveragePressure[val_marker][iSpan]/AverageDensity[val_marker][iSpan]; - AverageEntropy = FluidModel->GetEntropy(); + GetFluidModel()->SetTDState_Prho(AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan]); + AverageEnthalpy = GetFluidModel()->GetStaticEnergy() + AveragePressure[val_marker][iSpan]/AverageDensity[val_marker][iSpan]; + AverageEntropy = GetFluidModel()->GetEntropy(); avgVel2 = 0.0; for (iDim = 0; iDim < nDim; iDim++) avgVel2 += AverageVelocity[val_marker][iSpan][iDim]*AverageVelocity[val_marker][iSpan][iDim]; @@ -9211,17 +8662,18 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, T_Total /= config->GetTemperature_Ref(); /* --- Computes the total state --- */ - FluidModel->SetTDState_PT(P_Total, T_Total); - Enthalpy_BC = FluidModel->GetStaticEnergy()+ FluidModel->GetPressure()/FluidModel->GetDensity(); - Entropy_BC = FluidModel->GetEntropy(); + GetFluidModel()->SetTDState_PT(P_Total, T_Total); + Enthalpy_BC = GetFluidModel()->GetStaticEnergy()+ GetFluidModel()->GetPressure()/GetFluidModel()->GetDensity(); + Entropy_BC = GetFluidModel()->GetEntropy(); /* --- Computes the inverse matrix R_c --- */ - conv_numerics->ComputeResJacobianGiles(FluidModel, AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan], AverageTurboVelocity[val_marker][iSpan], alphaIn_BC, gammaIn_BC, R_c, R_c_inv); + conv_numerics->ComputeResJacobianGiles(GetFluidModel(), AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan], + AverageTurboVelocity[val_marker][iSpan], alphaIn_BC, gammaIn_BC, R_c, R_c_inv); - FluidModel->SetTDState_Prho(AveragePressure[val_marker][nSpanWiseSections], AverageDensity[val_marker][nSpanWiseSections]); - AverageEnthalpy = FluidModel->GetStaticEnergy() + AveragePressure[val_marker][nSpanWiseSections]/AverageDensity[val_marker][nSpanWiseSections]; - AverageEntropy = FluidModel->GetEntropy(); + GetFluidModel()->SetTDState_Prho(AveragePressure[val_marker][nSpanWiseSections], AverageDensity[val_marker][nSpanWiseSections]); + AverageEnthalpy = GetFluidModel()->GetStaticEnergy() + AveragePressure[val_marker][nSpanWiseSections]/AverageDensity[val_marker][nSpanWiseSections]; + AverageEntropy = GetFluidModel()->GetEntropy(); avgVel2 = 0.0; @@ -9265,8 +8717,8 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, /* --- Compute average jump of charachteristic variable at the mixing-plane interface--- */ - FluidModel->SetTDState_Prho(AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan]); - AverageSoundSpeed = FluidModel->GetSoundSpeed(); + GetFluidModel()->SetTDState_Prho(AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan]); + AverageSoundSpeed = GetFluidModel()->GetSoundSpeed(); conv_numerics->GetCharJump(AverageSoundSpeed, AverageDensity[val_marker][iSpan], deltaprim, c_avg); break; @@ -9286,8 +8738,8 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, } /* --- Compute average jump of charachteristic variable at the mixing-plane interface--- */ - FluidModel->SetTDState_Prho(AveragePressure[val_marker][nSpanWiseSections], AverageDensity[val_marker][nSpanWiseSections]); - AverageSoundSpeed = FluidModel->GetSoundSpeed(); + GetFluidModel()->SetTDState_Prho(AveragePressure[val_marker][nSpanWiseSections], AverageDensity[val_marker][nSpanWiseSections]); + AverageSoundSpeed = GetFluidModel()->GetSoundSpeed(); conv_numerics->GetCharJump(AverageSoundSpeed, AverageDensity[val_marker][nSpanWiseSections], deltaprim, c_avg); break; @@ -9375,9 +8827,9 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, Energy_i = nodes->GetEnergy(iPoint); StaticEnergy_i = Energy_i - 0.5*Velocity2_i; - FluidModel->SetTDState_rhoe(Density_i, StaticEnergy_i); + GetFluidModel()->SetTDState_rhoe(Density_i, StaticEnergy_i); - Pressure_i = FluidModel->GetPressure(); + Pressure_i = GetFluidModel()->GetPressure(); ComputeTurboVelocity(Velocity_i, turboNormal, turboVelocity, config->GetMarker_All_TurbomachineryFlag(val_marker),config->GetKind_TurboMachinery(iZone)); if (nDim == 2){ @@ -9394,8 +8846,8 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, deltaprim[4] = Pressure_i - AveragePressure[val_marker][iSpan]; } - FluidModel->SetTDState_Prho(AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan]); - AverageSoundSpeed = FluidModel->GetSoundSpeed(); + GetFluidModel()->SetTDState_Prho(AveragePressure[val_marker][iSpan], AverageDensity[val_marker][iSpan]); + AverageSoundSpeed = GetFluidModel()->GetSoundSpeed(); conv_numerics->GetCharJump(AverageSoundSpeed, AverageDensity[val_marker][iSpan], deltaprim, cj); @@ -9626,9 +9078,9 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, } } - FluidModel->SetTDState_Prho(Pressure_b, Density_b); - Energy_b = FluidModel->GetStaticEnergy() + 0.5*Velocity2_b; - Temperature_b= FluidModel->GetTemperature(); + GetFluidModel()->SetTDState_Prho(Pressure_b, Density_b); + Energy_b = GetFluidModel()->GetStaticEnergy() + 0.5*Velocity2_b; + Temperature_b= GetFluidModel()->GetTemperature(); Enthalpy_b = Energy_b + Pressure_b/Density_b; /*--- Primitive variables, using the derived quantities ---*/ @@ -9639,8 +9091,8 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, V_boundary[nDim+2] = Density_b; V_boundary[nDim+3] = Enthalpy_b; - S_boundary[0]= FluidModel->GetdPdrho_e(); - S_boundary[1]= FluidModel->GetdPde_rho(); + S_boundary[0]= GetFluidModel()->GetdPdrho_e(); + S_boundary[1]= GetFluidModel()->GetdPde_rho(); @@ -9655,14 +9107,14 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); /*--- Viscous contribution ---*/ @@ -9670,10 +9122,10 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, /*--- Set laminar and eddy viscosity at the infinity ---*/ - V_boundary[nDim+5] = FluidModel->GetLaminarViscosity(); + V_boundary[nDim+5] = GetFluidModel()->GetLaminarViscosity(); V_boundary[nDim+6] = nodes->GetEddyViscosity(iPoint); - V_boundary[nDim+7] = FluidModel->GetThermalConductivity(); - V_boundary[nDim+8] = FluidModel->GetCp(); + V_boundary[nDim+7] = GetFluidModel()->GetThermalConductivity(); + V_boundary[nDim+8] = GetFluidModel()->GetCp(); /*--- Set the normal vector and the coordinates ---*/ @@ -9688,26 +9140,27 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, /*--- Compute secondary thermodynamic properties (partial derivatives...) ---*/ - S_boundary[0]= FluidModel->GetdPdrho_e(); - S_boundary[1]= FluidModel->GetdPde_rho(); + S_boundary[0]= GetFluidModel()->GetdPdrho_e(); + S_boundary[1]= GetFluidModel()->GetdPde_rho(); - S_boundary[2]= FluidModel->GetdTdrho_e(); - S_boundary[3]= FluidModel->GetdTde_rho(); + S_boundary[2]= GetFluidModel()->GetdTdrho_e(); + S_boundary[3]= GetFluidModel()->GetdTde_rho(); /*--- Compute secondary thermo-physical properties (partial derivatives...) ---*/ - S_boundary[4]= FluidModel->Getdmudrho_T(); - S_boundary[5]= FluidModel->GetdmudT_rho(); + S_boundary[4]= GetFluidModel()->Getdmudrho_T(); + S_boundary[5]= GetFluidModel()->GetdmudT_rho(); - S_boundary[6]= FluidModel->Getdktdrho_T(); - S_boundary[7]= FluidModel->GetdktdT_rho(); + S_boundary[6]= GetFluidModel()->Getdktdrho_T(); + S_boundary[7]= GetFluidModel()->GetdktdT_rho(); visc_numerics->SetSecondary(S_domain, S_boundary); /*--- 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)); + 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) ---*/ @@ -9715,13 +9168,13 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, /*--- Compute and update residual ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.SubtractBlock(iPoint, Residual); + auto residual = visc_numerics->ComputeResidual(config); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } @@ -9761,7 +9214,8 @@ void CEulerSolver::BC_Giles(CGeometry *geometry, CSolver **solver_container, } void CEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, - CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + CNumerics *conv_numerics, CNumerics *visc_numerics, + CConfig *config, unsigned short val_marker) { unsigned short iDim; unsigned long iVertex, iPoint; su2double P_Total, T_Total, Velocity[3], Velocity2, H_Total, Temperature, Riemann, @@ -9995,16 +9449,16 @@ void CEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -10028,7 +9482,8 @@ void CEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, // /*--- 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)); +// 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) ---*/ // @@ -10036,13 +9491,13 @@ void CEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, // // /*--- Compute and update residual ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); -// LinSysRes.SubtractBlock(iPoint, Residual); +// auto residual = visc_numerics->ComputeResidual(config); +// LinSysRes.SubtractBlock(iPoint, residual); // // /*--- Jacobian contribution for implicit integration ---*/ // // if (implicit) -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); // // } @@ -10056,7 +9511,8 @@ void CEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, } void CEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, - CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + CNumerics *conv_numerics, CNumerics *visc_numerics, + CConfig *config, unsigned short val_marker) { unsigned short iVar, iDim; unsigned long iVertex, iPoint; su2double Pressure, P_Exit, Velocity[3], @@ -10170,15 +9626,14 @@ void CEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, conv_numerics->SetGridVel(geometry->node[iPoint]->GetGridVel(), geometry->node[iPoint]->GetGridVel()); /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); - /*--- Jacobian contribution for implicit integration ---*/ - if (implicit) { - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); - } + /*--- Add Residuals and Jacobians ---*/ + + LinSysRes.AddBlock(iPoint, residual); + if (implicit) + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -10202,20 +9657,21 @@ void CEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, // /*--- 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)); +// 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 ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); -// LinSysRes.SubtractBlock(iPoint, Residual); +// auto residual = visc_numerics->ComputeResidual(config); +// LinSysRes.SubtractBlock(iPoint, residual); // // /*--- Jacobian contribution for implicit integration ---*/ // // if (implicit) -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// Jacobian.SubtractBlock2Diag(iPoint, residual.acobian_i); // // } @@ -10228,7 +9684,8 @@ void CEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, } void CEulerSolver::BC_Supersonic_Inlet(CGeometry *geometry, CSolver **solver_container, - CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + CNumerics *conv_numerics, CNumerics *visc_numerics, + CConfig *config, unsigned short val_marker) { unsigned short iDim; unsigned long iVertex, iPoint; su2double *V_inlet, *V_domain; @@ -10312,13 +9769,14 @@ void CEulerSolver::BC_Supersonic_Inlet(CGeometry *geometry, CSolver **solver_con /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -10342,7 +9800,8 @@ void CEulerSolver::BC_Supersonic_Inlet(CGeometry *geometry, CSolver **solver_con // /*--- 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)); +// 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) ---*/ // @@ -10350,13 +9809,13 @@ void CEulerSolver::BC_Supersonic_Inlet(CGeometry *geometry, CSolver **solver_con // // /*--- Compute and update residual ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); -// LinSysRes.SubtractBlock(iPoint, Residual); +// auto residual = visc_numerics->ComputeResidual(config); +// LinSysRes.SubtractBlock(iPoint, residual); // // /*--- Jacobian contribution for implicit integration ---*/ // // if (implicit) -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); // } } @@ -10370,7 +9829,8 @@ void CEulerSolver::BC_Supersonic_Inlet(CGeometry *geometry, CSolver **solver_con } void CEulerSolver::BC_Supersonic_Outlet(CGeometry *geometry, CSolver **solver_container, - CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + CNumerics *conv_numerics, CNumerics *visc_numerics, + CConfig *config, unsigned short val_marker) { unsigned short iDim; unsigned long iVertex, iPoint; su2double *V_outlet, *V_domain; @@ -10430,37 +9890,39 @@ void CEulerSolver::BC_Supersonic_Outlet(CGeometry *geometry, CSolver **solver_co /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); - - // /*--- Viscous contribution, commented out because serious convergence problems ---*/ - // - // if (viscous) { - // - // /*--- Set laminar and eddy viscosity at the infinity ---*/ - // - // V_outlet[nDim+5] = nodes->GetLaminarViscosity(iPoint); - // V_outlet[nDim+6] = nodes->GetEddyViscosity(iPoint); - // - // /*--- Set the normal vector and the coordinates ---*/ - // - // visc_numerics->SetNormal(Normal); - // visc_numerics->SetCoord(geometry->node[iPoint]->GetCoord(), geometry->node[Point_Normal]->GetCoord()); - // - // /*--- 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)); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); + +// /*--- Viscous contribution, commented out because serious convergence problems ---*/ +// +// if (viscous) { +// +// /*--- Set laminar and eddy viscosity at the infinity ---*/ +// +// V_outlet[nDim+5] = nodes->GetLaminarViscosity(iPoint); +// V_outlet[nDim+6] = nodes->GetEddyViscosity(iPoint); +// +// /*--- Set the normal vector and the coordinates ---*/ +// +// visc_numerics->SetNormal(Normal); +// visc_numerics->SetCoord(geometry->node[iPoint]->GetCoord(), geometry->node[Point_Normal]->GetCoord()); +// +// /*--- 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)); // // /*--- Set the wall shear stress values (wall functions) to -1 (no evaluation using wall functions) ---*/ // @@ -10468,13 +9930,13 @@ void CEulerSolver::BC_Supersonic_Outlet(CGeometry *geometry, CSolver **solver_co // // /*--- Compute and update residual ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); -// LinSysRes.SubtractBlock(iPoint, Residual); +// auto residual = visc_numerics->ComputeResidual(config); +// LinSysRes.SubtractBlock(iPoint, residual); // // /*--- Jacobian contribution for implicit integration ---*/ // // if (implicit) -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); // } } @@ -10651,13 +10113,14 @@ void CEulerSolver::BC_Engine_Inflow(CGeometry *geometry, CSolver **solver_contai /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -10681,7 +10144,8 @@ void CEulerSolver::BC_Engine_Inflow(CGeometry *geometry, CSolver **solver_contai // /*--- 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)); +// 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) ---*/ // @@ -10689,13 +10153,13 @@ void CEulerSolver::BC_Engine_Inflow(CGeometry *geometry, CSolver **solver_contai // // /*--- Compute and update residual ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); -// LinSysRes.SubtractBlock(iPoint, Residual); +// auto residual = visc_numerics->ComputeResidual(config); +// LinSysRes.SubtractBlock(iPoint, residual); // // /*--- Jacobian contribution for implicit integration ---*/ // // if (implicit) -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); // // } @@ -10904,13 +10368,14 @@ void CEulerSolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_conta /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -10934,7 +10399,8 @@ void CEulerSolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_conta // /*--- 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)); +// 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) ---*/ // @@ -10942,13 +10408,13 @@ void CEulerSolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_conta // // /*--- Compute and update residual ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); -// LinSysRes.SubtractBlock(iPoint, Residual); +// auto residual = visc_numerics->ComputeResidual(config) +// LinSysRes.SubtractBlock(iPoint, residual); // // /*--- Jacobian contribution for implicit integration ---*/ // // if (implicit) -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); // // } @@ -10959,19 +10425,19 @@ 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) { +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, iMarker, nDonorVertex; + unsigned short iDim, iVar, jVar, iMarker, nDonorVertex; bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); bool viscous = config->GetViscous(); - su2double *Normal = new su2double[nDim]; - su2double *PrimVar_i = new su2double[nPrimVar]; - su2double *PrimVar_j = new su2double[nPrimVar]; - su2double *tmp_residual = new su2double[nVar]; + su2double Normal[MAXNDIM] = {0.0}; + su2double PrimVar_i[MAXNVAR] = {0.0}; + su2double PrimVar_j[MAXNVAR] = {0.0}; + su2double Secondary_j[MAXNVAR] = {0.0}; su2double weight; su2double P_static, rho_static; @@ -10989,12 +10455,15 @@ void CEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_cont /*--- Initialize Residual, this will serve to accumulate the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) + 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++){ + for (jVertex = 0; jVertex < nDonorVertex; jVertex++) { Point_Normal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); @@ -11012,14 +10481,14 @@ void CEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_cont conv_numerics->SetPrimitive( PrimVar_i, PrimVar_j ); if( !( config->GetKind_FluidModel() == STANDARD_AIR || config->GetKind_FluidModel() == IDEAL_GAS ) ) { - Secondary_i = nodes->GetSecondary(iPoint); + auto Secondary_i = nodes->GetSecondary(iPoint); P_static = PrimVar_j[nDim+1]; rho_static = PrimVar_j[nDim+2]; - FluidModel->SetTDState_Prho(P_static, rho_static); + GetFluidModel()->SetTDState_Prho(P_static, rho_static); - Secondary_j[0] = FluidModel->GetdPdrho_e(); - Secondary_j[1] = FluidModel->GetdPde_rho(); + Secondary_j[0] = GetFluidModel()->GetdPdrho_e(); + Secondary_j[1] = GetFluidModel()->GetdPde_rho(); conv_numerics->SetSecondary(Secondary_i, Secondary_j); } @@ -11037,31 +10506,37 @@ void CEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_cont /*--- Compute the convective residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(tmp_residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Accumulate the residuals to compute the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] += weight*tmp_residual[iVar]; - + 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.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); if (viscous) { /*--- Initialize Residual, this will serve to accumulate the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) + 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++){ + 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); @@ -11082,7 +10557,8 @@ void CEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_cont /*--- 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)); + 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) ---*/ @@ -11090,12 +10566,15 @@ void CEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_cont /*--- Compute and update residual ---*/ - visc_numerics->ComputeResidual(tmp_residual, Jacobian_i, Jacobian_j, config); + auto residual = visc_numerics->ComputeResidual(config); /*--- Accumulate the residuals to compute the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] += weight*tmp_residual[iVar]; + 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); @@ -11103,7 +10582,7 @@ void CEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_cont /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } } @@ -11111,12 +10590,6 @@ void CEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_cont } } - /*--- Free locally allocated memory ---*/ - - delete [] tmp_residual; - delete [] Normal; - delete [] PrimVar_i; - delete [] PrimVar_j; } void CEulerSolver::BC_Interface_Boundary(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, @@ -11161,12 +10634,13 @@ void CEulerSolver::BC_Interface_Boundary(CGeometry *geometry, CSolver **solver_c /*--- Compute the convective residual using an upwind scheme ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + + auto residual = numerics->ComputeResidual(config); /*--- Add Residuals and Jacobians ---*/ - LinSysRes.AddBlock(iPoint, Residual); - if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.AddBlock(iPoint, residual); + if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } @@ -11222,13 +10696,14 @@ void CEulerSolver::BC_NearField_Boundary(CGeometry *geometry, CSolver **solver_c /*--- Compute the convective residual using an upwind scheme ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = numerics->ComputeResidual(config); /*--- Add Residuals and Jacobians ---*/ - LinSysRes.AddBlock(iPoint, Residual); - if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.AddBlock(iPoint, residual); + if (implicit) + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } } @@ -11350,7 +10825,7 @@ void CEulerSolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, C P_static = V_outlet[nDim+1] / (Target_Press_Jump/PressureAdj); T_static = V_outlet[0] / (Target_Temp_Jump/TemperatureAdj); } - else { P_static = V_outlet[nDim+1] - Target_Press_Jump; T_static = V_outlet[0] - Target_Temp_Jump; } + else { P_static = V_outlet[nDim+1] - Target_Press_Jump; T_static = V_outlet[0] - Target_Temp_Jump; } } else { V_outlet = nodes->GetPrimitive(iPoint); @@ -11441,9 +10916,9 @@ void CEulerSolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, C else { - FluidModel->SetTDState_PT(P_static, T_static); - SoS_outlet = FluidModel->GetSoundSpeed(); - Rho_outlet = FluidModel->GetDensity(); + GetFluidModel()->SetTDState_PT(P_static, T_static); + SoS_outlet = GetFluidModel()->GetSoundSpeed(); + Rho_outlet = GetFluidModel()->GetDensity(); /*--- We use the velocity and the density from the flow inlet to evaluate flow direction and mass flow ---*/ @@ -11599,15 +11074,15 @@ void CEulerSolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, C /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -11639,7 +11114,8 @@ void CEulerSolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, C // /*--- 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)); +// 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) ---*/ // @@ -11647,12 +11123,12 @@ void CEulerSolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, C // // /*--- Compute and update residual ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); -// LinSysRes.SubtractBlock(iPoint, Residual); +// auto residual = visc_numerics->ComputeResidual(config); +// LinSysRes.SubtractBlock(iPoint, residual); // // /*--- Jacobian contribution for implicit integration ---*/ // -// if (implicit) Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// if (implicit) Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); // // } @@ -11759,14 +11235,17 @@ void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_co /*--- Local variables ---*/ - unsigned short iVar, jVar, iMarker, iDim; + unsigned short iVar, iMarker, iDim, iNeigh; unsigned long iPoint, jPoint, iEdge, iVertex; - su2double *U_time_nM1, *U_time_n, *U_time_nP1; + const su2double *U_time_nM1 = nullptr, *U_time_n = nullptr, *U_time_nP1 = nullptr; su2double Volume_nM1, Volume_nP1, TimeStep; - su2double *Normal = NULL, *GridVel_i = NULL, *GridVel_j = NULL, Residual_GCL; + const su2double *Normal = nullptr, *GridVel_i = nullptr, *GridVel_j = nullptr; + su2double Residual_GCL; - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + const bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + const bool first_order = (config->GetTime_Marching() == DT_STEPPING_1ST); + const bool second_order = (config->GetTime_Marching() == DT_STEPPING_2ND); /*--- Store the physical time step ---*/ @@ -11778,6 +11257,7 @@ void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_co /*--- Loop over all nodes (excluding halos) ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Retrieve the solution at time levels n-1, n, and n+1. Note that @@ -11797,26 +11277,17 @@ void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_co time discretization scheme (1st- or 2nd-order).---*/ for (iVar = 0; iVar < nVar; iVar++) { - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Residual[iVar] = (U_time_nP1[iVar] - U_time_n[iVar])*Volume_nP1 / TimeStep; - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Residual[iVar] = ( 3.0*U_time_nP1[iVar] - 4.0*U_time_n[iVar] - +1.0*U_time_nM1[iVar])*Volume_nP1 / (2.0*TimeStep); + if (first_order) + LinSysRes(iPoint,iVar) += (U_time_nP1[iVar] - U_time_n[iVar])*Volume_nP1 / TimeStep; + if (second_order) + LinSysRes(iPoint,iVar) += ( 3.0*U_time_nP1[iVar] - 4.0*U_time_n[iVar] + +1.0*U_time_nM1[iVar])*Volume_nP1 / (2.0*TimeStep); } - /*--- Store the residual and compute the Jacobian contribution due - to the dual time source term. ---*/ - - LinSysRes.AddBlock(iPoint, Residual); + /*--- Compute the Jacobian contribution due to the dual time source term. ---*/ if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] = 0.0; - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Jacobian_i[iVar][iVar] = Volume_nP1 / TimeStep; - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Jacobian_i[iVar][iVar] = (Volume_nP1*3.0)/(2.0*TimeStep); - } - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (first_order) Jacobian.AddVal2Diag(iPoint, Volume_nP1/TimeStep); + if (second_order) Jacobian.AddVal2Diag(iPoint, (Volume_nP1*3.0)/(2.0*TimeStep)); } } @@ -11832,40 +11303,30 @@ void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_co we will loop over the edges and boundaries to compute the GCL component of the dual time source term that depends on grid velocities. ---*/ - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { - - /*--- Get indices for nodes i & j plus the face normal ---*/ - - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); - Normal = geometry->edge[iEdge]->GetNormal(); - - /*--- Grid velocities stored at nodes i & j ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) + for (iPoint = 0; iPoint < nPointDomain; ++iPoint) { GridVel_i = geometry->node[iPoint]->GetGridVel(); - GridVel_j = geometry->node[jPoint]->GetGridVel(); - - /*--- Compute the GCL term by averaging the grid velocities at the - edge mid-point and dotting with the face normal. ---*/ + U_time_n = nodes->GetSolution_time_n(iPoint); - Residual_GCL = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Residual_GCL += 0.5*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iNeigh = 0; iNeigh < geometry->node[iPoint]->GetnNeighbor(); iNeigh++) { - /*--- Compute the GCL component of the source term for node i ---*/ + iEdge = geometry->node[iPoint]->GetEdge(iNeigh); + Normal = geometry->edge[iEdge]->GetNormal(); - U_time_n = nodes->GetSolution_time_n(iPoint); - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] = U_time_n[iVar]*Residual_GCL; - LinSysRes.AddBlock(iPoint, Residual); + jPoint = geometry->node[iPoint]->GetPoint(iNeigh); + GridVel_j = geometry->node[jPoint]->GetGridVel(); - /*--- Compute the GCL component of the source term for node j ---*/ + /*--- Determine whether to consider the normal outward or inward. ---*/ + su2double dir = (geometry->edge[iEdge]->GetNode(0) == iPoint)? 0.5 : -0.5; - U_time_n = nodes->GetSolution_time_n(jPoint); - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] = U_time_n[iVar]*Residual_GCL; - LinSysRes.SubtractBlock(jPoint, Residual); + Residual_GCL = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Residual_GCL += dir*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim]; + for (iVar = 0; iVar < nVar; iVar++) + LinSysRes(iPoint,iVar) += U_time_n[iVar]*Residual_GCL; + } } /*--- Loop over the boundary edges ---*/ @@ -11873,38 +11334,39 @@ void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_co for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) { if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) { - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - /*--- Get the index for node i plus the boundary face normal ---*/ + SU2_OMP_FOR_STAT(OMP_MIN_SIZE) + for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); + /*--- Get the index for node i plus the boundary face normal ---*/ - /*--- Grid velocities stored at boundary node i ---*/ + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - GridVel_i = geometry->node[iPoint]->GetGridVel(); + /*--- Grid velocities stored at boundary node i ---*/ - /*--- Compute the GCL term by dotting the grid velocity with the face - normal. The normal is negated to match the boundary convention. ---*/ + GridVel_i = geometry->node[iPoint]->GetGridVel(); - Residual_GCL = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Residual_GCL -= 0.5*(GridVel_i[iDim]+GridVel_i[iDim])*Normal[iDim]; + /*--- Compute the GCL term by dotting the grid velocity with the face + normal. The normal is negated to match the boundary convention. ---*/ - /*--- Compute the GCL component of the source term for node i ---*/ + Residual_GCL = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Residual_GCL -= 0.5*(GridVel_i[iDim]+GridVel_i[iDim])*Normal[iDim]; - U_time_n = nodes->GetSolution_time_n(iPoint); - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] = U_time_n[iVar]*Residual_GCL; - LinSysRes.AddBlock(iPoint, Residual); + /*--- Compute the GCL component of the source term for node i ---*/ - } + U_time_n = nodes->GetSolution_time_n(iPoint); + for (iVar = 0; iVar < nVar; iVar++) + LinSysRes(iPoint,iVar) += U_time_n[iVar]*Residual_GCL; + } } } /*--- Loop over all nodes (excluding halos) to compute the remainder of the dual time-stepping source term. ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Retrieve the solution at time levels n-1, n, and n+1. Note that @@ -11927,25 +11389,17 @@ void CEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_co due to the time discretization has a new form.---*/ for (iVar = 0; iVar < nVar; iVar++) { - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Residual[iVar] = (U_time_nP1[iVar] - U_time_n[iVar])*(Volume_nP1/TimeStep); - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Residual[iVar] = (U_time_nP1[iVar] - U_time_n[iVar])*(3.0*Volume_nP1/(2.0*TimeStep)) - + (U_time_nM1[iVar] - U_time_n[iVar])*(Volume_nM1/(2.0*TimeStep)); + if (first_order) + LinSysRes(iPoint,iVar) += (U_time_nP1[iVar] - U_time_n[iVar])*(Volume_nP1/TimeStep); + if (second_order) + LinSysRes(iPoint,iVar) += (U_time_nP1[iVar] - U_time_n[iVar])*(3.0*Volume_nP1/(2.0*TimeStep)) + + (U_time_nM1[iVar] - U_time_n[iVar])*(Volume_nM1/(2.0*TimeStep)); } - /*--- Store the residual and compute the Jacobian contribution due - to the dual time source term. ---*/ - LinSysRes.AddBlock(iPoint, Residual); + /*--- Compute the Jacobian contribution due to the dual time source term. ---*/ if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] = 0.0; - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Jacobian_i[iVar][iVar] = Volume_nP1/TimeStep; - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Jacobian_i[iVar][iVar] = (3.0*Volume_nP1)/(2.0*TimeStep); - } - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (first_order) Jacobian.AddVal2Diag(iPoint, Volume_nP1/TimeStep); + if (second_order) Jacobian.AddVal2Diag(iPoint, (Volume_nP1*3.0)/(2.0*TimeStep)); } } } @@ -12074,7 +11528,6 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig int counter = 0; long iPoint_Local = 0; unsigned long iPoint_Global = 0; unsigned long iPoint_Global_Local = 0; - unsigned short rbuf_NotMatching = 0, sbuf_NotMatching = 0; /*--- Skip coordinates ---*/ @@ -12161,14 +11614,7 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig /*--- Detect a wrong solution file ---*/ - if (iPoint_Global_Local < nPointDomain) { sbuf_NotMatching = 1; } - -#ifndef HAVE_MPI - rbuf_NotMatching = sbuf_NotMatching; -#else - SU2_MPI::Allreduce(&sbuf_NotMatching, &rbuf_NotMatching, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD); -#endif - if (rbuf_NotMatching != 0) { + if (iPoint_Global_Local < nPointDomain) { SU2_MPI::Error(string("The solution file ") + restart_filename + string(" doesn't match with the mesh file!\n") + string("It could be empty lines at the end of the file."), CURRENT_FUNCTION); } @@ -12277,9 +11723,8 @@ void CEulerSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig /*--- Delete the class memory that is used to load the restart. ---*/ - if (Restart_Vars != NULL) delete [] Restart_Vars; - if (Restart_Data != NULL) delete [] Restart_Data; - Restart_Vars = NULL; Restart_Data = NULL; + delete [] Restart_Vars; Restart_Vars = nullptr; + delete [] Restart_Data; Restart_Data = nullptr; } @@ -12313,8 +11758,8 @@ void CEulerSolver::SetFreeStream_TurboSolution(CConfig *config) { turboNormal = config->GetFreeStreamTurboNormal(); - FluidModel->SetTDState_Prho(Pressure_Inf, Density_Inf); - SoundSpeed = FluidModel->GetSoundSpeed(); + GetFluidModel()->SetTDState_Prho(Pressure_Inf, Density_Inf); + SoundSpeed = GetFluidModel()->GetSoundSpeed(); /*--- Compute the Free Stream velocity, using the Mach number ---*/ turboVelocity[0] = cos(Alpha)*Mach*SoundSpeed; @@ -12334,8 +11779,8 @@ void CEulerSolver::SetFreeStream_TurboSolution(CConfig *config) { } nodes->SetSolution(iPoint,nVar-1, Density_Inf*Energy_Inf); - nodes->SetPrimVar(iPoint,FluidModel); - nodes->SetSecondaryVar(iPoint,FluidModel); + nodes->SetPrimVar(iPoint, GetFluidModel()); + nodes->SetSecondaryVar(iPoint, GetFluidModel()); } delete [] turboVelocity; @@ -12364,14 +11809,9 @@ void CEulerSolver::PreprocessAverage(CSolver **solver, CGeometry *geometry, CCon TurboVelocity = new su2double[nDim]; TotalAreaVelocity = new su2double[nDim]; -#ifdef HAVE_MPI - su2double MyTotalAreaDensity, MyTotalAreaPressure; - su2double *MyTotalAreaVelocity = NULL; -#endif for (iSpan= 0; iSpan < nSpanWiseSections; iSpan++){ - for (iDim=0; iDimGetnMarker_All(); iMarker++){ for (iMarkerTP=1; iMarkerTP < config->GetnMarker_Turbomachinery()+1; iMarkerTP++){ if (config->GetMarker_All_Turbomachinery(iMarker) == iMarkerTP){ @@ -12767,72 +12195,46 @@ void CEulerSolver::TurboAverageProcess(CSolver **solver, CGeometry *geometry, CC /*--- Add information using all the nodes ---*/ - MyTotalDensity = TotalDensity; TotalDensity = 0; - MyTotalPressure = TotalPressure; TotalPressure = 0; - MyTotalAreaDensity = TotalAreaDensity; TotalAreaDensity = 0; - MyTotalAreaPressure = TotalAreaPressure; TotalAreaPressure = 0; - MyTotalMassDensity = TotalMassDensity; TotalMassDensity = 0; - MyTotalMassPressure = TotalMassPressure; TotalMassPressure = 0; - MyTotalNu = TotalNu; TotalNu = 0; - MyTotalKine = TotalKine; TotalKine = 0; - MyTotalOmega = TotalOmega; TotalOmega = 0; - MyTotalAreaNu = TotalAreaNu; TotalAreaNu = 0; - MyTotalAreaKine = TotalAreaKine; TotalAreaKine = 0; - MyTotalAreaOmega = TotalAreaOmega; TotalAreaOmega = 0; - MyTotalMassNu = TotalMassNu; TotalMassNu = 0; - MyTotalMassKine = TotalMassKine; TotalMassKine = 0; - MyTotalMassOmega = TotalMassOmega; TotalMassOmega = 0; - + 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; + }; + TotalDensity = Allreduce(TotalDensity); + TotalPressure = Allreduce(TotalPressure); + TotalAreaDensity = Allreduce(TotalAreaDensity); + TotalAreaPressure = Allreduce(TotalAreaPressure); + TotalMassDensity = Allreduce(TotalMassDensity); + TotalMassPressure = Allreduce(TotalMassPressure); + TotalNu = Allreduce(TotalNu); + TotalKine = Allreduce(TotalKine); + TotalOmega = Allreduce(TotalOmega); + TotalAreaNu = Allreduce(TotalAreaNu); + TotalAreaKine = Allreduce(TotalAreaKine); + TotalAreaOmega = Allreduce(TotalAreaOmega); - SU2_MPI::Allreduce(&MyTotalDensity, &TotalDensity, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalPressure, &TotalPressure, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalAreaDensity, &TotalAreaDensity, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalAreaPressure, &TotalAreaPressure, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalMassDensity, &TotalMassDensity, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalMassPressure, &TotalMassPressure, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalNu, &TotalNu, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalKine, &TotalKine, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalOmega, &TotalOmega, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalAreaNu, &TotalAreaNu, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalAreaKine, &TotalAreaKine, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalAreaOmega, &TotalAreaOmega, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalMassNu, &TotalMassNu, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalMassKine, &TotalMassKine, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyTotalMassOmega, &TotalMassOmega, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - - - MyTotalFluxes = new su2double[nVar]; - MyTotalVelocity = new su2double[nDim]; - MyTotalAreaVelocity = new su2double[nDim]; - MyTotalMassVelocity = new su2double[nDim]; - - for (iVar = 0; iVar < nVar; iVar++) { - MyTotalFluxes[iVar] = TotalFluxes[iVar]; - TotalFluxes[iVar] = 0.0; - } + TotalMassNu = Allreduce(TotalMassNu); + TotalMassKine = Allreduce(TotalMassKine); + TotalMassOmega = Allreduce(TotalMassOmega); - for (iDim = 0; iDim < nDim; iDim++) { - MyTotalVelocity[iDim] = TotalVelocity[iDim]; - TotalVelocity[iDim] = 0.0; - MyTotalAreaVelocity[iDim] = TotalAreaVelocity[iDim]; - TotalAreaVelocity[iDim] = 0.0; - MyTotalMassVelocity[iDim] = TotalMassVelocity[iDim]; - TotalMassVelocity[iDim] = 0.0; - } + su2double* buffer = new su2double[max(nVar,nDim)]; - SU2_MPI::Allreduce(MyTotalFluxes, TotalFluxes, nVar, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MyTotalVelocity, TotalVelocity, nDim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MyTotalAreaVelocity, TotalAreaVelocity, nDim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(MyTotalMassVelocity, TotalMassVelocity, nDim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + 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_All(); iMarker++){ for (iMarkerTP=1; iMarkerTP < config->GetnMarker_Turbomachinery()+1; iMarkerTP++){ if (config->GetMarker_All_Turbomachinery(iMarker) == iMarkerTP){ @@ -12842,11 +12244,9 @@ void CEulerSolver::TurboAverageProcess(CSolver **solver, CGeometry *geometry, CC AverageTurboNormal = geometry->GetAverageTurboNormal(iMarker,iSpan); nVert = geometry->GetnTotVertexSpan(iMarker,iSpan); - - /*--- compute normal Mach number as a check for massflow average and mixedout average ---*/ - FluidModel->SetTDState_Prho(TotalAreaPressure/TotalArea, TotalAreaDensity / TotalArea); - soundSpeed = FluidModel->GetSoundSpeed(); + GetFluidModel()->SetTDState_Prho(TotalAreaPressure/TotalArea, TotalAreaDensity / TotalArea); + soundSpeed = GetFluidModel()->GetSoundSpeed(); MachTest = TotalFluxes[0]/(TotalAreaDensity*soundSpeed); /*--- Compute the averaged value for the boundary of interest for the span of interest ---*/ @@ -13082,8 +12482,6 @@ void CEulerSolver::TurboAverageProcess(CSolver **solver, CGeometry *geometry, CC } } - - /*--- Compute Outlet Static Pressure if Radial equilibrium is imposed ---*/ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++){ @@ -13168,12 +12566,12 @@ void CEulerSolver::MixedOut_Average (CConfig *config, su2double val_init_pressur while ( iter <= maxiter ) { density_mix = val_Averaged_Flux[0]*val_Averaged_Flux[0]/(val_Averaged_Flux[1] - pressure_mix); - FluidModel->SetTDState_Prho(pressure_mix, density_mix); - enthalpy_mix = FluidModel->GetStaticEnergy() + (pressure_mix)/(density_mix); + GetFluidModel()->SetTDState_Prho(pressure_mix, density_mix); + enthalpy_mix = GetFluidModel()->GetStaticEnergy() + (pressure_mix)/(density_mix); - FluidModel->ComputeDerivativeNRBC_Prho(pressure_mix, density_mix); - dhdP = FluidModel->GetdhdP_rho(); - dhdrho = FluidModel->Getdhdrho_P(); + GetFluidModel()->ComputeDerivativeNRBC_Prho(pressure_mix, density_mix); + dhdP = GetFluidModel()->GetdhdP_rho(); + dhdrho = GetFluidModel()->Getdhdrho_P(); vel[0] = (val_Averaged_Flux[1] - pressure_mix) / val_Averaged_Flux[0]; for (iDim = 1; iDim < nDim; iDim++) { @@ -13199,7 +12597,6 @@ void CEulerSolver::MixedOut_Average (CConfig *config, su2double val_init_pressur density_mix = val_Averaged_Flux[0]*val_Averaged_Flux[0]/(val_Averaged_Flux[1] - pressure_mix); - delete [] vel; } @@ -13235,7 +12632,6 @@ void CEulerSolver::GatherInOutAverageValues(CConfig *config, CGeometry *geometry TurbPerfOut[i] = -1.0; #endif - densityIn = -1.0; pressureIn = -1.0; normalVelocityIn = -1.0; @@ -13253,7 +12649,6 @@ void CEulerSolver::GatherInOutAverageValues(CConfig *config, CGeometry *geometry omegaOut = -1.0; nuOut = -1.0; - markerTP = -1; for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++){ @@ -13272,7 +12667,6 @@ void CEulerSolver::GatherInOutAverageValues(CConfig *config, CGeometry *geometry omegaIn = OmegaIn[iMarkerTP -1][iSpan]; nuIn = NuIn[iMarkerTP -1][iSpan]; - #ifdef HAVE_MPI TurbPerfIn[0] = densityIn; TurbPerfIn[1] = pressureIn; @@ -13298,8 +12692,6 @@ void CEulerSolver::GatherInOutAverageValues(CConfig *config, CGeometry *geometry omegaOut = OmegaOut[iMarkerTP -1][iSpan]; nuOut = NuOut[iMarkerTP -1][iSpan]; - - #ifdef HAVE_MPI TurbPerfOut[0] = densityOut; TurbPerfOut[1] = pressureOut; @@ -13338,43 +12730,25 @@ void CEulerSolver::GatherInOutAverageValues(CConfig *config, CGeometry *geometry if (rank == MASTER_NODE){ for (i=0;i 0.0){ - densityIn = 0.0; densityIn = TotTurbPerfIn[n1*i]; - pressureIn = 0.0; pressureIn = TotTurbPerfIn[n1*i+1]; - normalVelocityIn = 0.0; normalVelocityIn = TotTurbPerfIn[n1*i+2]; - tangVelocityIn = 0.0; tangVelocityIn = TotTurbPerfIn[n1*i+3]; - radialVelocityIn = 0.0; radialVelocityIn = TotTurbPerfIn[n1*i+4]; - kineIn = 0.0; kineIn = TotTurbPerfIn[n1*i+5]; - omegaIn = 0.0; omegaIn = TotTurbPerfIn[n1*i+6]; - nuIn = 0.0; nuIn = TotTurbPerfIn[n1*i+7]; - - markerTP = -1; markerTP = TotMarkerTP[i]; } if(TotTurbPerfOut[n2*i] > 0.0){ - densityOut = 0.0; densityOut = TotTurbPerfOut[n1*i]; - pressureOut = 0.0; pressureOut = TotTurbPerfOut[n1*i+1]; - normalVelocityOut = 0.0; normalVelocityOut = TotTurbPerfOut[n1*i+2]; - tangVelocityOut = 0.0; tangVelocityOut = TotTurbPerfOut[n1*i+3]; - radialVelocityOut = 0.0; radialVelocityOut = TotTurbPerfOut[n1*i+4]; - kineOut = 0.0; kineOut = TotTurbPerfOut[n1*i+5]; - omegaOut = 0.0; omegaOut = TotTurbPerfOut[n1*i+6]; - nuOut = 0.0; nuOut = TotTurbPerfOut[n1*i+7]; } } diff --git a/SU2_CFD/src/solvers/CFEASolver.cpp b/SU2_CFD/src/solvers/CFEASolver.cpp index 8acdcfb153c4..16d1b8e92953 100644 --- a/SU2_CFD/src/solvers/CFEASolver.cpp +++ b/SU2_CFD/src/solvers/CFEASolver.cpp @@ -28,7 +28,6 @@ #include "../../include/solvers/CFEASolver.hpp" #include "../../include/variables/CFEABoundVariable.hpp" #include "../../../Common/include/toolboxes/printing_toolbox.hpp" -#include "../../../Common/include/omp_structure.hpp" #include /*! @@ -246,17 +245,19 @@ CFEASolver::CFEASolver(CGeometry *geometry, CConfig *config) : CSolver() { const auto& coloring = geometry->GetElementColoring(); - auto nColor = coloring.getOuterSize(); - ElemColoring.resize(nColor); + if (!coloring.empty()) { + auto nColor = coloring.getOuterSize(); + ElemColoring.reserve(nColor); - for(auto iColor = 0ul; iColor < nColor; ++iColor) { - ElemColoring[iColor].size = coloring.getNumNonZeros(iColor); - ElemColoring[iColor].indices = coloring.innerIdx(iColor); + for(auto iColor = 0ul; iColor < nColor; ++iColor) { + ElemColoring.emplace_back(coloring.innerIdx(iColor), coloring.getNumNonZeros(iColor)); + } } - ColorGroupSize = geometry->GetElementColorGroupSize(); omp_chunk_size = computeStaticChunkSize(nPointDomain, omp_get_max_threads(), OMP_MAX_SIZE); +#else + ElemColoring[0] = DummyGridColor<>(nElement); #endif iElem_iDe = nullptr; @@ -408,7 +409,6 @@ void CFEASolver::Set_ElementProperties(CGeometry *geometry, CConfig *config) { long iElem_Local; unsigned long iElem_Global_Local = 0, iElem_Global = 0; string text_line; - unsigned short rbuf_NotMatching = 0, sbuf_NotMatching = 0; /*--- The first line is the header ---*/ @@ -454,11 +454,7 @@ void CFEASolver::Set_ElementProperties(CGeometry *geometry, CConfig *config) { /*--- Detect a wrong solution file ---*/ - if (iElem_Global_Local < nElement) { sbuf_NotMatching = 1; } - - SU2_MPI::Allreduce(&sbuf_NotMatching, &rbuf_NotMatching, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD); - - if (rbuf_NotMatching != 0) { + if (iElem_Global_Local != nElement) { SU2_MPI::Error(string("The properties file ") + filename + string(" doesn't match with the mesh file!\n") + string("It could be empty lines at the end of the file."), CURRENT_FUNCTION); } @@ -505,6 +501,7 @@ void CFEASolver::Set_Prestretch(CGeometry *geometry, CConfig *config) { if (prestretch_file.fail()) { SU2_MPI::Error(string("There is no FEM prestretch reference file ") + filename, CURRENT_FUNCTION); } + /*--- In case this is a parallel simulation, we need to perform the Global2Local index transformation first. ---*/ @@ -520,7 +517,6 @@ void CFEASolver::Set_Prestretch(CGeometry *geometry, CConfig *config) { long iPoint_Local; unsigned long iPoint_Global_Local = 0, iPoint_Global = 0; string text_line; - unsigned short rbuf_NotMatching = 0, sbuf_NotMatching = 0; /*--- The first line is the header ---*/ @@ -551,13 +547,9 @@ void CFEASolver::Set_Prestretch(CGeometry *geometry, CConfig *config) { /*--- Detect a wrong solution file ---*/ - if (iPoint_Global_Local < nPointDomain) { sbuf_NotMatching = 1; } - - SU2_MPI::Allreduce(&sbuf_NotMatching, &rbuf_NotMatching, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD); - - if (rbuf_NotMatching != 0) { - SU2_MPI::Error(string("The solution file ") + filename + string(" doesn't match with the mesh file!\n") + - string("It could be empty lines at the end of the file."), CURRENT_FUNCTION); + if (iPoint_Global_Local != nPointDomain) { + SU2_MPI::Error(string("The solution file ") + filename + string(" doesn't match with the mesh file!\n") + + string("It could be empty lines at the end of the file."), CURRENT_FUNCTION); } /*--- Close the restart file ---*/ @@ -676,7 +668,6 @@ void CFEASolver::Set_ReferenceGeometry(CGeometry *geometry, CConfig *config) { long iPoint_Local; unsigned long iPoint_Global_Local = 0, iPoint_Global = 0; string text_line; - unsigned short rbuf_NotMatching = 0, sbuf_NotMatching = 0; /*--- The first line is the header ---*/ @@ -716,17 +707,11 @@ void CFEASolver::Set_ReferenceGeometry(CGeometry *geometry, CConfig *config) { /*--- Detect a wrong solution file ---*/ - if (iPoint_Global_Local < nPointDomain) { sbuf_NotMatching = 1; } - - SU2_MPI::Allreduce(&sbuf_NotMatching, &rbuf_NotMatching, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD); - - if (rbuf_NotMatching != 0) { + if (iPoint_Global_Local != nPointDomain) { SU2_MPI::Error(string("The solution file ") + filename + string(" doesn't match with the mesh file!\n") + string("It could be empty lines at the end of the file."), CURRENT_FUNCTION); } - /*--- I don't think we need to communicate ---*/ - /*--- Close the restart file ---*/ reference_file.close(); @@ -795,37 +780,14 @@ void CFEASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, if (body_forces && initial_calc) Compute_DeadLoad(geometry, numerics, config); - + /*--- Clear the linear system solution. ---*/ SU2_OMP_PARALLEL { - /*--- Clear the linear system solution. ---*/ LinSysSol.SetValZero(); - - /*--- Some external forces may be considered constant over the time step. ---*/ - if (first_iter) { - SU2_OMP_FOR_STAT(omp_chunk_size) - for (auto iPoint = 0ul; iPoint < nPoint; iPoint++) - nodes->Clear_SurfaceLoad_Res(iPoint); - } } - /* - * If we apply nonlinear forces, we need to clear the residual - * on every iteration to avoid adding over previous values. - */ - for (unsigned short iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++){ - switch (config->GetMarker_All_KindBC(iMarker)) { - case LOAD_BOUNDARY: - case DAMPER_BOUNDARY: - /*--- For all the vertices in the marker iMarker. ---*/ - for (auto iVertex = 0ul; iVertex < geometry->nVertex[iMarker]; iVertex++) { - /*--- Retrieve the point ID and clear the residual. ---*/ - auto iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - nodes->Clear_SurfaceLoad_Res(iPoint); - } - break; - } - } + /*--- Clear external forces. ---*/ + nodes->Clear_SurfaceLoad_Res(); /* * FSI loads (computed upstream) need to be integrated if a nonconservative interpolation scheme is in use @@ -864,22 +826,14 @@ void CFEASolver::Compute_StiffMatrix(CGeometry *geometry, CNumerics **numerics, LinSysRes.SetValZero(); Jacobian.SetValZero(); -#ifdef HAVE_OMP - /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ - auto chunkSize = roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize; + for(auto color : ElemColoring) { - /*--- Loop over element colors. ---*/ - for (auto color : ElemColoring) - { - SU2_OMP_FOR_DYN(chunkSize) + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) for(auto k = 0ul; k < color.size; ++k) { auto iElem = color.indices[k]; -#else - /*--- Natural coloring. ---*/ - { - for (auto iElem = 0ul; iElem < nElement; iElem++) { -#endif + unsigned short iNode, jNode, iDim, iVar; int thread = omp_get_thread_num(); @@ -927,7 +881,7 @@ void CFEASolver::Compute_StiffMatrix(CGeometry *geometry, CNumerics **numerics, auto Ta = element->Get_Kt_a(iNode); for (iVar = 0; iVar < nVar; iVar++) - LinSysRes[indexNode[iNode]*nVar+iVar] -= simp_penalty*Ta[iVar]; + LinSysRes(indexNode[iNode], iVar) -= simp_penalty*Ta[iVar]; for (jNode = 0; jNode < nNodes; jNode++) { auto Kab = element->Get_Kab(iNode, jNode); @@ -960,22 +914,14 @@ void CFEASolver::Compute_StiffMatrix_NodalStressRes(CGeometry *geometry, CNumeri LinSysRes.SetValZero(); Jacobian.SetValZero(); -#ifdef HAVE_OMP - /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ - auto chunkSize = roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize; + for(auto color : ElemColoring) { - /*--- Loop over element colors. ---*/ - for (auto color : ElemColoring) - { - SU2_OMP_FOR_DYN(chunkSize) + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) for(auto k = 0ul; k < color.size; ++k) { auto iElem = color.indices[k]; -#else - /*--- Natural coloring. ---*/ - { - for (auto iElem = 0ul; iElem < nElement; iElem++) { -#endif + unsigned short iNode, jNode, iDim, iVar; int thread = omp_get_thread_num(); @@ -1042,13 +988,13 @@ void CFEASolver::Compute_StiffMatrix_NodalStressRes(CGeometry *geometry, CNumeri auto Ta = fea_elem->Get_Kt_a(iNode); for (iVar = 0; iVar < nVar; iVar++) - LinSysRes[indexNode[iNode]*nVar+iVar] -= simp_penalty*Ta[iVar]; + LinSysRes(indexNode[iNode], iVar) -= simp_penalty*Ta[iVar]; /*--- Retrieve the electric contribution to the residual. ---*/ if (de_effects) { auto Ta_DE = de_elem->Get_Kt_a(iNode); for (iVar = 0; iVar < nVar; iVar++) - LinSysRes[indexNode[iNode]*nVar+iVar] -= simp_penalty*Ta_DE[iVar]; + LinSysRes(indexNode[iNode], iVar) -= simp_penalty*Ta_DE[iVar]; } for (jNode = 0; jNode < nNodes; jNode++) { @@ -1099,22 +1045,14 @@ void CFEASolver::Compute_MassMatrix(CGeometry *geometry, CNumerics **numerics, C /*--- Clear matrix before calculation. ---*/ MassMatrix.SetValZero(); -#ifdef HAVE_OMP - /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ - auto chunkSize = roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize; + for(auto color : ElemColoring) { - /*--- Loop over element colors. ---*/ - for (auto color : ElemColoring) - { - SU2_OMP_FOR_DYN(chunkSize) + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) for(auto k = 0ul; k < color.size; ++k) { auto iElem = color.indices[k]; -#else - /*--- Natural coloring. ---*/ - { - for (auto iElem = 0ul; iElem < nElement; iElem++) { -#endif + unsigned short iNode, jNode, iDim, iVar; int thread = omp_get_thread_num(); @@ -1184,22 +1122,14 @@ void CFEASolver::Compute_MassRes(CGeometry *geometry, CNumerics **numerics, CCon TimeRes.SetValZero(); SU2_OMP_BARRIER -#ifdef HAVE_OMP - /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ - auto chunkSize = roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize; + for(auto color : ElemColoring) { - /*--- Loop over element colors. ---*/ - for (auto color : ElemColoring) - { - SU2_OMP_FOR_DYN(chunkSize) + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) for(auto k = 0ul; k < color.size; ++k) { auto iElem = color.indices[k]; -#else - /*--- Natural coloring. ---*/ - { - for (auto iElem = 0ul; iElem < nElement; iElem++) { -#endif + unsigned short iNode, jNode, iDim, iVar; int thread = omp_get_thread_num(); @@ -1242,8 +1172,8 @@ void CFEASolver::Compute_MassRes(CGeometry *geometry, CNumerics **numerics, CCon su2double Mab = simp_penalty * element->Get_Mab(iNode, jNode); for (iVar = 0; iVar < nVar; iVar++) { - TimeRes[indexNode[iNode]*nVar+iVar] += Mab * TimeRes_Aux.GetBlock(indexNode[iNode],iVar); - TimeRes[indexNode[jNode]*nVar+iVar] += Mab * TimeRes_Aux.GetBlock(indexNode[jNode],iVar); + TimeRes[indexNode[iNode]*nVar+iVar] += Mab * TimeRes_Aux(indexNode[iNode],iVar); + TimeRes[indexNode[jNode]*nVar+iVar] += Mab * TimeRes_Aux(indexNode[jNode],iVar); } } } @@ -1272,22 +1202,14 @@ void CFEASolver::Compute_NodalStressRes(CGeometry *geometry, CNumerics **numeric LinSysRes.SetValZero(); SU2_OMP_BARRIER -#ifdef HAVE_OMP - /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ - auto chunkSize = roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize; + for(auto color : ElemColoring) { - /*--- Loop over element colors. ---*/ - for (auto color : ElemColoring) - { - SU2_OMP_FOR_DYN(chunkSize) + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) for(auto k = 0ul; k < color.size; ++k) { auto iElem = color.indices[k]; -#else - /*--- Natural coloring. ---*/ - { - for (auto iElem = 0ul; iElem < nElement; iElem++) { -#endif + unsigned short iNode, iDim, iVar; int thread = omp_get_thread_num(); @@ -1340,7 +1262,7 @@ void CFEASolver::Compute_NodalStressRes(CGeometry *geometry, CNumerics **numeric for (iNode = 0; iNode < nNodes; iNode++) { auto Ta = element->Get_Kt_a(iNode); for (iVar = 0; iVar < nVar; iVar++) - LinSysRes[indexNode[iNode]*nVar+iVar] -= simp_penalty*Ta[iVar]; + LinSysRes(indexNode[iNode], iVar) -= simp_penalty*Ta[iVar]; } } // end iElem loop @@ -1360,11 +1282,7 @@ void CFEASolver::Compute_NodalStress(CGeometry *geometry, CNumerics **numerics, const unsigned short nStress = (nDim == 2) ? 3 : 6; - /*--- Reduction variable to compute the maximum von Misses stress, - * each thread uses the first element of each row, the rest of - * the row is padding to prevent false sharing. ---*/ - su2activematrix auxMaxVonMisses(omp_get_max_threads(), 64/sizeof(su2double)); - auxMaxVonMisses.setConstant(0.0); + su2double MaxVonMises_Stress = 0.0; /*--- Start OpenMP parallel region. ---*/ @@ -1381,22 +1299,14 @@ void CFEASolver::Compute_NodalStress(CGeometry *geometry, CNumerics **numerics, } } -#ifdef HAVE_OMP - /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ - auto chunkSize = roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize; + for(auto color : ElemColoring) { - /*--- Loop over element colors. ---*/ - for (auto color : ElemColoring) - { - SU2_OMP_FOR_DYN(chunkSize) + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) for(auto k = 0ul; k < color.size; ++k) { auto iElem = color.indices[k]; -#else - /*--- Natural coloring. ---*/ - { - for (auto iElem = 0ul; iElem < nElement; iElem++) { -#endif + unsigned short iNode, iDim, iVar, iStress; int thread = omp_get_thread_num(); @@ -1451,7 +1361,7 @@ void CFEASolver::Compute_NodalStress(CGeometry *geometry, CNumerics **numerics, auto Ta = element->Get_Kt_a(iNode); for (iVar = 0; iVar < nVar; iVar++) - LinSysReact[iPoint*nVar+iVar] += simp_penalty*Ta[iVar]; + LinSysReact(iPoint,iVar) += simp_penalty*Ta[iVar]; /*--- Divide the nodal stress by the number of elements that will contribute to this point. ---*/ su2double weight = simp_penalty / geometry->node[iPoint]->GetnElem(); @@ -1466,10 +1376,10 @@ void CFEASolver::Compute_NodalStress(CGeometry *geometry, CNumerics **numerics, /*--- Compute the von Misses stress at each point, and the maximum for the domain. ---*/ - SU2_OMP_FOR_STAT(omp_chunk_size) - for (auto iPoint = 0ul; iPoint < nPointDomain; iPoint++) { + su2double maxVonMises = 0.0; - int thread = omp_get_thread_num(); + SU2_OMP(for schedule(static,omp_chunk_size) nowait) + for (auto iPoint = 0ul; iPoint < nPointDomain; iPoint++) { /*--- Get the stresses, added up from all the elements that connect to the node. ---*/ @@ -1502,18 +1412,15 @@ void CFEASolver::Compute_NodalStress(CGeometry *geometry, CNumerics **numerics, /*--- Update the maximum value of the Von Mises Stress ---*/ - auxMaxVonMisses(thread,0) = max(auxMaxVonMisses(thread,0), VonMises_Stress); + maxVonMises = max(maxVonMises, VonMises_Stress); } + SU2_OMP_CRITICAL + MaxVonMises_Stress = max(MaxVonMises_Stress, maxVonMises); } // end SU2_OMP_PARALLEL - /*--- Compute MaxVonMises_Stress across all threads and ranks. ---*/ - - for(auto thread = 1ul; thread < auxMaxVonMisses.rows(); ++thread) - auxMaxVonMisses(0,0) = max(auxMaxVonMisses(0,0), auxMaxVonMisses(thread,0)); - - su2double MaxVonMises_Stress; - SU2_MPI::Allreduce(auxMaxVonMisses.data(), &MaxVonMises_Stress, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + su2double tmp = MaxVonMises_Stress; + SU2_MPI::Allreduce(&tmp, &MaxVonMises_Stress, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); /*--- Set the value of the MaxVonMises_Stress as the CFEA coeffient ---*/ @@ -1560,7 +1467,7 @@ void CFEASolver::Compute_NodalStress(CGeometry *geometry, CNumerics **numerics, for (iVar = 0; iVar < nVar; iVar++) { /*--- Retrieve reaction ---*/ - val_Reaction = LinSysReact.GetBlock(iPoint, iVar); + val_Reaction = LinSysReact(iPoint, iVar); myfile << "F" << iVar + 1 << ": " << val_Reaction << " \t " ; } @@ -1581,7 +1488,7 @@ void CFEASolver::Compute_NodalStress(CGeometry *geometry, CNumerics **numerics, /*--- Loop over all points, and set aux vector TimeRes_Aux = a0*U+a2*U'+a3*U'' ---*/ for (iPoint = 0; iPoint < geometry->GetnPoint(); iPoint++) { for (iVar = 0; iVar < nVar; iVar++) { - TimeRes_Aux[iPoint*nVar+iVar] = + TimeRes_Aux(iPoint,iVar) = a_dt[0]*nodes->GetSolution_time_n(iPoint,iVar) - // a0*U(t) a_dt[0]*nodes->GetSolution(iPoint,iVar) + // a0*U(t+dt)(k-1) a_dt[2]*nodes->GetSolution_Vel_time_n(iPoint,iVar) + // a2*U'(t) @@ -1618,7 +1525,7 @@ void CFEASolver::Compute_NodalStress(CGeometry *geometry, CNumerics **numerics, for (iVar = 0; iVar < nVar; iVar++) { /*--- Retrieve the time contribution and reaction. ---*/ - val_Reaction = LinSysReact.GetBlock(iPoint, iVar) + TimeRes.GetBlock(iPoint, iVar); + val_Reaction = LinSysReact(iPoint, iVar) + TimeRes(iPoint, iVar); myfile << "F" << iVar + 1 << ": " << val_Reaction << " \t " ; } @@ -1654,22 +1561,14 @@ void CFEASolver::Compute_DeadLoad(CGeometry *geometry, CNumerics **numerics, CCo for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++) nodes->Clear_BodyForces_Res(iPoint); -#ifdef HAVE_OMP - /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ - auto chunkSize = roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize; + for(auto color : ElemColoring) { - /*--- Loop over element colors. ---*/ - for (auto color : ElemColoring) - { - SU2_OMP_FOR_DYN(chunkSize) + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) for(auto k = 0ul; k < color.size; ++k) { auto iElem = color.indices[k]; -#else - /*--- Natural coloring. ---*/ - { - for (auto iElem = 0ul; iElem < nElement; iElem++) { -#endif + unsigned short iNode, iDim, iVar; int thread = omp_get_thread_num(); @@ -1834,38 +1733,42 @@ void CFEASolver::BC_DispDir(CGeometry *geometry, CNumerics *numerics, CConfig *c auto TagBound = config->GetMarker_All_TagBound(val_marker); su2double DispDirVal = config->GetDisp_Dir_Value(TagBound); su2double DispDirMult = config->GetDisp_Dir_Multiplier(TagBound); - const su2double *Disp_Dir_Local = config->GetDisp_Dir(TagBound); + const su2double *DispDirLocal = config->GetDisp_Dir(TagBound); - su2double Disp_Dir[3] = {0.0, 0.0, 0.0}; + su2double DispDir[3] = {0.0}; - su2double Disp_Dir_Mod = 0.0; + su2double DispDirMod = 0.0; for (iDim = 0; iDim < nDim; iDim++) - Disp_Dir_Mod += Disp_Dir_Local[iDim]*Disp_Dir_Local[iDim]; - Disp_Dir_Mod = sqrt(Disp_Dir_Mod); + DispDirMod += DispDirLocal[iDim]*DispDirLocal[iDim]; + DispDirMod = sqrt(DispDirMod); su2double CurrentTime = config->GetCurrent_DynTime(); - su2double Ramp_Time = config->GetRamp_Time(); - su2double ModAmpl = Compute_LoadCoefficient(CurrentTime, Ramp_Time, config); + su2double RampTime = config->GetRamp_Time(); + su2double ModAmpl = Compute_LoadCoefficient(CurrentTime, RampTime, config); - su2double TotalDisp = ModAmpl * DispDirVal * DispDirMult / Disp_Dir_Mod; + su2double TotalDisp = ModAmpl * DispDirVal * DispDirMult / DispDirMod; for (iDim = 0; iDim < nDim; iDim++) - Disp_Dir[iDim] = TotalDisp * Disp_Dir_Local[iDim]; + DispDir[iDim] = TotalDisp * DispDirLocal[iDim]; for (auto iVertex = 0ul; iVertex < geometry->nVertex[val_marker]; iVertex++) { - /*--- Get node index ---*/ + /*--- Get node index. ---*/ auto iNode = geometry->vertex[val_marker][iVertex]->GetNode(); - /*--- Set and enforce solution ---*/ - LinSysSol.SetBlock(iNode, Disp_Dir); - Jacobian.EnforceSolutionAtNode(iNode, Disp_Dir, LinSysRes); + /*--- The solution is incremental so we need to + * subtract the current displacement. ---*/ + for (iDim = 0; iDim < nDim; iDim++) + LinSysSol(iNode,iDim) = DispDir[iDim] - nodes->GetSolution(iNode,iDim); + + /*--- Enforce the solution. ---*/ + Jacobian.EnforceSolutionAtNode(iNode, LinSysSol.GetBlock(iNode), LinSysRes); } } -void CFEASolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, CNumerics **numerics, - unsigned short iMesh) { +void CFEASolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, + CConfig *config, CNumerics **numerics, unsigned short iMesh) { unsigned short iVar; unsigned long iPoint, total_index; @@ -2104,28 +2007,57 @@ void CFEASolver::BC_Dir_Load(CGeometry *geometry, CNumerics *numerics, CConfig * void CFEASolver::BC_Damper(CGeometry *geometry, CNumerics *numerics, CConfig *config, unsigned short val_marker) { - su2double dampConstant = config->GetDamper_Constant(config->GetMarker_All_TagBound(val_marker)); - unsigned long nVertex = geometry->GetnVertex(val_marker); - - /*--- The damping is distributed evenly over all the nodes in the marker ---*/ - const su2double dampC = -1.0 * dampConstant / (nVertex + EPS); + const su2double dampConst = config->GetDamper_Constant(config->GetMarker_All_TagBound(val_marker)); for (auto iElem = 0ul; iElem < geometry->GetnElem_Bound(val_marker); iElem++) { - unsigned short iNode, iVar; + unsigned short iNode, iDim; + unsigned long indexNode[4] = {0}; + + su2double nodeCoord[4][3] = {0.0}; bool quad = (geometry->bound[val_marker][iElem]->GetVTK_Type() == QUADRILATERAL); - unsigned short nNode = quad? 4 : nDim; + unsigned short nNodes = quad? 4 : nDim; - for(iNode = 0; iNode < nNode; ++iNode) { + /*--- Retrieve the boundary current coordinates. ---*/ + + for (iNode = 0; iNode < nNodes; iNode++) { auto iPoint = geometry->bound[val_marker][iElem]->GetNode(iNode); + indexNode[iNode] = iPoint; - for (iVar = 0; iVar < nVar; iVar++){ - su2double dampValue = dampC * nodes->GetSolution_Vel(iPoint, iVar); - nodes->Set_SurfaceLoad_Res(iPoint, iVar, dampValue); - } + for (iDim = 0; iDim < nVar; iDim++) + nodeCoord[iNode][iDim] = geometry->node[iPoint]->GetCoord(iDim) + nodes->GetSolution(iPoint,iDim); + } + + /*--- Compute the area of the surface element. ---*/ + + su2double normal[3] = {0.0}; + + switch (nNodes) { + case 2: LineNormal(nodeCoord, normal); break; + case 3: TriangleNormal(nodeCoord, normal); break; + case 4: QuadrilateralNormal(nodeCoord, normal); break; } + + su2double area = sqrt(pow(normal[0],2) + pow(normal[1],2) + pow(normal[2],2)); + + /*--- Compute damping forces. ---*/ + + su2double dampCoeff = -1.0 * area * dampConst / su2double(nNodes); + + for(iNode = 0; iNode < nNodes; ++iNode) { + + auto iPoint = indexNode[iNode]; + + /*--- Writing over the normal. --*/ + su2double* force = normal; + for (iDim = 0; iDim < nVar; iDim++) + force[iDim] = dampCoeff * nodes->GetSolution_Vel(iPoint, iDim); + + nodes->Add_SurfaceLoad_Res(iPoint, force); + } + } } @@ -2416,21 +2348,21 @@ void CFEASolver::ImplicitNewmark_Iteration(CGeometry *geometry, CSolver **solver /*--- External surface load contribution. ---*/ for (iVar = 0; iVar < nVar; iVar++) { - LinSysRes[iPoint*nVar+iVar] += loadIncr * nodes->Get_SurfaceLoad_Res(iPoint,iVar); + LinSysRes(iPoint,iVar) += loadIncr * nodes->Get_SurfaceLoad_Res(iPoint,iVar); } /*--- Body forces contribution (dead load). ---*/ if (body_forces) { for (iVar = 0; iVar < nVar; iVar++) { - LinSysRes[iPoint*nVar+iVar] += loadIncr * nodes->Get_BodyForces_Res(iPoint,iVar); + LinSysRes(iPoint,iVar) += loadIncr * nodes->Get_BodyForces_Res(iPoint,iVar); } } /*--- FSI contribution (flow loads). ---*/ for (iVar = 0; iVar < nVar; iVar++) { - LinSysRes[iPoint*nVar+iVar] += loadIncr * nodes->Get_FlowTraction(iPoint,iVar); + LinSysRes(iPoint,iVar) += loadIncr * nodes->Get_FlowTraction(iPoint,iVar); } } @@ -2458,7 +2390,7 @@ void CFEASolver::ImplicitNewmark_Iteration(CGeometry *geometry, CSolver **solver SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < nPoint; iPoint++) { for (iVar = 0; iVar < nVar; iVar++) { - TimeRes_Aux[iPoint*nVar+iVar] = + TimeRes_Aux(iPoint,iVar) = a_dt[0]*nodes->GetSolution_time_n(iPoint,iVar) - // a0*U(t) a_dt[0]*nodes->GetSolution(iPoint,iVar) + // a0*U(t+dt)(k-1) a_dt[2]*nodes->GetSolution_Vel_time_n(iPoint,iVar) + // a2*U'(t) @@ -2491,7 +2423,7 @@ void CFEASolver::ImplicitNewmark_Update(CGeometry *geometry, CSolver **solver_co for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Displacement component of the solution. ---*/ for (iVar = 0; iVar < nVar; iVar++) - nodes->Add_DeltaSolution(iPoint, iVar, LinSysSol[iPoint*nVar+iVar]); + nodes->Add_DeltaSolution(iPoint, iVar, LinSysSol(iPoint,iVar)); } if (dynamic) { @@ -2622,21 +2554,21 @@ void CFEASolver::GeneralizedAlpha_Iteration(CGeometry *geometry, CSolver **solve /*--- External surface load contribution. ---*/ for (iVar = 0; iVar < nVar; iVar++) { - LinSysRes[iPoint*nVar+iVar] += loadIncr * nodes->Get_SurfaceLoad_Res(iPoint,iVar); + LinSysRes(iPoint,iVar) += loadIncr * nodes->Get_SurfaceLoad_Res(iPoint,iVar); } /*--- Body forces contribution (dead load). ---*/ if (body_forces) { for (iVar = 0; iVar < nVar; iVar++) { - LinSysRes[iPoint*nVar+iVar] += loadIncr * nodes->Get_BodyForces_Res(iPoint,iVar); + LinSysRes(iPoint,iVar) += loadIncr * nodes->Get_BodyForces_Res(iPoint,iVar); } } /*--- FSI contribution (flow loads). ---*/ for (iVar = 0; iVar < nVar; iVar++) { - LinSysRes[iPoint*nVar+iVar] += loadIncr * nodes->Get_FlowTraction(iPoint,iVar); + LinSysRes(iPoint,iVar) += loadIncr * nodes->Get_FlowTraction(iPoint,iVar); } } @@ -2657,7 +2589,7 @@ void CFEASolver::GeneralizedAlpha_Iteration(CGeometry *geometry, CSolver **solve SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < nPoint; iPoint++) { for (iVar = 0; iVar < nVar; iVar++) { - TimeRes_Aux[iPoint*nVar+iVar] = + TimeRes_Aux(iPoint,iVar) = a_dt[0]*nodes->GetSolution_time_n(iPoint,iVar) - // a0*U(t) a_dt[0]*nodes->GetSolution(iPoint,iVar) + // a0*U(t+dt)(k-1) a_dt[2]*nodes->GetSolution_Vel_time_n(iPoint,iVar) + // a2*U'(t) @@ -2677,8 +2609,8 @@ void CFEASolver::GeneralizedAlpha_Iteration(CGeometry *geometry, CSolver **solve /*--- External surface load contribution ---*/ for (iVar = 0; iVar < nVar; iVar++) { - LinSysRes[iPoint*nVar+iVar] += loadIncr * ( (1-alpha_f) * nodes->Get_SurfaceLoad_Res(iPoint,iVar) + - alpha_f * nodes->Get_SurfaceLoad_Res_n(iPoint,iVar) ); + LinSysRes(iPoint,iVar) += loadIncr * ( (1-alpha_f) * nodes->Get_SurfaceLoad_Res(iPoint,iVar) + + alpha_f * nodes->Get_SurfaceLoad_Res_n(iPoint,iVar) ); } /*--- Add the contribution to the residual due to body forces. @@ -2686,15 +2618,15 @@ void CFEASolver::GeneralizedAlpha_Iteration(CGeometry *geometry, CSolver **solve if (body_forces) { for (iVar = 0; iVar < nVar; iVar++) { - LinSysRes[iPoint*nVar+iVar] += loadIncr * nodes->Get_BodyForces_Res(iPoint,iVar); + LinSysRes(iPoint,iVar) += loadIncr * nodes->Get_BodyForces_Res(iPoint,iVar); } } /*--- Add FSI contribution. ---*/ for (iVar = 0; iVar < nVar; iVar++) { - LinSysRes[iPoint*nVar+iVar] += loadIncr * ( (1-alpha_f) * nodes->Get_FlowTraction(iPoint,iVar) + - alpha_f * nodes->Get_FlowTraction_n(iPoint,iVar) ); + LinSysRes(iPoint,iVar) += loadIncr * ( (1-alpha_f) * nodes->Get_FlowTraction(iPoint,iVar) + + alpha_f * nodes->Get_FlowTraction_n(iPoint,iVar) ); } } } @@ -2707,10 +2639,10 @@ void CFEASolver::GeneralizedAlpha_UpdateDisp(CGeometry *geometry, CSolver **solv /*--- Update displacement components of the solution. ---*/ - SU2_OMP(parallel for schedule(static,omp_chunk_size)) + SU2_OMP_PARALLEL_(for schedule(static,omp_chunk_size)) for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) for (unsigned short iVar = 0; iVar < nVar; iVar++) - nodes->Add_DeltaSolution(iPoint, iVar, LinSysSol[iPoint*nVar+iVar]); + nodes->Add_DeltaSolution(iPoint, iVar, LinSysSol(iPoint,iVar)); /*--- Perform the MPI communication of the solution, displacements only. ---*/ @@ -2726,7 +2658,7 @@ void CFEASolver::GeneralizedAlpha_UpdateSolution(CGeometry *geometry, CSolver ** /*--- Compute solution at t_n+1, and update velocities and accelerations ---*/ - SU2_OMP(parallel for schedule(static,omp_chunk_size)) + SU2_OMP_PARALLEL_(for schedule(static,omp_chunk_size)) for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { unsigned short iVar; @@ -2788,23 +2720,32 @@ void CFEASolver::GeneralizedAlpha_UpdateLoads(CGeometry *geometry, CSolver **sol void CFEASolver::Solve_System(CGeometry *geometry, CConfig *config) { + SU2_OMP_PARALLEL + { /*--- Initialize residual and solution at the ghost points ---*/ - for (auto iPoint = nPointDomain; iPoint < nPoint; iPoint++) { - LinSysRes.SetBlock_Zero(iPoint); - LinSysSol.SetBlock_Zero(iPoint); - } - - IterLinSol = System.Solve(Jacobian, LinSysRes, LinSysSol, geometry, config); - - /*--- The the number of iterations of the linear solver ---*/ + SU2_OMP(sections) + { + SU2_OMP(section) + for (auto iPoint = nPointDomain; iPoint < nPoint; iPoint++) + LinSysRes.SetBlock_Zero(iPoint); - SetIterLinSolver(IterLinSol); + SU2_OMP(section) + for (auto iPoint = nPointDomain; iPoint < nPoint; iPoint++) + LinSysSol.SetBlock_Zero(iPoint); + } - /*--- Store the value of the residual. ---*/ + /*--- Solve or smooth the linear system. ---*/ - SetResLinSolver(System.GetResidual()); + auto iter = System.Solve(Jacobian, LinSysRes, LinSysSol, geometry, config); + SU2_OMP_MASTER + { + SetIterLinSolver(iter); + SetResLinSolver(System.GetResidual()); + } + SU2_OMP_BARRIER + } // end SU2_OMP_PARALLEL } @@ -2821,7 +2762,7 @@ void CFEASolver::PredictStruct_Displacement(CGeometry **fea_geometry, cout << "Higher order predictor not implemented. Solving with order 0." << endl; /*--- To nPointDomain: we need to communicate the predicted solution after setting it. ---*/ - SU2_OMP(parallel for schedule(static,omp_chunk_size)) + SU2_OMP_PARALLEL_(for schedule(static,omp_chunk_size)) for (unsigned long iPoint=0; iPoint < nPointDomain; iPoint++) { unsigned short iDim; @@ -2956,7 +2897,7 @@ void CFEASolver::SetAitken_Relaxation(CGeometry **fea_geometry, const su2double WAitken = GetWAitken_Dyn(); // To nPointDomain; we need to communicate the solutions (predicted, old and old predicted) after this routine - SU2_OMP(parallel for schedule(static,omp_chunk_size)) + SU2_OMP_PARALLEL_(for schedule(static,omp_chunk_size)) for (unsigned long iPoint=0; iPoint < nPointDomain; iPoint++) { /*--- Retrieve pointers to the predicted and calculated solutions ---*/ @@ -2981,7 +2922,7 @@ void CFEASolver::Update_StructSolution(CGeometry **fea_geometry, CConfig *fea_config, CSolver ***fea_solution) { - SU2_OMP(parallel for schedule(static,omp_chunk_size)) + SU2_OMP_PARALLEL_(for schedule(static,omp_chunk_size)) for (unsigned long iPoint=0; iPoint < nPointDomain; iPoint++) { auto valSolutionPred = fea_solution[MESH_0][FEA_SOL]->GetNodes()->GetSolution_Pred(iPoint); @@ -3074,7 +3015,11 @@ void CFEASolver::Compute_OFRefGeom(CGeometry *geometry, CSolver **solver_contain su2double objective_function = 0.0; - SU2_OMP(parallel for schedule(static,omp_chunk_size) reduction(+:objective_function)) + SU2_OMP_PARALLEL + { + su2double obj_fun_local = 0.0; + + SU2_OMP_FOR_STAT(omp_chunk_size) for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { for (unsigned short iVar = 0; iVar < nVar; iVar++) { @@ -3086,9 +3031,10 @@ void CFEASolver::Compute_OFRefGeom(CGeometry *geometry, CSolver **solver_contain su2double current_solution = nodes->GetSolution(iPoint,iVar); /*--- The objective function is the sum of the difference between solution and difference, squared ---*/ - objective_function += pow(current_solution - reference_geometry, 2); + obj_fun_local += pow(current_solution - reference_geometry, 2); } - + } + atomicAdd(obj_fun_local, objective_function); } SU2_MPI::Allreduce(&objective_function, &Total_OFRefGeom, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); @@ -3211,17 +3157,25 @@ void CFEASolver::Compute_OFVolFrac(CGeometry *geometry, CSolver **solver_contain su2double total_volume = 0.0, integral = 0.0, discreteness = 0.0; - SU2_OMP(parallel for schedule(static,omp_chunk_size) reduction(+:total_volume,integral,discreteness)) + SU2_OMP_PARALLEL + { + su2double tot_vol_loc = 0.0, integral_loc = 0.0, discrete_loc = 0.0; + + SU2_OMP_FOR_STAT(omp_chunk_size) for (unsigned long iElem = 0; iElem < nElement; ++iElem) { /*--- count only elements that belong to the partition ---*/ - if ( geometry->node[geometry->elem[iElem]->GetNode(0)]->GetDomain() ){ + if (geometry->node[geometry->elem[iElem]->GetNode(0)]->GetDomain()) { su2double volume = geometry->elem[iElem]->GetVolume(); su2double rho = element_properties[iElem]->GetPhysicalDensity(); - total_volume += volume; - integral += volume*rho; - discreteness += volume*4.0*rho*(1.0-rho); + tot_vol_loc += volume; + integral_loc += volume*rho; + discrete_loc += volume*4.0*rho*(1.0-rho); } } + atomicAdd(tot_vol_loc, total_volume); + atomicAdd(integral_loc, integral); + atomicAdd(discrete_loc, discreteness); + } su2double tmp; SU2_MPI::Allreduce(&total_volume,&tmp,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); @@ -3266,7 +3220,11 @@ void CFEASolver::Compute_OFCompliance(CGeometry *geometry, CSolver **solver_cont su2double compliance = 0.0; - SU2_OMP(parallel for schedule(static,omp_chunk_size) reduction(+:compliance)) + SU2_OMP_PARALLEL + { + su2double comp_local = 0.0; + + SU2_OMP_FOR_STAT(omp_chunk_size) for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { unsigned short iVar; @@ -3292,7 +3250,9 @@ void CFEASolver::Compute_OFCompliance(CGeometry *geometry, CSolver **solver_cont /*--- Add work contribution from this node ---*/ for (iVar = 0; iVar < nVar; iVar++) - compliance += nodalForce[iVar]*nodes->GetSolution(iPoint,iVar); + comp_local += nodalForce[iVar]*nodes->GetSolution(iPoint,iVar); + } + atomicAdd(comp_local, compliance); } SU2_MPI::Allreduce(&compliance, &Total_OFCompliance, 1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); @@ -3318,7 +3278,11 @@ void CFEASolver::Stiffness_Penalty(CGeometry *geometry, CSolver **solver, CNumer su2double totalVolume_reduce = 0.0; /*--- Loop over the elements in the domain. ---*/ - SU2_OMP(parallel for schedule(dynamic,omp_chunk_size) reduction(+:weightedValue,totalVolume)) + SU2_OMP_PARALLEL + { + su2double weighted_loc = 0.0, totalVol_loc = 0.0; + + SU2_OMP_FOR_DYN(omp_chunk_size) for (unsigned long iElem = 0; iElem < nElement; iElem++) { int thread = omp_get_thread_num(); @@ -3353,16 +3317,18 @@ void CFEASolver::Stiffness_Penalty(CGeometry *geometry, CSolver **solver, CNumer elementVolume = element->ComputeVolume(); // Compute the total volume - totalVolume += elementVolume; + totalVol_loc += elementVolume; // Retrieve the value of the design variable su2double dvValue = numerics[FEA_TERM]->Get_DV_Val(element_properties[iElem]->GetDV()); // Add the weighted sum of the value of the design variable - weightedValue += dvValue * elementVolume; + weighted_loc += dvValue * elementVolume; } - + } + atomicAdd(totalVol_loc, totalVolume); + atomicAdd(weighted_loc, weightedValue); } // Reduce value across processors for parallelization @@ -3550,7 +3516,7 @@ void CFEASolver::FilterElementDensities(CGeometry *geometry, CConfig *config) /*--- "Rectify" the input, initialize the physical density with the design density (the filter function works in-place). ---*/ - SU2_OMP(parallel for schedule(static,omp_chunk_size)) + SU2_OMP_PARALLEL_(for schedule(static,omp_chunk_size)) for (auto iElem=0ul; iElemGetDesignDensity(); if (rho > 1.0) physical_rho[iElem] = 1.0; diff --git a/SU2_CFD/src/solvers/CHeatSolver.cpp b/SU2_CFD/src/solvers/CHeatSolver.cpp index 24cb96b9571f..f383a5ee6d55 100644 --- a/SU2_CFD/src/solvers/CHeatSolver.cpp +++ b/SU2_CFD/src/solvers/CHeatSolver.cpp @@ -504,8 +504,10 @@ void CHeatSolver::SetUndivided_Laplacian(CGeometry *geometry, CConfig *config) { } -void CHeatSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, - CConfig *config, unsigned short iMesh, unsigned short iRKStep) { +void CHeatSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, + CConfig *config, unsigned short iMesh, unsigned short iRKStep) { + + CNumerics* numerics = numerics_container[CONV_TERM]; su2double *V_i, *V_j, Temp_i, Temp_j; unsigned long iEdge, iPoint, jPoint; @@ -550,7 +552,10 @@ void CHeatSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_contai } } -void CHeatSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short iMesh) { +void CHeatSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[CONV_TERM]; su2double *V_i, *V_j, Temp_i, Temp_i_Corrected, Temp_j, Temp_j_Corrected, **Gradient_i, **Gradient_j, Project_Grad_i, Project_Grad_j, **Temp_i_Grad, **Temp_j_Grad, Project_Temp_i_Grad, Project_Temp_j_Grad; @@ -644,7 +649,10 @@ void CHeatSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_containe } -void CHeatSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { +void CHeatSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, + CConfig *config, unsigned short iMesh, unsigned short iRKStep) { + + CNumerics* numerics = numerics_container[VISC_TERM]; su2double laminar_viscosity, Prandtl_Lam, Prandtl_Turb, eddy_viscosity_i, eddy_viscosity_j, thermal_diffusivity_i, thermal_diffusivity_j, Temp_i, Temp_j, **Temp_i_Grad, **Temp_j_Grad; @@ -708,15 +716,10 @@ void CHeatSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_contain LinSysRes.SubtractBlock(iPoint, Residual); LinSysRes.AddBlock(jPoint, Residual); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); - Jacobian.SubtractBlock(iPoint, jPoint, Jacobian_j); - Jacobian.AddBlock(jPoint, iPoint, Jacobian_i); - Jacobian.AddBlock(jPoint, jPoint, Jacobian_j); + Jacobian.UpdateBlocksSub(iEdge, iPoint, jPoint, Jacobian_i, Jacobian_j); } } -void CHeatSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, CConfig *config, unsigned short iMesh) { } - void CHeatSolver::Set_Heatflux_Areas(CGeometry *geometry, CConfig *config) { unsigned short iMarker, iMarker_HeatFlux, Monitoring, iDim; @@ -765,15 +768,9 @@ void CHeatSolver::Set_Heatflux_Areas(CGeometry *geometry, CConfig *config) { } } } -#ifdef HAVE_MPI - SU2_MPI::Allreduce(Local_Surface_Areas, Surface_Areas, config->GetnMarker_HeatFlux(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&Local_HeatFlux_Areas_Monitor, &Total_HeatFlux_Areas_Monitor, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); -#else - for( iMarker_HeatFlux = 0; iMarker_HeatFlux < config->GetnMarker_HeatFlux(); iMarker_HeatFlux++ ) { - Surface_Areas[iMarker_HeatFlux] = Local_Surface_Areas[iMarker_HeatFlux]; - } - Total_HeatFlux_Areas_Monitor = Local_HeatFlux_Areas_Monitor; -#endif + + SU2_MPI::Allreduce(Local_Surface_Areas, Surface_Areas, config->GetnMarker_HeatFlux(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + SU2_MPI::Allreduce(&Local_HeatFlux_Areas_Monitor, &Total_HeatFlux_Areas_Monitor, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); Total_HeatFlux_Areas = 0.0; for( iMarker_HeatFlux = 0; iMarker_HeatFlux < config->GetnMarker_HeatFlux(); iMarker_HeatFlux++ ) { @@ -843,7 +840,7 @@ void CHeatSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_conta } LinSysRes.SubtractBlock(iPoint, Res_Visc); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } } } @@ -977,7 +974,7 @@ void CHeatSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } /*--- Viscous contribution ---*/ @@ -1011,7 +1008,7 @@ void CHeatSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, /*--- Viscous contribution to the residual at the wall ---*/ LinSysRes.SubtractBlock(iPoint, Res_Visc); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } } } @@ -1080,7 +1077,7 @@ void CHeatSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } } } @@ -1098,7 +1095,7 @@ void CHeatSolver::BC_ConjugateHeat_Interface(CGeometry *geometry, CSolver **solv su2double thermal_diffusivity, rho_cp_solid, Temperature_Ref, T_Conjugate, Tinterface, Tnormal_Conjugate, HeatFluxDensity, HeatFlux, Area; - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); bool flow = ((config->GetKind_Solver() == INC_NAVIER_STOKES) || (config->GetKind_Solver() == INC_RANS) || (config->GetKind_Solver() == DISC_ADJ_INC_NAVIER_STOKES) @@ -1173,7 +1170,7 @@ void CHeatSolver::BC_ConjugateHeat_Interface(CGeometry *geometry, CSolver **solv if (implicit) { Jacobian_i[0][0] = thermal_diffusivity*Area; - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } } } @@ -1803,7 +1800,7 @@ void CHeatSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con Jacobian_i[iVar][iVar] = (Volume_nP1*3.0)/(2.0*TimeStep); } - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } } } diff --git a/SU2_CFD/src/solvers/CIncEulerSolver.cpp b/SU2_CFD/src/solvers/CIncEulerSolver.cpp index 25045f2c7ce5..275e296a7523 100644 --- a/SU2_CFD/src/solvers/CIncEulerSolver.cpp +++ b/SU2_CFD/src/solvers/CIncEulerSolver.cpp @@ -1812,9 +1812,11 @@ void CIncEulerSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_contain } -void CIncEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, +void CIncEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { + CNumerics* numerics = numerics_container[CONV_TERM]; + unsigned long iEdge, iPoint, jPoint; bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); @@ -1851,24 +1853,26 @@ void CIncEulerSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_co /*--- Compute residuals, and Jacobians ---*/ - numerics->ComputeResidual(Res_Conv, Jacobian_i, Jacobian_j, config); + auto residual = numerics->ComputeResidual(config); /*--- Update convective and artificial dissipation residuals ---*/ - LinSysRes.AddBlock(iPoint, Res_Conv); - LinSysRes.SubtractBlock(jPoint, Res_Conv); + LinSysRes.AddBlock(iPoint, residual); + LinSysRes.SubtractBlock(jPoint, residual); /*--- Store implicit contributions from the residual calculation. ---*/ if (implicit) { - Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, Jacobian_i, Jacobian_j); + Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, residual.jacobian_i, residual.jacobian_j); } } } -void CIncEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, - CConfig *config, unsigned short iMesh) { +void CIncEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[CONV_TERM]; su2double **Gradient_i, **Gradient_j, Project_Grad_i, Project_Grad_j, *V_i, *V_j, *S_i, *S_j, *Limiter_i = NULL, *Limiter_j = NULL; @@ -1997,49 +2001,45 @@ void CIncEulerSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_cont /*--- Compute the residual ---*/ - numerics->ComputeResidual(Res_Conv, Jacobian_i, Jacobian_j, config); + auto residual = numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Res_Conv); - LinSysRes.SubtractBlock(jPoint, Res_Conv); + LinSysRes.AddBlock(iPoint, residual); + LinSysRes.SubtractBlock(jPoint, residual); /*--- Set implicit Jacobians ---*/ if (implicit) { - Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, Jacobian_i, Jacobian_j); + Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, residual.jacobian_i, residual.jacobian_j); } } /*--- Warning message about non-physical reconstructions. ---*/ if (config->GetComm_Level() == COMM_FULL) { -#ifdef HAVE_MPI - SU2_MPI::Reduce(&counter_local, &counter_global, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD); -#else - counter_global = counter_local; -#endif - if (iMesh == MESH_0) config->SetNonphysical_Reconstr(counter_global); + if (iMesh == MESH_0) { + SU2_MPI::Reduce(&counter_local, &counter_global, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD); + config->SetNonphysical_Reconstr(counter_global); + } } } -void CIncEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, CConfig *config, unsigned short iMesh) { +void CIncEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[SOURCE_FIRST_TERM]; unsigned short iVar; unsigned long iPoint; - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - bool rotating_frame = config->GetRotating_Frame(); - bool axisymmetric = config->GetAxisymmetric(); - bool body_force = config->GetBody_Force(); - bool boussinesq = (config->GetKind_DensityModel() == BOUSSINESQ); - bool viscous = config->GetViscous(); - - - /*--- Initialize the source residual to zero ---*/ - - for (iVar = 0; iVar < nVar; iVar++) Residual[iVar] = 0.0; + const bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + const bool rotating_frame = config->GetRotating_Frame(); + const bool axisymmetric = config->GetAxisymmetric(); + const bool body_force = config->GetBody_Force(); + const bool boussinesq = (config->GetKind_DensityModel() == BOUSSINESQ); + const bool viscous = config->GetViscous(); if (body_force) { @@ -2063,11 +2063,11 @@ void CIncEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_cont /*--- Compute the rotating frame source residual ---*/ - numerics->ComputeResidual(Residual, config); + auto residual = numerics->ComputeResidual(config); /*--- Add the source residual to the total ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); } } @@ -2094,11 +2094,11 @@ void CIncEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_cont /*--- Compute the rotating frame source residual ---*/ - numerics->ComputeResidual(Residual, config); + auto residual = numerics->ComputeResidual(config); /*--- Add the source residual to the total ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); } } @@ -2123,51 +2123,38 @@ void CIncEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_cont /*--- Compute the rotating frame source residual ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, config); + auto residual = numerics->ComputeResidual(config); /*--- Add the source residual to the total ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Add the implicit Jacobian contribution ---*/ - if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } } if (axisymmetric) { - /*--- Zero out Jacobian structure ---*/ - - if (implicit) { - for (iVar = 0; iVar < nVar; iVar ++) - for (unsigned short jVar = 0; jVar < nVar; jVar ++) - Jacobian_i[iVar][jVar] = 0.0; - } - /*--- For viscous problems, we need an additional gradient. ---*/ if (viscous) { - su2double AuxVar, Total_Viscosity, yCoord, yVelocity; - for (iPoint = 0; iPoint < nPoint; iPoint++) { - yCoord = geometry->node[iPoint]->GetCoord(1); - yVelocity = nodes->GetVelocity(iPoint,1); - Total_Viscosity = (nodes->GetLaminarViscosity(iPoint) + - nodes->GetEddyViscosity(iPoint)); - - if (yCoord > EPS) { + su2double yCoord = geometry->node[iPoint]->GetCoord(1); + su2double yVelocity = nodes->GetVelocity(iPoint,1); + su2double Total_Viscosity = (nodes->GetLaminarViscosity(iPoint) + + nodes->GetEddyViscosity(iPoint)); + su2double AuxVar = 0.0; + if (yCoord > EPS) AuxVar = Total_Viscosity*yVelocity/yCoord; - } else { - AuxVar = 0.0; - } /*--- Set the auxilairy variable for this node. ---*/ - nodes->SetAuxVar(iPoint,AuxVar); + nodes->SetAuxVar(iPoint, AuxVar); } @@ -2220,15 +2207,16 @@ void CIncEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_cont /*--- Compute Source term Residual ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, config); + auto residual = numerics->ComputeResidual(config); /*--- Add Residual ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Implicit part ---*/ - if (implicit) Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (implicit) + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } } @@ -2255,14 +2243,11 @@ void CIncEulerSolver::Source_Residual(CGeometry *geometry, CSolver **solver_cont vector sourceMan(nVar,0.0); VerificationSolution->GetMMSSourceTerm(coor, time, sourceMan.data()); - /*--- Compute the residual for this control volume. ---*/ + /*--- Compute the residual for this control volume and subtract. ---*/ for (iVar = 0; iVar < nVar; iVar++) { - Residual[iVar] = sourceMan[iVar]*Volume; + LinSysRes[iPoint*nVar+iVar] -= sourceMan[iVar]*Volume; } - /*--- Subtract Residual ---*/ - LinSysRes.SubtractBlock(iPoint, Residual); - } } } @@ -3446,7 +3431,7 @@ void CIncEulerSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **sol Preconditioner[iVar][jVar] = Delta*Preconditioner[iVar][jVar]; } } - Jacobian.AddBlock(iPoint, iPoint, Preconditioner); + Jacobian.AddBlock2Diag(iPoint, Preconditioner); } else { Jacobian.SetVal2Diag(iPoint, 1.0); for (iVar = 0; iVar < nVar; iVar++) { @@ -4079,16 +4064,16 @@ void CIncEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_contain /*--- Compute the convective residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Convective Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); /*--- Viscous residual contribution ---*/ @@ -4120,13 +4105,13 @@ void CIncEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_contain /*--- Compute and update viscous residual ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.SubtractBlock(iPoint, Residual); + auto residual = visc_numerics->ComputeResidual(config); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Viscous Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } @@ -4331,16 +4316,16 @@ void CIncEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); /*--- Viscous contribution, commented out because serious convergence problems ---*/ @@ -4372,14 +4357,14 @@ void CIncEulerSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, /*--- Compute and update residual ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = visc_numerics->ComputeResidual(config); - LinSysRes.SubtractBlock(iPoint, Residual); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } @@ -4539,16 +4524,16 @@ void CIncEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) { - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } /*--- Viscous contribution, commented out because serious convergence problems ---*/ @@ -4581,13 +4566,13 @@ void CIncEulerSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, /*--- Compute and update residual ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = visc_numerics->ComputeResidual(config); - LinSysRes.SubtractBlock(iPoint, Residual); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } @@ -4757,14 +4742,14 @@ void CIncEulerSolver::BC_Sym_Plane(CGeometry *geometry, conv_numerics->SetSecondary(nodes->GetSecondary(iPoint), nodes->GetSecondary(iPoint)); /*--- Compute the residual using an upwind scheme. ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Update residual value ---*/ - LinSysRes.AddBlock(iPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration. ---*/ if (implicit) { - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } if (viscous) { @@ -4860,13 +4845,13 @@ void CIncEulerSolver::BC_Sym_Plane(CGeometry *geometry, /*--- Compute and update residual. Note that the viscous shear stress tensor is computed in the following routine based upon the velocity-component gradients. ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = visc_numerics->ComputeResidual(config); - LinSysRes.SubtractBlock(iPoint, Residual); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration. ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); }//if viscous }//if GetDomain }//for iVertex @@ -4884,14 +4869,14 @@ void CIncEulerSolver::BC_Sym_Plane(CGeometry *geometry, } -void CIncEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, - CConfig *config) { +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, iMarker, nDonorVertex; + unsigned short iDim, iVar, jVar, iMarker, nDonorVertex; - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - bool viscous = config->GetViscous(); + bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + bool viscous = config->GetViscous(); su2double *Normal = new su2double[nDim]; su2double *PrimVar_i = new su2double[nPrimVar]; @@ -4913,12 +4898,15 @@ void CIncEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_c /*--- Initialize Residual, this will serve to accumulate the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) + 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++){ + for (jVertex = 0; jVertex < nDonorVertex; jVertex++) { Point_Normal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor(); @@ -4948,12 +4936,15 @@ void CIncEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_c /*--- Compute the convective residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(tmp_residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Accumulate the residuals to compute the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] += weight*tmp_residual[iVar]; + 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]; + } } @@ -4961,14 +4952,17 @@ void CIncEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_c LinSysRes.AddBlock(iPoint, Residual); if (implicit) - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); if (viscous) { /*--- Initialize Residual, this will serve to accumulate the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) + 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 ---*/ @@ -5001,12 +4995,15 @@ void CIncEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_c /*--- Compute and update residual ---*/ - visc_numerics->ComputeResidual(tmp_residual, Jacobian_i, Jacobian_j, config); + auto residual = visc_numerics->ComputeResidual(config); /*--- Accumulate the residuals to compute the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] += weight*tmp_residual[iVar]; + 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); @@ -5014,7 +5011,7 @@ void CIncEulerSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_c /*--- Jacobian contribution for implicit integration ---*/ if (implicit) - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } } @@ -5237,7 +5234,7 @@ void CIncEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver } } - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } } @@ -5461,7 +5458,7 @@ void CIncEulerSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver Jacobian_i[nDim+1][iVar] = 0.0; } } - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } } } diff --git a/SU2_CFD/src/solvers/CIncNSSolver.cpp b/SU2_CFD/src/solvers/CIncNSSolver.cpp index aa5cc6887618..9fe1fe3bbd84 100644 --- a/SU2_CFD/src/solvers/CIncNSSolver.cpp +++ b/SU2_CFD/src/solvers/CIncNSSolver.cpp @@ -800,11 +800,8 @@ void CIncNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container SU2_MPI::Allreduce(&MyOmega_Max, &Omega_Max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); #endif - if (iMesh == MESH_0) { + if (iMesh == MESH_0) config->SetNonphysical_Points(ErrorCounter); - solver_container[FLOW_SOL]->SetStrainMag_Max(StrainMag_Max); - solver_container[FLOW_SOL]->SetOmega_Max(Omega_Max); - } } @@ -1086,8 +1083,10 @@ void CIncNSSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container, } -void CIncNSSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, - CConfig *config, unsigned short iMesh, unsigned short iRKStep) { +void CIncNSSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, + CConfig *config, unsigned short iMesh, unsigned short iRKStep) { + + CNumerics* numerics = numerics_container[VISC_TERM]; unsigned long iPoint, jPoint, iEdge; @@ -1121,18 +1120,15 @@ void CIncNSSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_contai /*--- Compute and update residual ---*/ - numerics->ComputeResidual(Res_Visc, Jacobian_i, Jacobian_j, config); + auto residual = numerics->ComputeResidual(config); - LinSysRes.SubtractBlock(iPoint, Res_Visc); - LinSysRes.AddBlock(jPoint, Res_Visc); + LinSysRes.SubtractBlock(iPoint, residual); + LinSysRes.AddBlock(jPoint, residual); /*--- Implicit part ---*/ if (implicit) { - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); - Jacobian.SubtractBlock(iPoint, jPoint, Jacobian_j); - Jacobian.AddBlock(jPoint, iPoint, Jacobian_i); - Jacobian.AddBlock(jPoint, jPoint, Jacobian_j); + Jacobian.UpdateBlocksSub(iEdge, iPoint, jPoint, residual.jacobian_i, residual.jacobian_j); } } @@ -1601,7 +1597,8 @@ void CIncNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { } -void CIncNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CIncNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iDim, iVar, jVar;// Wall_Function; unsigned long iVertex, iPoint, total_index; @@ -1702,7 +1699,8 @@ void CIncNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_contai } } -void CIncNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CIncNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iDim, iVar, jVar, Wall_Function; unsigned long iVertex, iPoint, Point_Normal, total_index; @@ -1823,7 +1821,7 @@ void CIncNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_cont Jacobian_i[nDim+1][nDim+1] = -thermal_conductivity*proj_vector_ij; - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } /*--- Viscous contribution to the residual at the wall ---*/ @@ -1948,6 +1946,7 @@ void CIncNSSolver::BC_ConjugateHeat_Interface(CGeometry *geometry, CSolver **sol Twall = Tconjugate; } else { + Twall = 0.0; SU2_MPI::Error("Unknown CHT coupling method.", CURRENT_FUNCTION); } diff --git a/SU2_CFD/src/solvers/CMeshSolver.cpp b/SU2_CFD/src/solvers/CMeshSolver.cpp index f7b284db65c5..0d4e959a1ac6 100644 --- a/SU2_CFD/src/solvers/CMeshSolver.cpp +++ b/SU2_CFD/src/solvers/CMeshSolver.cpp @@ -105,17 +105,19 @@ CMeshSolver::CMeshSolver(CGeometry *geometry, CConfig *config) : CFEASolver(true const auto& coloring = geometry->GetElementColoring(); - auto nColor = coloring.getOuterSize(); - ElemColoring.resize(nColor); + if (!coloring.empty()) { + auto nColor = coloring.getOuterSize(); + ElemColoring.reserve(nColor); - for(auto iColor = 0ul; iColor < nColor; ++iColor) { - ElemColoring[iColor].size = coloring.getNumNonZeros(iColor); - ElemColoring[iColor].indices = coloring.innerIdx(iColor); + for(auto iColor = 0ul; iColor < nColor; ++iColor) { + ElemColoring.emplace_back(coloring.innerIdx(iColor), coloring.getNumNonZeros(iColor)); + } } - ColorGroupSize = geometry->GetElementColorGroupSize(); omp_chunk_size = computeStaticChunkSize(nPointDomain, omp_get_max_threads(), OMP_MAX_SIZE); +#else + ElemColoring[0] = DummyGridColor<>(nElement); #endif /*--- Structural parameters ---*/ @@ -184,13 +186,16 @@ void CMeshSolver::SetMinMaxVolume(CGeometry *geometry, CConfig *config, bool upd /*--- Shared reduction variables. ---*/ unsigned long ElemCounter = 0; - su2double MaxVolume = -1E22, MinVolume = -1E22; + su2double MaxVolume = -1E22, MinVolume = 1E22; SU2_OMP_PARALLEL { + /*--- Local min/max, final reduction outside loop. ---*/ + su2double maxVol = -1E22, minVol = 1E22; + /*--- Loop over the elements in the domain. ---*/ - SU2_OMP(for schedule(dynamic,omp_chunk_size) reduction(max:MaxVolume,MinVolume)) + SU2_OMP(for schedule(dynamic,omp_chunk_size) reduction(+:ElemCounter) nowait) for (unsigned long iElem = 0; iElem < nElement; iElem++) { int thread = omp_get_thread_num(); @@ -225,19 +230,21 @@ void CMeshSolver::SetMinMaxVolume(CGeometry *geometry, CConfig *config, bool upd if (nDim == 2) ElemVolume = fea_elem->ComputeArea(); else ElemVolume = fea_elem->ComputeVolume(); - MaxVolume = max(MaxVolume, ElemVolume); - MinVolume = max(MinVolume, -1.0*ElemVolume); + maxVol = max(maxVol, ElemVolume); + minVol = min(minVol, ElemVolume); if (updated) element[iElem].SetCurr_Volume(ElemVolume); else element[iElem].SetRef_Volume(ElemVolume); /*--- Count distorted elements. ---*/ - if (ElemVolume <= 0.0) { - SU2_OMP(atomic) - ElemCounter++; - } + if (ElemVolume <= 0.0) ElemCounter++; } - MinVolume *= -1.0; + SU2_OMP_CRITICAL + { + MaxVolume = max(MaxVolume, maxVol); + MinVolume = min(MinVolume, minVol); + } + SU2_OMP_BARRIER SU2_OMP_MASTER { @@ -483,7 +490,7 @@ void CMeshSolver::UpdateGridCoord(CGeometry *geometry, CConfig *config){ /*--- Update the grid coordinates using the solution of the linear system ---*/ /*--- LinSysSol contains the absolute x, y, z displacements. ---*/ - SU2_OMP(parallel for schedule(static,omp_chunk_size)) + SU2_OMP_PARALLEL_(for schedule(static,omp_chunk_size)) for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++){ for (unsigned short iDim = 0; iDim < nDim; iDim++) { auto total_index = iPoint*nDim + iDim; @@ -528,7 +535,7 @@ void CMeshSolver::ComputeGridVelocity(CGeometry *geometry, CConfig *config){ /*--- Compute the velocity of each node in the domain of the current rank (halo nodes are not computed as the grid velocity is later communicated). ---*/ - SU2_OMP(parallel for schedule(static,omp_chunk_size)) + SU2_OMP_PARALLEL_(for schedule(static,omp_chunk_size)) for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Coordinates of the current point at n+1, n, & n-1 time levels. ---*/ diff --git a/SU2_CFD/src/solvers/CNSSolver.cpp b/SU2_CFD/src/solvers/CNSSolver.cpp index 96065b8dea4d..03263d0d9aab 100644 --- a/SU2_CFD/src/solvers/CNSSolver.cpp +++ b/SU2_CFD/src/solvers/CNSSolver.cpp @@ -30,358 +30,15 @@ #include "../../include/variables/CNSVariable.hpp" #include "../../../Common/include/toolboxes/printing_toolbox.hpp" -CNSSolver::CNSSolver(void) : CEulerSolver() { +CNSSolver::CNSSolver(void) : CEulerSolver() { } - /*--- Basic array initialization ---*/ +CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) : + CEulerSolver(geometry, config, iMesh, true) { - CD_Visc = NULL; CL_Visc = NULL; CSF_Visc = NULL; CEff_Visc = NULL; - CFx_Visc = NULL; CFy_Visc = NULL; CFz_Visc = NULL; - CMx_Visc = NULL; CMy_Visc = NULL; CMz_Visc = NULL; - CoPx_Visc = NULL; CoPy_Visc = NULL; CoPz_Visc = NULL; + /*--- This constructor only allocates/inits what is extra to CEulerSolver. ---*/ - ForceViscous = NULL; MomentViscous = NULL; CSkinFriction = NULL; - - Buffet_Sensor = NULL; Buffet_Metric = NULL; - - /*--- Surface based array initialization ---*/ - - Surface_CL_Visc = NULL; Surface_CD_Visc = NULL; Surface_CSF_Visc = NULL; Surface_CEff_Visc = NULL; - Surface_CFx_Visc = NULL; Surface_CFy_Visc = NULL; Surface_CFz_Visc = NULL; - Surface_CMx_Visc = NULL; Surface_CMy_Visc = NULL; Surface_CMz_Visc = NULL; - Surface_HF_Visc = NULL; Surface_MaxHF_Visc = NULL; Surface_Buffet_Metric = NULL; - - /*--- Rotorcraft simulation array initialization ---*/ - - CMerit_Visc = NULL; CT_Visc = NULL; CQ_Visc = NULL; - HF_Visc = NULL; MaxHF_Visc = NULL; - - /*--- Inlet Variables ---*/ - Inlet_Ttotal = NULL; - Inlet_Ptotal = NULL; - Inlet_FlowDir = NULL; - - SlidingState = NULL; - SlidingStateNodes = NULL; - - DonorPrimVar = NULL; DonorGlobalIndex = NULL; - - HeatConjugateVar = NULL; - -} - -CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) : CEulerSolver() { - - unsigned long iPoint, counter_local = 0, counter_global = 0, iVertex; - unsigned short iVar, iDim, iMarker, nLineLets; - su2double Density, Velocity2, Pressure, Temperature, StaticEnergy; - ifstream restart_file; - unsigned short nZone = geometry->GetnZone(); - bool restart = (config->GetRestart() || config->GetRestart_Flow()); - int Unst_RestartIter = 0; - bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || - (config->GetTime_Marching() == DT_STEPPING_2ND)); - bool time_stepping = config->GetTime_Marching() == TIME_STEPPING; - - /* 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(); - - bool roe_turkel = (config->GetKind_Upwind_Flow() == TURKEL); - bool low_mach_prec = config->Low_Mach_Preconditioning(); - - bool adjoint = (config->GetContinuous_Adjoint()) || (config->GetDiscrete_Adjoint()); - string filename_ = "flow"; - - unsigned short direct_diff = config->GetDirectDiff(); - bool rans = (config->GetKind_Turb_Model() != NONE); - - /*--- 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) && - (config->GetFixed_CL_Mode() || config->GetFixed_CM_Mode())) { - - /*--- 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; - } - - /*--- 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->GetFilename(filename_, ".meta", Unst_RestartIter); - - /*--- Read and store the restart metadata. ---*/ - - Read_SU2_Restart_Metadata(geometry, config, adjoint, filename_); - - } - - /*--- Array initialization ---*/ - - CD_Visc = NULL; CL_Visc = NULL; CSF_Visc = NULL; CEff_Visc = NULL; - CFx_Visc = NULL; CFy_Visc = NULL; CFz_Visc = NULL; - CMx_Visc = NULL; CMy_Visc = NULL; CMz_Visc = NULL; - CoPx_Visc = NULL; CoPy_Visc = NULL; CoPz_Visc = NULL; - - Buffet_Sensor = NULL; Buffet_Metric = NULL; - - Surface_CL_Visc = NULL; Surface_CD_Visc = NULL; Surface_CSF_Visc = NULL; Surface_CEff_Visc = NULL; - Surface_CFx_Visc = NULL; Surface_CFy_Visc = NULL; Surface_CFz_Visc = NULL; - Surface_CMx_Visc = NULL; Surface_CMy_Visc = NULL; Surface_CMz_Visc = NULL; - Surface_HF_Visc = NULL; Surface_MaxHF_Visc = NULL; - - Surface_Buffet_Metric = NULL; - - CMerit_Visc = NULL; CT_Visc = NULL; CQ_Visc = NULL; - MaxHF_Visc = NULL; ForceViscous = NULL; MomentViscous = NULL; - CSkinFriction = NULL; HF_Visc = NULL; - HeatConjugateVar = NULL; - - /*--- Initialize quantities for the average process for internal flow ---*/ - - AverageVelocity = NULL; - AverageTurboVelocity = NULL; - OldAverageTurboVelocity = NULL; - ExtAverageTurboVelocity = NULL; - AverageFlux = NULL; - SpanTotalFlux = NULL; - AveragePressure = NULL; - OldAveragePressure = NULL; - RadialEquilibriumPressure = NULL; - ExtAveragePressure = NULL; - AverageDensity = NULL; - OldAverageDensity = NULL; - ExtAverageDensity = NULL; - AverageNu = NULL; - AverageKine = NULL; - AverageOmega = NULL; - ExtAverageNu = NULL; - ExtAverageKine = NULL; - ExtAverageOmega = NULL; - - - /*--- Initialize primitive quantities for turboperformace ---*/ - - DensityIn = NULL; - PressureIn = NULL; - TurboVelocityIn = NULL; - DensityOut = NULL; - PressureOut = NULL; - TurboVelocityOut = NULL; - - - /*--- Initialize quantities for Giles BC ---*/ - - CkInflow = NULL; - CkOutflow1 = NULL; - CkOutflow2 = NULL; - - - - /*--- Set the gamma value ---*/ - - Gamma = config->GetGamma(); - Gamma_Minus_One = Gamma - 1.0; - - /*--- Define geometry constants in the solver structure - Compressible flow, primitive variables (T, vx, vy, vz, P, rho, h, c, lamMu, EddyMu, ThCond, Cp). - ---*/ - - nDim = geometry->GetnDim(); - - nVar = nDim+2; - nPrimVar = nDim+9; nPrimVarGrad = nDim+4; - nSecondaryVar = 8; nSecondaryVarGrad = 2; - - - /*--- 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]; - - /*--- 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; - Residual_i = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_i[iVar] = 0.0; - Residual_j = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_j[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 auxiliary vectors related to the Secondary solution ---*/ - - Secondary = new su2double[nSecondaryVar]; for (iVar = 0; iVar < nSecondaryVar; iVar++) Secondary[iVar] = 0.0; - Secondary_i = new su2double[nSecondaryVar]; for (iVar = 0; iVar < nSecondaryVar; iVar++) Secondary_i[iVar] = 0.0; - Secondary_j = new su2double[nSecondaryVar]; for (iVar = 0; iVar < nSecondaryVar; iVar++) Secondary_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]; - } - - /*--- Define some auxiliary vectors related to low-speed preconditioning ---*/ - - if (roe_turkel || low_mach_prec) { - LowMach_Precontioner = new su2double* [nVar]; - for (iVar = 0; iVar < nVar; iVar ++) - LowMach_Precontioner[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; - } - - /*--- Define some auxiliary vectors for computing flow variable - gradients by least squares, S matrix := inv(R)*traspose(inv(R)), - c vector := transpose(WA)*(Wb) ---*/ - - if (config->GetLeastSquaresRequired()) { - Smatrix = new su2double* [nDim]; - for (iDim = 0; iDim < nDim; iDim++) - Smatrix[iDim] = new su2double [nDim]; - - Cvector = new su2double* [nPrimVarGrad]; - for (iVar = 0; iVar < nPrimVarGrad; iVar++) - Cvector[iVar] = new su2double [nDim]; - } - - /*--- 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 value of the primitive variables + 2 turb variables at the boundaries, - used for IO with a donor cell ---*/ - - DonorPrimVar = new su2double** [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - DonorPrimVar[iMarker] = new su2double* [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - if (rans) { - DonorPrimVar[iMarker][iVertex] = new su2double [nPrimVar+2]; - for (iVar = 0; iVar < nPrimVar + 2 ; iVar++) { - DonorPrimVar[iMarker][iVertex][iVar] = 0.0; - } - } - else { - DonorPrimVar[iMarker][iVertex] = new su2double [nPrimVar]; - for (iVar = 0; iVar < nPrimVar ; iVar++) { - DonorPrimVar[iMarker][iVertex][iVar] = 0.0; - } - } - } - } - - /*--- Store the value of the characteristic primitive variables index at the boundaries ---*/ - - DonorGlobalIndex = new unsigned long* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - DonorGlobalIndex[iMarker] = new unsigned long [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - DonorGlobalIndex[iMarker][iVertex] = 0; - } - } + 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 ---*/ @@ -389,105 +46,29 @@ CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) 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] = new su2double* [nVertex[iMarker]]; + for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { + HeatConjugateVar[iMarker][iVertex] = new su2double [nHeatConjugateVar](); HeatConjugateVar[iMarker][iVertex][0] = config->GetTemperature_FreeStreamND(); } } - /*--- Store the value of the Delta P at the Actuator Disk ---*/ - - ActDisk_DeltaP = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - ActDisk_DeltaP[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - ActDisk_DeltaP[iMarker][iVertex] = 0; - } - } - - /*--- Store the value of the Delta T at the Actuator Disk ---*/ + /*--- Allocates a 2D array with variable "outer" sizes and init to 0. ---*/ - ActDisk_DeltaT = new su2double* [nMarker]; - for (iMarker = 0; iMarker < nMarker; iMarker++) { - ActDisk_DeltaT[iMarker] = new su2double [geometry->nVertex[iMarker]]; - for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { - ActDisk_DeltaT[iMarker][iVertex] = 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; - } - } - } - - /*--- 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; - } - } + 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]] (); + }; /*--- 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; - } - } + Alloc2D(nMarker, nVertex, HeatFlux); + Alloc2D(nMarker, nVertex, HeatFluxTarget); /*--- 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; - } - } + Alloc2D(nMarker, nVertex, YPlus); /*--- Skin friction in all the markers ---*/ @@ -495,376 +76,51 @@ CNSSolver::CNSSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) 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; - } - } - } - - /*--- Buffet sensor in all the markers ---*/ - - if(config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR){ - - Buffet_Sensor = new su2double*[nMarker]; - for(iMarker = 0; iMarker < nMarker; iMarker++) { - Buffet_Sensor[iMarker] = new su2double[geometry->nVertex[iMarker]]; + CSkinFriction[iMarker][iDim] = new su2double[nVertex[iMarker]] (); } - - } - - /*--- 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]; - CEff_Inv = new su2double[nMarker]; - CFx_Inv = new su2double[nMarker]; - CFy_Inv = new su2double[nMarker]; - CFz_Inv = new su2double[nMarker]; - CMx_Inv = new su2double[nMarker]; - CMy_Inv = new su2double[nMarker]; - CMz_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]; - CEff_Mnt = new su2double[nMarker]; - CFx_Mnt = new su2double[nMarker]; - CFy_Mnt = new su2double[nMarker]; - CFz_Mnt = new su2double[nMarker]; - CMx_Mnt = new su2double[nMarker]; - CMy_Mnt = new su2double[nMarker]; - CMz_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]; - CEff_Visc = new su2double[nMarker]; - CFx_Visc = new su2double[nMarker]; - CFy_Visc = new su2double[nMarker]; - CFz_Visc = new su2double[nMarker]; - CMx_Visc = new su2double[nMarker]; - CMy_Visc = new su2double[nMarker]; - CMz_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()]; - - if(config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR){ - - Buffet_Metric = new su2double[nMarker]; - Surface_Buffet_Metric = new su2double[config->GetnMarker_Monitoring()]; - } + /*--- Non dimensional aerodynamic coefficients ---*/ - /*--- Rotational coefficients ---*/ + ViscCoeff.allocate(nMarker); + SurfaceViscCoeff.allocate(config->GetnMarker_Monitoring()); - CMerit_Inv = new su2double[nMarker]; - CT_Inv = new su2double[nMarker]; - CQ_Inv = new su2double[nMarker]; + /*--- Heat flux and buffet coefficients ---*/ - CMerit_Mnt = new su2double[nMarker]; - CT_Mnt = new su2double[nMarker]; - CQ_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]; + HF_Visc = new su2double[nMarker]; MaxHF_Visc = new su2double[nMarker]; - /*--- Supersonic coefficients ---*/ + Surface_HF_Visc = new su2double[config->GetnMarker_Monitoring()]; + Surface_MaxHF_Visc = new su2double[config->GetnMarker_Monitoring()]; - CEquivArea_Inv = new su2double[nMarker]; - CNearFieldOF_Inv = new su2double[nMarker]; + /*--- Buffet sensor in all the markers and coefficients ---*/ - /*--- Engine simulation ---*/ - - 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]; + if(config->GetBuffet_Monitoring() || config->GetKind_ObjFunc() == BUFFET_SENSOR){ - /*--- Init total coefficients ---*/ + Alloc2D(nMarker, nVertex, Buffet_Sensor); + Buffet_Metric = new su2double[nMarker]; + Surface_Buffet_Metric = new su2double[config->GetnMarker_Monitoring()]; - 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_CEquivArea = 0.0; Total_CNearFieldOF = 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_NetThrust = 0.0; Total_Power = 0.0; - Total_CL_Prev = 0.0; Total_CD_Prev = 0.0; Total_CMx_Prev = 0.0; - Total_CMy_Prev = 0.0; Total_CMz_Prev = 0.0; - Total_AeroCD = 0.0; Total_SolidCD = 0.0; Total_IDR = 0.0; - Total_IDC = 0.0; - Total_Custom_ObjFunc = 0.0; + } /*--- 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(); Viscosity_Inf = config->GetViscosity_FreeStreamND(); - Mach_Inf = config->GetMach(); Prandtl_Lam = config->GetPrandtl_Lam(); Prandtl_Turb = config->GetPrandtl_Turb(); Tke_Inf = config->GetTke_FreeStreamND(); - /*--- Initialize the secondary values for direct derivative approxiations ---*/ + /*--- Initialize the seed values for forward mode differentiation. ---*/ - 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: + /*--- Already done upstream. ---*/ break; } - /*--- Initialize fan face pressure, fan face mach number, and mass flow rate ---*/ - - for (iMarker = 0; iMarker < nMarker; iMarker++) { - Inflow_MassFlow[iMarker] = 0.0; - Inflow_Mach[iMarker] = Mach_Inf; - Inflow_Pressure[iMarker] = Pressure_Inf; - Inflow_Area[iMarker] = 0.0; - - Exhaust_MassFlow[iMarker] = 0.0; - Exhaust_Temperature[iMarker] = Temperature_Inf; - Exhaust_Pressure[iMarker] = Pressure_Inf; - Exhaust_Area[iMarker] = 0.0; - - } - /*--- Initializate quantities for SlidingMesh Interface ---*/ - - SlidingState = new su2double*** [nMarker]; - SlidingStateNodes = new int* [nMarker]; - - for (iMarker = 0; iMarker < nMarker; iMarker++){ - - SlidingState[iMarker] = NULL; - SlidingStateNodes[iMarker] = NULL; - - 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] = NULL; - } - - } - } - - /*--- Only initialize when there is a Marker_Fluid_Load - *--- (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 CNSVariable(Density_Inf, Velocity_Inf, Energy_Inf, nPoint, nDim, nVar, config); - SetBaseClassPointerToNodes(); - - /*--- Check that the initial solution is physical, report any non-physical nodes ---*/ - - counter_local = 0; - - for (iPoint = 0; iPoint < nPoint; iPoint++) { - - Density = nodes->GetDensity(iPoint); - - Velocity2 = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Velocity2 += pow(nodes->GetSolution(iPoint,iDim+1)/Density,2); - - StaticEnergy= nodes->GetEnergy(iPoint) - 0.5*Velocity2; - - FluidModel->SetTDState_rhoe(Density, StaticEnergy); - Pressure= FluidModel->GetPressure(); - Temperature= FluidModel->GetTemperature(); - - /*--- Use the values at the infinity ---*/ - - if ((Pressure < 0.0) || (Density < 0.0) || (Temperature < 0.0)) { - Solution[0] = Density_Inf; - for (iDim = 0; iDim < nDim; iDim++) - Solution[iDim+1] = Velocity_Inf[iDim]*Density_Inf; - Solution[nDim+1] = Energy_Inf*Density_Inf; - nodes->SetSolution(iPoint,Solution); - nodes->SetSolution_Old(iPoint,Solution); - counter_local++; - } - - } - - /*--- Warning message about non-physical points ---*/ - - if (config->GetComm_Level() == COMM_FULL) { -#ifdef HAVE_MPI - SU2_MPI::Reduce(&counter_local, &counter_global, 1, MPI_UNSIGNED_LONG, MPI_SUM, MASTER_NODE, MPI_COMM_WORLD); -#else - counter_global = counter_local; -#endif - if ((rank == MASTER_NODE) && (counter_global != 0)) - 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]; 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 = "C.FLOW"; - } CNSSolver::~CNSSolver(void) { @@ -873,41 +129,13 @@ CNSSolver::~CNSSolver(void) { unsigned long iVertex; - if (CD_Visc != NULL) delete [] CD_Visc; - if (CL_Visc != NULL) delete [] CL_Visc; - if (CSF_Visc != NULL) delete [] CSF_Visc; - if (CFx_Visc != NULL) delete [] CFx_Visc; - if (CFy_Visc != NULL) delete [] CFy_Visc; - if (CFz_Visc != NULL) delete [] CFz_Visc; - if (CMx_Visc != NULL) delete [] CMx_Visc; - if (CMy_Visc != NULL) delete [] CMy_Visc; - if (CMz_Visc != NULL) delete [] CMz_Visc; - if (CoPx_Visc != NULL) delete [] CoPx_Visc; - if (CoPy_Visc != NULL) delete [] CoPy_Visc; - if (CoPz_Visc != NULL) delete [] CoPz_Visc; - if (CEff_Visc != NULL) delete [] CEff_Visc; - if (CMerit_Visc != NULL) delete [] CMerit_Visc; - if (Buffet_Metric != NULL) delete [] Buffet_Metric; - if (CT_Visc != NULL) delete [] CT_Visc; - if (CQ_Visc != NULL) delete [] CQ_Visc; - if (HF_Visc != NULL) delete [] HF_Visc; - if (MaxHF_Visc != NULL) delete [] MaxHF_Visc; - if (ForceViscous != NULL) delete [] ForceViscous; - if (MomentViscous != NULL) delete [] MomentViscous; - - if (Surface_CL_Visc != NULL) delete [] Surface_CL_Visc; - if (Surface_CD_Visc != NULL) delete [] Surface_CD_Visc; - if (Surface_CSF_Visc != NULL) delete [] Surface_CSF_Visc; - if (Surface_CEff_Visc != NULL) delete [] Surface_CEff_Visc; - if (Surface_CFx_Visc != NULL) delete [] Surface_CFx_Visc; - if (Surface_CFy_Visc != NULL) delete [] Surface_CFy_Visc; - if (Surface_CFz_Visc != NULL) delete [] Surface_CFz_Visc; - if (Surface_CMx_Visc != NULL) delete [] Surface_CMx_Visc; - if (Surface_CMy_Visc != NULL) delete [] Surface_CMy_Visc; - if (Surface_CMz_Visc != NULL) delete [] Surface_CMz_Visc; - if (Surface_HF_Visc != NULL) delete [] Surface_HF_Visc; - if (Surface_MaxHF_Visc != NULL) delete [] Surface_MaxHF_Visc; - if (Surface_Buffet_Metric != NULL) delete [] Surface_Buffet_Metric; + delete [] Buffet_Metric; + delete [] HF_Visc; + delete [] MaxHF_Visc; + + delete [] Surface_HF_Visc; + delete [] Surface_MaxHF_Visc; + delete [] Surface_Buffet_Metric; if (CSkinFriction != NULL) { for (iMarker = 0; iMarker < nMarker; iMarker++) { @@ -938,12 +166,10 @@ CNSSolver::~CNSSolver(void) { } -void CNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { +void CNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, + unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { - unsigned long iPoint, ErrorCounter = 0; - su2double StrainMag = 0.0, Omega = 0.0, *Vorticity; - - unsigned long InnerIter = config->GetInnerIter(); + unsigned long InnerIter = config->GetInnerIter(); bool cont_adjoint = config->GetContinuous_Adjoint(); bool disc_adjoint = config->GetDiscrete_Adjoint(); bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); @@ -966,26 +192,58 @@ void CNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, C /*--- Update the angle of attack at the far-field for fixed CL calculations (only direct problem). ---*/ - if ((fixed_cl) && (!disc_adjoint) && (!cont_adjoint)) { SetFarfield_AoA(geometry, solver_container, config, iMesh, Output); } + if (fixed_cl && !disc_adjoint && !cont_adjoint) { + SU2_OMP_MASTER + SetFarfield_AoA(geometry, solver_container, config, iMesh, Output); + SU2_OMP_BARRIER + } /*--- Set the primitive variables ---*/ - ErrorCounter = SetPrimitive_Variables(solver_container, config, Output); + SU2_OMP_MASTER + ErrorCounter = 0; + SU2_OMP_BARRIER + + SU2_OMP_ATOMIC + ErrorCounter += SetPrimitive_Variables(solver_container, config, Output); + + if ((iMesh == MESH_0) && (config->GetComm_Level() == COMM_FULL)) { + SU2_OMP_BARRIER + SU2_OMP_MASTER + { + unsigned long tmp = ErrorCounter; + SU2_MPI::Allreduce(&tmp, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); + config->SetNonphysical_Points(ErrorCounter); + } + SU2_OMP_BARRIER + } /*--- Compute the engine properties ---*/ - if (engine) { GetPower_Properties(geometry, config, iMesh, Output); } + if (engine) { + SU2_OMP_MASTER + GetPower_Properties(geometry, config, iMesh, Output); + SU2_OMP_BARRIER + } /*--- Compute the actuator disk properties and distortion levels ---*/ if (actuator_disk) { - Set_MPI_ActDisk(solver_container, geometry, config); - SetActDisk_BCThrust(geometry, solver_container, config, iMesh, Output); + SU2_OMP_MASTER + { + Set_MPI_ActDisk(solver_container, geometry, config); + SetActDisk_BCThrust(geometry, solver_container, config, iMesh, Output); + } + SU2_OMP_BARRIER } /*--- Compute NearField MPI ---*/ - if (nearfield) { Set_MPI_Nearfield(geometry, config); } + if (nearfield) { + SU2_OMP_MASTER + Set_MPI_Nearfield(geometry, config); + SU2_OMP_BARRIER + } /*--- Artificial dissipation ---*/ @@ -1029,92 +287,101 @@ void CNSSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, C /*--- Compute the limiter in case we need it in the turbulence model or to limit the viscous terms (check this logic with JST and 2nd order turbulence model) ---*/ - if ((iMesh == MESH_0) && (limiter_flow || limiter_turb || limiter_adjflow) - && !Output && !van_albada) { SetPrimitive_Limiter(geometry, config); } + if ((iMesh == MESH_0) && (limiter_flow || limiter_turb || limiter_adjflow) && !Output && !van_albada) { + SetPrimitive_Limiter(geometry, config); + } /*--- Evaluate the vorticity and strain rate magnitude ---*/ - solver_container[FLOW_SOL]->GetNodes()->SetVorticity_StrainMag(); + SU2_OMP_MASTER + { + StrainMag_Max = 0.0; + Omega_Max = 0.0; + } + SU2_OMP_BARRIER + + nodes->SetVorticity_StrainMag(); - StrainMag_Max = 0.0; Omega_Max = 0.0; - for (iPoint = 0; iPoint < nPoint; iPoint++) { + su2double strainMax = 0.0, omegaMax = 0.0; - StrainMag = solver_container[FLOW_SOL]->GetNodes()->GetStrainMag(iPoint); - Vorticity = solver_container[FLOW_SOL]->GetNodes()->GetVorticity(iPoint); - Omega = sqrt(Vorticity[0]*Vorticity[0]+ Vorticity[1]*Vorticity[1]+ Vorticity[2]*Vorticity[2]); + SU2_OMP(for schedule(static,omp_chunk_size) nowait) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++) { - StrainMag_Max = max(StrainMag_Max, StrainMag); - Omega_Max = max(Omega_Max, Omega); + su2double StrainMag = nodes->GetStrainMag(iPoint); + const su2double* Vorticity = nodes->GetVorticity(iPoint); + su2double Omega = sqrt(Vorticity[0]*Vorticity[0]+ Vorticity[1]*Vorticity[1]+ Vorticity[2]*Vorticity[2]); + strainMax = max(strainMax, StrainMag); + omegaMax = max(omegaMax, Omega); + + } + SU2_OMP_CRITICAL + { + StrainMag_Max = max(StrainMag_Max, strainMax); + Omega_Max = max(Omega_Max, omegaMax); + } + + if ((iMesh == MESH_0) && (config->GetComm_Level() == COMM_FULL)) { + SU2_OMP_BARRIER + SU2_OMP_MASTER + { + su2double MyOmega_Max = Omega_Max; + su2double MyStrainMag_Max = StrainMag_Max; + + SU2_MPI::Allreduce(&MyStrainMag_Max, &StrainMag_Max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + SU2_MPI::Allreduce(&MyOmega_Max, &Omega_Max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + } + SU2_OMP_BARRIER } /*--- Compute the TauWall from the wall functions ---*/ - if (wall_functions) + if (wall_functions) { + SU2_OMP_MASTER SetTauWall_WF(geometry, solver_container, config); + SU2_OMP_BARRIER + } /*--- Initialize the Jacobian matrices ---*/ if (implicit && !config->GetDiscrete_Adjoint()) Jacobian.SetValZero(); - /*--- Error message ---*/ - - if (config->GetComm_Level() == COMM_FULL) { - -#ifdef HAVE_MPI - unsigned long MyErrorCounter = ErrorCounter; ErrorCounter = 0; - su2double MyOmega_Max = Omega_Max; Omega_Max = 0.0; - su2double MyStrainMag_Max = StrainMag_Max; StrainMag_Max = 0.0; - - SU2_MPI::Allreduce(&MyErrorCounter, &ErrorCounter, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyStrainMag_Max, &StrainMag_Max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); - SU2_MPI::Allreduce(&MyOmega_Max, &Omega_Max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); -#endif - - if (iMesh == MESH_0) { - config->SetNonphysical_Points(ErrorCounter); - solver_container[FLOW_SOL]->SetStrainMag_Max(StrainMag_Max); - solver_container[FLOW_SOL]->SetOmega_Max(Omega_Max); - } - - } - } unsigned long CNSSolver::SetPrimitive_Variables(CSolver **solver_container, CConfig *config, bool Output) { - unsigned long iPoint, nonPhysicalPoints = 0; - su2double eddy_visc = 0.0, turb_ke = 0.0, DES_LengthScale = 0.0; - unsigned short turb_model = config->GetKind_Turb_Model(); - bool physical = true; + /*--- Number of non-physical points, local to the thread, needs + * further reduction if function is called in parallel ---*/ + unsigned long nonPhysicalPoints = 0; - bool tkeNeeded = ((turb_model == SST) || (turb_model == SST_SUST)) ; + const unsigned short turb_model = config->GetKind_Turb_Model(); + const bool tkeNeeded = (turb_model == SST) || (turb_model == SST_SUST); - for (iPoint = 0; iPoint < nPoint; iPoint ++) { + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - /*--- Retrieve the value of the kinetic energy (if need it) ---*/ + /*--- Retrieve the value of the kinetic energy (if needed). ---*/ + + su2double eddy_visc = 0.0, turb_ke = 0.0; if (turb_model != NONE) { eddy_visc = solver_container[TURB_SOL]->GetNodes()->GetmuT(iPoint); if (tkeNeeded) turb_ke = solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0); - if (config->GetKind_HybridRANSLES() != NO_HYBRIDRANSLES){ - DES_LengthScale = solver_container[TURB_SOL]->GetNodes()->GetDES_LengthScale(iPoint); + if (config->GetKind_HybridRANSLES() != NO_HYBRIDRANSLES) { + su2double DES_LengthScale = solver_container[TURB_SOL]->GetNodes()->GetDES_LengthScale(iPoint); + nodes->SetDES_LengthScale(iPoint, DES_LengthScale); } } /*--- Compressible flow, primitive variables nDim+5, (T, vx, vy, vz, P, rho, h, c, lamMu, eddyMu, ThCond, Cp) ---*/ - physical = static_cast(nodes)->SetPrimVar(iPoint,eddy_visc, turb_ke, FluidModel); - nodes->SetSecondaryVar(iPoint,FluidModel); - - /* Check for non-realizable states for reporting. */ - - if (!physical) nonPhysicalPoints++; + bool physical = static_cast(nodes)->SetPrimVar(iPoint, eddy_visc, turb_ke, GetFluidModel()); + nodes->SetSecondaryVar(iPoint, GetFluidModel()); - /*--- Set the DES length scale ---*/ + /*--- Check for non-realizable states for reporting. ---*/ - nodes->SetDES_LengthScale(iPoint,DES_LengthScale); + nonPhysicalPoints += !physical; /*--- Initialize the convective, source and viscous residual vector ---*/ @@ -1125,281 +392,65 @@ unsigned long CNSSolver::SetPrimitive_Variables(CSolver **solver_container, CCon return nonPhysicalPoints; } -void CNSSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned long Iteration) { +void CNSSolver::Viscous_Residual(unsigned long iEdge, CGeometry *geometry, CSolver **solver_container, + CNumerics *numerics, CConfig *config) { - su2double *Normal, Area, Vol, Mean_SoundSpeed = 0.0, Mean_ProjVel = 0.0, Lambda, Local_Delta_Time, Local_Delta_Time_Visc, - Global_Delta_Time = 1E6, Mean_LaminarVisc = 0.0, Mean_EddyVisc = 0.0, Mean_Density = 0.0, Lambda_1, Lambda_2, K_v = 0.25, Global_Delta_UnstTimeND; - unsigned long iEdge, iVertex, iPoint = 0, jPoint = 0; - unsigned short iDim, iMarker; - su2double ProjVel, ProjVel_i, ProjVel_j; + const bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); + const bool tkeNeeded = (config->GetKind_Turb_Model() == SST) || + (config->GetKind_Turb_Model() == SST_SUST); - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || - (config->GetTime_Marching() == DT_STEPPING_2ND)); - - Min_Delta_Time = 1.E30; Max_Delta_Time = 0.0; + CVariable* turbNodes = nullptr; + if (tkeNeeded) turbNodes = solver_container[TURB_SOL]->GetNodes(); - /*--- Set maximum inviscid eigenvalue to zero, and compute sound speed and viscosity ---*/ - - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - nodes->SetMax_Lambda_Inv(iPoint,0.0); - nodes->SetMax_Lambda_Visc(iPoint,0.0); - } + /*--- Points, coordinates and normal vector in edge ---*/ - /*--- Loop interior edges ---*/ + auto iPoint = geometry->edge[iEdge]->GetNode(0); + auto jPoint = geometry->edge[iEdge]->GetNode(1); - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { + numerics->SetCoord(geometry->node[iPoint]->GetCoord(), + geometry->node[jPoint]->GetCoord()); - /*--- Point identification, Normal vector and area ---*/ + numerics->SetNormal(geometry->edge[iEdge]->GetNormal()); - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); + /*--- Primitive and secondary variables. ---*/ - Normal = geometry->edge[iEdge]->GetNormal(); - Area = 0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); + numerics->SetPrimitive(nodes->GetPrimitive(iPoint), + nodes->GetPrimitive(jPoint)); - /*--- Mean Values ---*/ + numerics->SetSecondary(nodes->GetSecondary(iPoint), + nodes->GetSecondary(jPoint)); - Mean_ProjVel = 0.5 * (nodes->GetProjVel(iPoint,Normal) + nodes->GetProjVel(jPoint,Normal)); - Mean_SoundSpeed = 0.5 * (nodes->GetSoundSpeed(iPoint) + nodes->GetSoundSpeed(jPoint)) * Area; + /*--- Gradients. ---*/ - /*--- Adjustment for grid movement ---*/ + numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), + nodes->GetGradient_Primitive(jPoint)); - if (dynamic_grid) { - su2double *GridVel_i = geometry->node[iPoint]->GetGridVel(); - su2double *GridVel_j = geometry->node[jPoint]->GetGridVel(); - ProjVel_i = 0.0; ProjVel_j =0.0; - for (iDim = 0; iDim < nDim; iDim++) { - ProjVel_i += GridVel_i[iDim]*Normal[iDim]; - ProjVel_j += GridVel_j[iDim]*Normal[iDim]; - } - Mean_ProjVel -= 0.5 * (ProjVel_i + ProjVel_j) ; - } + /*--- Turbulent kinetic energy. ---*/ - /*--- Inviscid contribution ---*/ + if (tkeNeeded) + numerics->SetTurbKineticEnergy(turbNodes->GetSolution(iPoint,0), + turbNodes->GetSolution(jPoint,0)); - Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed ; - if (geometry->node[iPoint]->GetDomain()) nodes->AddMax_Lambda_Inv(iPoint,Lambda); - if (geometry->node[jPoint]->GetDomain()) nodes->AddMax_Lambda_Inv(jPoint,Lambda); + /*--- Wall shear stress values (wall functions) ---*/ - /*--- Viscous contribution ---*/ + numerics->SetTauWall(nodes->GetTauWall(iPoint), + nodes->GetTauWall(iPoint)); - Mean_LaminarVisc = 0.5*(nodes->GetLaminarViscosity(iPoint) + nodes->GetLaminarViscosity(jPoint)); - Mean_EddyVisc = 0.5*(nodes->GetEddyViscosity(iPoint) + nodes->GetEddyViscosity(jPoint)); - Mean_Density = 0.5*(nodes->GetDensity(iPoint) + nodes->GetDensity(jPoint)); + /*--- Compute and update residual ---*/ - Lambda_1 = (4.0/3.0)*(Mean_LaminarVisc + Mean_EddyVisc); - //TODO (REAL_GAS) removing Gamma it cannot work with FLUIDPROP - Lambda_2 = (1.0 + (Prandtl_Lam/Prandtl_Turb)*(Mean_EddyVisc/Mean_LaminarVisc))*(Gamma*Mean_LaminarVisc/Prandtl_Lam); - Lambda = (Lambda_1 + Lambda_2)*Area*Area/Mean_Density; - - if (geometry->node[iPoint]->GetDomain()) nodes->AddMax_Lambda_Visc(iPoint, Lambda); - if (geometry->node[jPoint]->GetDomain()) nodes->AddMax_Lambda_Visc(jPoint, Lambda); + auto residual = numerics->ComputeResidual(config); + if ((MGLevel != MESH_0) && (omp_get_num_threads() > 1)) { + EdgeFluxes.SubtractBlock(iEdge, residual); + if (implicit) + Jacobian.UpdateBlocksSub(iEdge, residual.jacobian_i, residual.jacobian_j); } + else { + LinSysRes.SubtractBlock(iPoint, residual); + LinSysRes.AddBlock(jPoint, residual); - /*--- Loop boundary edges ---*/ - - for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) { - if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && - (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) { - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - - /*--- Point identification, Normal vector and area ---*/ - - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - Area = 0.0; for (iDim = 0; iDim < nDim; iDim++) Area += Normal[iDim]*Normal[iDim]; Area = sqrt(Area); - - /*--- Mean Values ---*/ - - Mean_ProjVel = nodes->GetProjVel(iPoint,Normal); - Mean_SoundSpeed = nodes->GetSoundSpeed(iPoint) * Area; - - /*--- Adjustment for grid movement ---*/ - - if (dynamic_grid) { - su2double *GridVel = geometry->node[iPoint]->GetGridVel(); - ProjVel = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - ProjVel += GridVel[iDim]*Normal[iDim]; - Mean_ProjVel -= ProjVel; - } - - /*--- Inviscid contribution ---*/ - - Lambda = fabs(Mean_ProjVel) + Mean_SoundSpeed; - if (geometry->node[iPoint]->GetDomain()) { - nodes->AddMax_Lambda_Inv(iPoint,Lambda); - } - - /*--- Viscous contribution ---*/ - - Mean_LaminarVisc = nodes->GetLaminarViscosity(iPoint); - Mean_EddyVisc = nodes->GetEddyViscosity(iPoint); - Mean_Density = nodes->GetDensity(iPoint); - - Lambda_1 = (4.0/3.0)*(Mean_LaminarVisc + Mean_EddyVisc); - Lambda_2 = (1.0 + (Prandtl_Lam/Prandtl_Turb)*(Mean_EddyVisc/Mean_LaminarVisc))*(Gamma*Mean_LaminarVisc/Prandtl_Lam); - Lambda = (Lambda_1 + Lambda_2)*Area*Area/Mean_Density; - - if (geometry->node[iPoint]->GetDomain()) nodes->AddMax_Lambda_Visc(iPoint, Lambda); - - } - } - } - - /*--- Each element uses their own speed, steady state simulation ---*/ - - - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - - Vol = geometry->node[iPoint]->GetVolume(); - - if (Vol != 0.0) { - Local_Delta_Time = nodes->GetLocalCFL(iPoint)*Vol / nodes->GetMax_Lambda_Inv(iPoint); - Local_Delta_Time_Visc = nodes->GetLocalCFL(iPoint)*K_v*Vol*Vol/ nodes->GetMax_Lambda_Visc(iPoint); - Local_Delta_Time = min(Local_Delta_Time, Local_Delta_Time_Visc); - Global_Delta_Time = min(Global_Delta_Time, Local_Delta_Time); - Min_Delta_Time = min(Min_Delta_Time, Local_Delta_Time); - Max_Delta_Time = max(Max_Delta_Time, Local_Delta_Time); - if (Local_Delta_Time > config->GetMax_DeltaTime()) - Local_Delta_Time = config->GetMax_DeltaTime(); - nodes->SetDelta_Time(iPoint,Local_Delta_Time); - } - else { - nodes->SetDelta_Time(iPoint,0.0); - } - - } - - - /*--- Compute the max and the min dt (in parallel) ---*/ - if (config->GetComm_Level() == COMM_FULL) { -#ifdef HAVE_MPI - su2double rbuf_time, sbuf_time; - sbuf_time = Min_Delta_Time; - SU2_MPI::Reduce(&sbuf_time, &rbuf_time, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, MPI_COMM_WORLD); - SU2_MPI::Bcast(&rbuf_time, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); - Min_Delta_Time = rbuf_time; - - sbuf_time = Max_Delta_Time; - SU2_MPI::Reduce(&sbuf_time, &rbuf_time, 1, MPI_DOUBLE, MPI_MAX, MASTER_NODE, MPI_COMM_WORLD); - SU2_MPI::Bcast(&rbuf_time, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); - Max_Delta_Time = rbuf_time; -#endif - } - - /*--- For exact time solution use the minimum delta time of the whole mesh ---*/ - if (config->GetTime_Marching() == TIME_STEPPING) { -#ifdef HAVE_MPI - su2double rbuf_time, sbuf_time; - sbuf_time = Global_Delta_Time; - SU2_MPI::Reduce(&sbuf_time, &rbuf_time, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, MPI_COMM_WORLD); - SU2_MPI::Bcast(&rbuf_time, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); - Global_Delta_Time = rbuf_time; -#endif - /*--- If the unsteady CFL is set to zero, it uses the defined - unsteady time step, otherwise it computes the time step based - on the unsteady CFL ---*/ - - if (config->GetUnst_CFL() == 0.0) { - Global_Delta_Time = config->GetDelta_UnstTime(); - } - config->SetDelta_UnstTimeND(Global_Delta_Time); - for (iPoint = 0; iPoint < nPointDomain; iPoint++){ - - /*--- Sets the regular CFL equal to the unsteady CFL ---*/ - - nodes->SetLocalCFL(iPoint, config->GetUnst_CFL()); - nodes->SetDelta_Time(iPoint, Global_Delta_Time); - Min_Delta_Time = Global_Delta_Time; - Max_Delta_Time = Global_Delta_Time; - - } - } - - /*--- Recompute the unsteady time step for the dual time strategy - if the unsteady CFL is diferent from 0 ---*/ - if ((dual_time) && (Iteration == 0) && (config->GetUnst_CFL() != 0.0) && (iMesh == MESH_0)) { - - Global_Delta_UnstTimeND = 1e30; - for (iPoint = 0; iPoint < nPointDomain; iPoint++){ - Global_Delta_UnstTimeND = min(Global_Delta_UnstTimeND,config->GetUnst_CFL()*Global_Delta_Time/nodes->GetLocalCFL(iPoint)); - } - -#ifdef HAVE_MPI - su2double rbuf_time, sbuf_time; - sbuf_time = Global_Delta_UnstTimeND; - SU2_MPI::Reduce(&sbuf_time, &rbuf_time, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, MPI_COMM_WORLD); - SU2_MPI::Bcast(&rbuf_time, 1, MPI_DOUBLE, MASTER_NODE, MPI_COMM_WORLD); - Global_Delta_UnstTimeND = rbuf_time; -#endif - config->SetDelta_UnstTimeND(Global_Delta_UnstTimeND); - } - - /*--- The pseudo local time (explicit integration) cannot be greater than the physical time ---*/ - if (dual_time) - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - if (!implicit) { - Local_Delta_Time = min((2.0/3.0)*config->GetDelta_UnstTimeND(), nodes->GetDelta_Time(iPoint)); - nodes->SetDelta_Time(iPoint,Local_Delta_Time); - } - } - -} - -void CNSSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, - CConfig *config, unsigned short iMesh, unsigned short iRKStep) { - - unsigned long iPoint, jPoint, iEdge; - - bool implicit = (config->GetKind_TimeIntScheme_Flow() == EULER_IMPLICIT); - - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { - - /*--- Points, coordinates and normal vector in edge ---*/ - - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); - numerics->SetCoord(geometry->node[iPoint]->GetCoord(), geometry->node[jPoint]->GetCoord()); - numerics->SetNormal(geometry->edge[iEdge]->GetNormal()); - - /*--- Primitive and secondary variables ---*/ - - numerics->SetPrimitive(nodes->GetPrimitive(iPoint), nodes->GetPrimitive(jPoint)); - numerics->SetSecondary(nodes->GetSecondary(iPoint), nodes->GetSecondary(jPoint)); - - /*--- Gradient and limiters ---*/ - - numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint), nodes->GetGradient_Primitive(jPoint)); - - /*--- Turbulent kinetic energy ---*/ - - if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) - numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint,0), - solver_container[TURB_SOL]->GetNodes()->GetSolution(jPoint,0)); - - /*--- Wall shear stress values (wall functions) ---*/ - - numerics->SetTauWall(nodes->GetTauWall(iPoint), nodes->GetTauWall(iPoint)); - - /*--- Compute and update residual ---*/ - - numerics->ComputeResidual(Res_Visc, Jacobian_i, Jacobian_j, config); - - LinSysRes.SubtractBlock(iPoint, Res_Visc); - LinSysRes.AddBlock(jPoint, Res_Visc); - - /*--- Implicit part ---*/ - - if (implicit) { - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); - Jacobian.SubtractBlock(iPoint, jPoint, Jacobian_j); - Jacobian.AddBlock(jPoint, iPoint, Jacobian_i); - Jacobian.AddBlock(jPoint, jPoint, Jacobian_j); - } - + if (implicit) + Jacobian.UpdateBlocksSub(iEdge, iPoint, jPoint, residual.jacobian_i, residual.jacobian_j); } } @@ -1408,42 +459,37 @@ 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, *Normal, MomentDist[3] = {0.0, 0.0, 0.0}, WallDist[3] = {0.0, 0.0, 0.0}, - *Coord, *Coord_Normal, Area, WallShearStress, TauNormal, factor, RefTemp, RefVel2, - RefDensity, GradTemperature, Density = 0.0, WallDistMod, FrictionVel, + 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}}, Force[3] = {0.0, 0.0, 0.0}, Cp, thermal_conductivity, MaxNorm = 8.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 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; -#endif + 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(); - su2double *Origin = NULL; + 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(); + 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; + RefTemp = Temperature_Inf; RefDensity = Density_Inf; if (dynamic_grid) { Mach2Vel = sqrt(Gamma*Gas_Constant*RefTemp); @@ -1459,20 +505,13 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { /*--- Variables initialization ---*/ - AllBound_CD_Visc = 0.0; AllBound_CL_Visc = 0.0; AllBound_CSF_Visc = 0.0; - AllBound_CFx_Visc = 0.0; AllBound_CFy_Visc = 0.0; AllBound_CFz_Visc = 0.0; - AllBound_CMx_Visc = 0.0; AllBound_CMy_Visc = 0.0; AllBound_CMz_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; + 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_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; + Surface_HF_Visc[iMarker_Monitoring] = 0.0; Surface_MaxHF_Visc[iMarker_Monitoring] = 0.0; } /*--- Loop over the Navier-Stokes markers ---*/ @@ -1497,18 +536,12 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { /*--- Forces initialization at each Marker ---*/ - CD_Visc[iMarker] = 0.0; CL_Visc[iMarker] = 0.0; CSF_Visc[iMarker] = 0.0; - CFx_Visc[iMarker] = 0.0; CFy_Visc[iMarker] = 0.0; CFz_Visc[iMarker] = 0.0; - CMx_Visc[iMarker] = 0.0; CMy_Visc[iMarker] = 0.0; CMz_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; + ViscCoeff.setZero(iMarker); + + HF_Visc[iMarker] = 0.0; MaxHF_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; + 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 ---*/ @@ -1551,30 +584,29 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { /*--- If necessary evaluate the QCR contribution to Tau ---*/ - if (QCR){ - su2double den_aux, c_cr1=0.3, O_ik, O_jk; - unsigned short kDim; + if (QCR) { + su2double den_aux, c_cr1=0.3, O_ik, O_jk; + unsigned short kDim; - /*--- Denominator Antisymmetric normalized rotation tensor ---*/ + /*--- 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)); + 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 ---*/ + /*--- 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]); - } - } + 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 ---*/ @@ -1628,6 +660,7 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { /*--- 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]; @@ -1660,54 +693,54 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { 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); - CFx_Visc[iMarker] = ForceViscous[0]; - CFy_Visc[iMarker] = ForceViscous[1]; - CMz_Visc[iMarker] = MomentViscous[2]; - 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); + 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) { - 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); - CFx_Visc[iMarker] = ForceViscous[0]; - CFy_Visc[iMarker] = ForceViscous[1]; - CFz_Visc[iMarker] = ForceViscous[2]; - CMx_Visc[iMarker] = MomentViscous[0]; - CMy_Visc[iMarker] = MomentViscous[1]; - CMz_Visc[iMarker] = MomentViscous[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); + 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); } - AllBound_CD_Visc += CD_Visc[iMarker]; - AllBound_CL_Visc += CL_Visc[iMarker]; - AllBound_CSF_Visc += CSF_Visc[iMarker]; - AllBound_CFx_Visc += CFx_Visc[iMarker]; - AllBound_CFy_Visc += CFy_Visc[iMarker]; - AllBound_CFz_Visc += CFz_Visc[iMarker]; - AllBound_CMx_Visc += CMx_Visc[iMarker]; - AllBound_CMy_Visc += CMy_Visc[iMarker]; - AllBound_CMz_Visc += CMz_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); + 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 ---*/ @@ -1715,18 +748,18 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { 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); + 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); } } @@ -1737,8 +770,8 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { /*--- Update some global coeffients ---*/ - AllBound_CEff_Visc = AllBound_CL_Visc / (AllBound_CD_Visc + EPS); - AllBound_CMerit_Visc = AllBound_CT_Visc / (AllBound_CQ_Visc + EPS); + AllBoundViscCoeff.CEff = AllBoundViscCoeff.CL / (AllBoundViscCoeff.CD + EPS); + AllBoundViscCoeff.CMerit = AllBoundViscCoeff.CT / (AllBoundViscCoeff.CQ + EPS); AllBound_MaxHF_Visc = pow(AllBound_MaxHF_Visc, 1.0/MaxNorm); @@ -1746,148 +779,114 @@ void CNSSolver::Friction_Forces(CGeometry *geometry, CConfig *config) { /*--- 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_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_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_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 ---*/ + 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); - 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()]; + AllBoundViscCoeff.CMx = Allreduce(AllBoundViscCoeff.CMx); + AllBoundViscCoeff.CMy = Allreduce(AllBoundViscCoeff.CMy); + AllBoundViscCoeff.CMz = Allreduce(AllBoundViscCoeff.CMz); - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { + 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); - 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; } + /*--- Add the forces on the surfaces using all the nodes ---*/ + 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; + 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++) { - 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]; + 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]; } } @@ -1986,8 +985,6 @@ void CNSSolver::Buffet_Monitoring(CGeometry *geometry, CConfig *config) { /*--- Add buffet metric information using all the nodes ---*/ su2double MyTotal_Buffet_Metric = Total_Buffet_Metric; - Total_Buffet_Metric = 0.0; - SU2_MPI::Allreduce(&MyTotal_Buffet_Metric, &Total_Buffet_Metric, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); /*--- Add the buffet metric on the surfaces using all the nodes ---*/ @@ -1995,10 +992,7 @@ void CNSSolver::Buffet_Monitoring(CGeometry *geometry, CConfig *config) { su2double *MySurface_Buffet_Metric = new su2double[config->GetnMarker_Monitoring()]; for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { - MySurface_Buffet_Metric[iMarker_Monitoring] = Surface_Buffet_Metric[iMarker_Monitoring]; - Surface_Buffet_Metric[iMarker_Monitoring] = 0.0; - } SU2_MPI::Allreduce(MySurface_Buffet_Metric, Surface_Buffet_Metric, config->GetnMarker_Monitoring(), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); @@ -2011,33 +1005,34 @@ void CNSSolver::Buffet_Monitoring(CGeometry *geometry, CConfig *config) { void CNSSolver::Evaluate_ObjFunc(CConfig *config) { - unsigned short iMarker_Monitoring, Kind_ObjFunc; - su2double Weight_ObjFunc; + unsigned short iMarker_Monitoring, Kind_ObjFunc; + su2double Weight_ObjFunc; - /*--- Evaluate objective functions common to Euler and NS solvers ---*/ + /*--- Evaluate objective functions common to Euler and NS solvers ---*/ - CEulerSolver::Evaluate_ObjFunc(config); + CEulerSolver::Evaluate_ObjFunc(config); - /*--- Evaluate objective functions specific to NS solver ---*/ + /*--- Evaluate objective functions specific to NS solver ---*/ - for (iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring(); iMarker_Monitoring++) { + 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); + Weight_ObjFunc = config->GetWeight_ObjFunc(iMarker_Monitoring); + Kind_ObjFunc = config->GetKind_ObjFunc(iMarker_Monitoring); - switch(Kind_ObjFunc) { - case BUFFET_SENSOR: - Total_ComboObj +=Weight_ObjFunc*Surface_Buffet_Metric[iMarker_Monitoring]; - break; - default: - break; - } + switch(Kind_ObjFunc) { + case BUFFET_SENSOR: + Total_ComboObj +=Weight_ObjFunc*Surface_Buffet_Metric[iMarker_Monitoring]; + break; + default: + break; } + } } -void CNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iDim, jDim, iVar, jVar; unsigned long iVertex, iPoint, Point_Normal, total_index; @@ -2157,7 +1152,8 @@ void CNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container for (iDim = 0; iDim < nDim; iDim++) { for (jDim = 0; jDim < nDim; jDim++) { - tau[iDim][jDim] = total_viscosity*( Grad_Vel[jDim][iDim]+Grad_Vel[iDim][jDim] ) - TWO3*total_viscosity*div_vel*delta[iDim][jDim]; + tau[iDim][jDim] = total_viscosity*( Grad_Vel[jDim][iDim]+Grad_Vel[iDim][jDim] ) - + TWO3*total_viscosity*div_vel*delta[iDim][jDim]; } } @@ -2194,7 +1190,7 @@ void CNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container /*--- Add the block to the Global Jacobian structure ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); /*--- Now the Jacobian contribution related to the shear stress ---*/ @@ -2255,7 +1251,7 @@ void CNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container /*--- Subtract the block from the Global Jacobian structure ---*/ - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } } @@ -2282,7 +1278,8 @@ void CNSSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container } } -void CNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iVar, jVar, iDim, jDim; unsigned long iVertex, iPoint, Point_Normal, total_index; @@ -2432,7 +1429,7 @@ void CNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_contain /*--- Subtract the block from the Global Jacobian structure ---*/ - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } @@ -2471,7 +1468,8 @@ void CNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_contain for (iDim = 0; iDim < nDim; iDim++) for (jDim = 0; jDim < nDim; jDim++) { - tau[iDim][jDim] = total_viscosity*( Grad_Vel[jDim][iDim] + Grad_Vel[iDim][jDim] ) - TWO3*total_viscosity*div_vel*delta[iDim][jDim]; + tau[iDim][jDim] = total_viscosity*( Grad_Vel[jDim][iDim] + Grad_Vel[iDim][jDim] ) - + TWO3*total_viscosity*div_vel*delta[iDim][jDim]; } /*--- Dot product of the stress tensor with the grid velocity ---*/ @@ -2508,7 +1506,7 @@ void CNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_contain /*--- Add the block to the Global Jacobian structure ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); /*--- Now the Jacobian contribution related to the shear stress ---*/ @@ -2552,7 +1550,7 @@ void CNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_contain /*--- Subtract the block from the Global Jacobian structure ---*/ - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } } @@ -2581,26 +1579,25 @@ void CNSSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_contain void CNSSolver::SetRoe_Dissipation(CGeometry *geometry, CConfig *config){ - unsigned long iPoint; - su2double wall_distance; + const unsigned short kind_roe_dissipation = config->GetKind_RoeLowDiss(); - unsigned short kind_roe_dissipation = config->GetKind_RoeLowDiss(); - - for (iPoint = 0; iPoint < nPoint; iPoint++){ + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++) { if (kind_roe_dissipation == FD || kind_roe_dissipation == FD_DUCROS){ - wall_distance = geometry->node[iPoint]->GetWall_Distance(); + su2double wall_distance = geometry->node[iPoint]->GetWall_Distance(); - nodes->SetRoe_Dissipation_FD(iPoint,wall_distance); + nodes->SetRoe_Dissipation_FD(iPoint, wall_distance); } else if (kind_roe_dissipation == NTS || kind_roe_dissipation == NTS_DUCROS) { const su2double delta = geometry->node[iPoint]->GetMaxLength(); - assert(delta > 0); // Delta must be initialized and non-negative - nodes->SetRoe_Dissipation_NTS(iPoint,delta, config->GetConst_DES()); + assert(delta > 0 && "Delta must be initialized and non-negative"); + nodes->SetRoe_Dissipation_NTS(iPoint, delta, config->GetConst_DES()); } } + } void CNSSolver::BC_ConjugateHeat_Interface(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, @@ -2735,7 +1732,7 @@ void CNSSolver::BC_ConjugateHeat_Interface(CGeometry *geometry, CSolver **solver dTdn = -(There - Twall)/dist_ij; } else { - + Twall = dTdn = 0.0; SU2_MPI::Error("Unknown CHT coupling method.", CURRENT_FUNCTION); } @@ -2774,7 +1771,7 @@ void CNSSolver::BC_ConjugateHeat_Interface(CGeometry *geometry, CSolver **solver /*--- Subtract the block from the Global Jacobian structure ---*/ - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } @@ -2851,7 +1848,7 @@ void CNSSolver::BC_ConjugateHeat_Interface(CGeometry *geometry, CSolver **solver /*--- Add the block to the Global Jacobian structure ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); /*--- Now the Jacobian contribution related to the shear stress ---*/ @@ -2895,7 +1892,7 @@ void CNSSolver::BC_ConjugateHeat_Interface(CGeometry *geometry, CSolver **solver /*--- Subtract the block from the Global Jacobian structure ---*/ - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } } diff --git a/SU2_CFD/src/solvers/CSolver.cpp b/SU2_CFD/src/solvers/CSolver.cpp index 5f1ef6d171fe..45afb94148d3 100644 --- a/SU2_CFD/src/solvers/CSolver.cpp +++ b/SU2_CFD/src/solvers/CSolver.cpp @@ -512,27 +512,27 @@ void CSolver::InitiatePeriodicComms(CGeometry *geometry, volume to the other side of the periodic face. ---*/ for (iVar = 0; iVar < nVar; iVar++) { - bufDSend[buf_offset+iVar] = LinSysRes.GetBlock(iPoint, iVar); + bufDSend[buf_offset+iVar] = LinSysRes(iPoint, iVar); } /*--- Rotate the momentum components of the residual array. ---*/ if (rotate_periodic) { if (nDim == 2) { - bufDSend[buf_offset+1] = (rotMatrix[0][0]*LinSysRes.GetBlock(iPoint, 1) + - rotMatrix[0][1]*LinSysRes.GetBlock(iPoint, 2)); - bufDSend[buf_offset+2] = (rotMatrix[1][0]*LinSysRes.GetBlock(iPoint, 1) + - rotMatrix[1][1]*LinSysRes.GetBlock(iPoint, 2)); + bufDSend[buf_offset+1] = (rotMatrix[0][0]*LinSysRes(iPoint, 1) + + rotMatrix[0][1]*LinSysRes(iPoint, 2)); + bufDSend[buf_offset+2] = (rotMatrix[1][0]*LinSysRes(iPoint, 1) + + rotMatrix[1][1]*LinSysRes(iPoint, 2)); } else { - bufDSend[buf_offset+1] = (rotMatrix[0][0]*LinSysRes.GetBlock(iPoint, 1) + - rotMatrix[0][1]*LinSysRes.GetBlock(iPoint, 2) + - rotMatrix[0][2]*LinSysRes.GetBlock(iPoint, 3)); - bufDSend[buf_offset+2] = (rotMatrix[1][0]*LinSysRes.GetBlock(iPoint, 1) + - rotMatrix[1][1]*LinSysRes.GetBlock(iPoint, 2) + - rotMatrix[1][2]*LinSysRes.GetBlock(iPoint, 3)); - bufDSend[buf_offset+3] = (rotMatrix[2][0]*LinSysRes.GetBlock(iPoint, 1) + - rotMatrix[2][1]*LinSysRes.GetBlock(iPoint, 2) + - rotMatrix[2][2]*LinSysRes.GetBlock(iPoint, 3)); + bufDSend[buf_offset+1] = (rotMatrix[0][0]*LinSysRes(iPoint, 1) + + rotMatrix[0][1]*LinSysRes(iPoint, 2) + + rotMatrix[0][2]*LinSysRes(iPoint, 3)); + bufDSend[buf_offset+2] = (rotMatrix[1][0]*LinSysRes(iPoint, 1) + + rotMatrix[1][1]*LinSysRes(iPoint, 2) + + rotMatrix[1][2]*LinSysRes(iPoint, 3)); + bufDSend[buf_offset+3] = (rotMatrix[2][0]*LinSysRes(iPoint, 1) + + rotMatrix[2][1]*LinSysRes(iPoint, 2) + + rotMatrix[2][2]*LinSysRes(iPoint, 3)); } } buf_offset += nVar; @@ -1665,7 +1665,7 @@ void CSolver::CompletePeriodicComms(CGeometry *geometry, if (implicit_periodic) { - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); if (iPeriodic == val_periodic_index + nPeriodic/2) { for (iVar = 0; iVar < nVar; iVar++) { @@ -2318,7 +2318,7 @@ void CSolver::CompleteComms(CGeometry *geometry, } -void CSolver::ResetCFLAdapt(){ +void CSolver::ResetCFLAdapt() { NonLinRes_Series.clear(); NonLinRes_Value = 0; NonLinRes_Func = 0; @@ -2332,6 +2332,8 @@ void CSolver::AdaptCFLNumber(CGeometry **geometry, CSolver ***solver_container, CConfig *config) { + /// TODO: Add OpenMP stuff to this method. + /* Adapt the CFL number on all multigrid levels using an exponential progression with under-relaxation approach. */ @@ -2496,26 +2498,10 @@ void CSolver::AdaptCFLNumber(CGeometry **geometry, /* Reduce the min/max/avg local CFL numbers. */ - su2double rbuf_min, sbuf_min; - sbuf_min = myCFLMin; - SU2_MPI::Allreduce(&sbuf_min, &rbuf_min, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); - Min_CFL_Local = rbuf_min; - - su2double rbuf_max, sbuf_max; - sbuf_max = myCFLMax; - SU2_MPI::Allreduce(&sbuf_max, &rbuf_max, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); - Max_CFL_Local = rbuf_max; - - su2double rbuf_sum, sbuf_sum; - sbuf_sum = myCFLSum; - SU2_MPI::Allreduce(&sbuf_sum, &rbuf_sum, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); - Avg_CFL_Local = rbuf_sum; - - unsigned long Global_nPointDomain; - unsigned long Local_nPointDomain = geometry[iMesh]->GetnPointDomain(); - SU2_MPI::Allreduce(&Local_nPointDomain, &Global_nPointDomain, 1, - MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); - Avg_CFL_Local /= (su2double)Global_nPointDomain; + SU2_MPI::Allreduce(&myCFLMin, &Min_CFL_Local, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); + SU2_MPI::Allreduce(&myCFLMax, &Max_CFL_Local, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); + SU2_MPI::Allreduce(&myCFLSum, &Avg_CFL_Local, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); + Avg_CFL_Local /= su2double(geometry[iMesh]->GetGlobal_nPointDomain()); } @@ -2549,8 +2535,8 @@ void CSolver::SetResidual_RMS(CGeometry *geometry, CConfig *config) { /*--- Set the L2 Norm residual in all the processors ---*/ - sbuf_residual = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) sbuf_residual[iVar] = 0.0; - rbuf_residual = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) rbuf_residual[iVar] = 0.0; + sbuf_residual = new su2double[nVar]; + rbuf_residual = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) sbuf_residual[iVar] = GetRes_RMS(iVar); @@ -2560,16 +2546,16 @@ void CSolver::SetResidual_RMS(CGeometry *geometry, CConfig *config) { SU2_MPI::Allreduce(sbuf_residual, rbuf_residual, nVar, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); SU2_MPI::Allreduce(&Local_nPointDomain, &Global_nPointDomain, 1, MPI_UNSIGNED_LONG, MPI_SUM, MPI_COMM_WORLD); - } else { - + } + else { /*--- Reduced MPI comms have been requested. Use a local residual only. ---*/ - for (iVar = 0; iVar < nVar; iVar++) rbuf_residual[iVar] = sbuf_residual[iVar]; + for (iVar = 0; iVar < nVar; iVar++) + rbuf_residual[iVar] = sbuf_residual[iVar]; Global_nPointDomain = geometry->GetnPointDomain(); } - for (iVar = 0; iVar < nVar; iVar++) { if (rbuf_residual[iVar] != rbuf_residual[iVar]) { @@ -2587,13 +2573,13 @@ void CSolver::SetResidual_RMS(CGeometry *geometry, CConfig *config) { if (config->GetComm_Level() == COMM_FULL) { - sbuf_residual = new su2double [nVar]; for (iVar = 0; iVar < nVar; iVar++) sbuf_residual[iVar] = 0.0; - sbuf_point = new unsigned long [nVar]; for (iVar = 0; iVar < nVar; iVar++) sbuf_point[iVar] = 0; - sbuf_coord = new su2double[nVar*nDim]; for (iVar = 0; iVar < nVar*nDim; iVar++) sbuf_coord[iVar] = 0.0; + sbuf_residual = new su2double [nVar](); + sbuf_point = new unsigned long [nVar](); + sbuf_coord = new su2double[nVar*nDim](); - rbuf_residual = new su2double [nProcessor*nVar]; for (iVar = 0; iVar < nProcessor*nVar; iVar++) rbuf_residual[iVar] = 0.0; - rbuf_point = new unsigned long [nProcessor*nVar]; for (iVar = 0; iVar < nProcessor*nVar; iVar++) rbuf_point[iVar] = 0; - rbuf_coord = new su2double[nProcessor*nVar*nDim]; for (iVar = 0; iVar < nProcessor*nVar*nDim; iVar++) rbuf_coord[iVar] = 0.0; + rbuf_residual = new su2double [nProcessor*nVar](); + rbuf_point = new unsigned long [nProcessor*nVar](); + rbuf_coord = new su2double[nProcessor*nVar*nDim](); for (iVar = 0; iVar < nVar; iVar++) { sbuf_residual[iVar] = GetRes_Max(iVar); @@ -4176,7 +4162,8 @@ void CSolver::LoadInletProfile(CGeometry **geometry, unsigned short iDim, iVar, iMesh, iMarker, jMarker; unsigned long iPoint, iVertex, index, iChildren, Point_Fine, iRow; - su2double Area_Children, Area_Parent, *Coord, dist, min_dist, Interp_Radius, Theta; + su2double Area_Children, Area_Parent, dist, min_dist, Interp_Radius, Theta; + const su2double *Coord = nullptr; bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) || (config->GetTime_Marching() == DT_STEPPING_2ND)); bool time_stepping = config->GetTime_Marching() == TIME_STEPPING; @@ -4191,9 +4178,9 @@ void CSolver::LoadInletProfile(CGeometry **geometry, string profile_filename = config->GetInlet_FileName(); ifstream inlet_file; string Interpolation_Function, Interpolation_Type; - bool Interpolate; + bool Interpolate = false; - su2double *Normal = new su2double[nDim]; + su2double *Normal = new su2double[nDim]; unsigned long Marker_Counter = 0; @@ -4250,207 +4237,218 @@ void CSolver::LoadInletProfile(CGeometry **geometry, const su2double tolerance = config->GetInlet_Profile_Matching_Tolerance(); for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { - if (config->GetMarker_All_KindBC(iMarker) == KIND_MARKER) { - /*--- Get tag in order to identify the correct inlet data. ---*/ + /*--- Skip if this is the wrong type of marker. ---*/ - Marker_Tag = config->GetMarker_All_TagBound(iMarker); + if (config->GetMarker_All_KindBC(iMarker) != KIND_MARKER) continue; - for (jMarker = 0; jMarker < profileReader.GetNumberOfProfiles(); jMarker++) { + /*--- Get tag in order to identify the correct inlet data. ---*/ - /*--- If we have found the matching marker string, continue. ---*/ + Marker_Tag = config->GetMarker_All_TagBound(iMarker); - if (profileReader.GetTagForProfile(jMarker) == Marker_Tag) { + for (jMarker = 0; jMarker < profileReader.GetNumberOfProfiles(); jMarker++) { - /*--- Increment our counter for marker matches. ---*/ + /*--- If we have not found the matching marker string, continue to next marker. ---*/ - Marker_Counter++; + if (profileReader.GetTagForProfile(jMarker) != Marker_Tag) continue; - /*--- Get data for this profile. ---*/ + /*--- Increment our counter for marker matches. ---*/ - vector Inlet_Data = profileReader.GetDataForProfile(jMarker); - unsigned short nColumns = profileReader.GetNumberOfColumnsInProfile(jMarker); - vector Inlet_Data_Interpolated ((nCol_InletFile+nDim)*geometry[MESH_0]->nVertex[iMarker]); + Marker_Counter++; - /*--- Define Inlet Values vectors before and after interpolation (if needed) ---*/ - vector Inlet_Values(nCol_InletFile+nDim); - vector Inlet_Interpolated(nColumns); + /*--- Get data for this profile. ---*/ - unsigned long nRows = profileReader.GetNumberOfRowsInProfile(jMarker); + vector Inlet_Data = profileReader.GetDataForProfile(jMarker); + unsigned short nColumns = profileReader.GetNumberOfColumnsInProfile(jMarker); + vector Inlet_Data_Interpolated ((nCol_InletFile+nDim)*geometry[MESH_0]->nVertex[iMarker]); - /*--- Pointer to call Set and Evaluate functions. ---*/ - vector interpolator (nColumns); - string interpolation_function, interpolation_type; + /*--- Define Inlet Values vectors before and after interpolation (if needed) ---*/ + vector Inlet_Values(nCol_InletFile+nDim); + vector Inlet_Interpolated(nColumns); - /*--- Define the reference for interpolation. ---*/ - unsigned short radius_index=0; - vector InletRadii = profileReader.GetColumnForProfile(jMarker, radius_index); - vector Interpolation_Column (nRows); + unsigned long nRows = profileReader.GetNumberOfRowsInProfile(jMarker); - switch(config->GetKindInletInterpolationFunction()){ + /*--- Pointer to call Set and Evaluate functions. ---*/ + vector interpolator (nColumns); + string interpolation_function, interpolation_type; - case (NONE): - Interpolate = false; - break; + /*--- Define the reference for interpolation. ---*/ + unsigned short radius_index=0; + vector InletRadii = profileReader.GetColumnForProfile(jMarker, radius_index); + vector Interpolation_Column (nRows); - case (AKIMA_1D): - for (unsigned short iCol=0; iCol < nColumns; iCol++){ - Interpolation_Column = profileReader.GetColumnForProfile(jMarker, iCol); - interpolator[iCol] = new CAkimaInterpolation(InletRadii,Interpolation_Column); - interpolation_function = "AKIMA"; - Interpolate = true; - } - break; - - case (LINEAR_1D): - for (unsigned short iCol=0; iCol < nColumns; iCol++){ - Interpolation_Column = profileReader.GetColumnForProfile(jMarker, iCol); - interpolator[iCol] = new CLinearInterpolation(InletRadii,Interpolation_Column); - interpolation_function = "LINEAR"; - Interpolate = true; - } - break; - - default: - SU2_MPI::Error("Error in the Kind_InletInterpolation Marker\n",CURRENT_FUNCTION); - break; - } + switch(config->GetKindInletInterpolationFunction()){ - if (Interpolate == true){ - switch(config->GetKindInletInterpolationType()){ - case(VR_VTHETA): - interpolation_type="VR_VTHETA"; - break; - case(ALPHA_PHI): - interpolation_type="ALPHA_PHI"; - break; - } - cout<<"Inlet Interpolation being done using "<nVertex[iMarker]; iVertex++) { - - iPoint = geometry[MESH_0]->vertex[iMarker][iVertex]->GetNode(); - Coord = geometry[MESH_0]->node[iPoint]->GetCoord(); + default: + SU2_MPI::Error("Error in the Kind_InletInterpolation Marker\n",CURRENT_FUNCTION); + break; + } - if(Interpolate == false){ + if (Interpolate == true){ + switch(config->GetKindInletInterpolationType()){ + case(VR_VTHETA): + interpolation_type="VR_VTHETA"; + break; + case(ALPHA_PHI): + interpolation_type="ALPHA_PHI"; + break; + } + cout<<"Inlet Interpolation being done using "<nVertex[iMarker]; iVertex++) { - /*--- Get the coords for this data point. ---*/ + iPoint = geometry[MESH_0]->vertex[iMarker][iVertex]->GetNode(); + Coord = geometry[MESH_0]->node[iPoint]->GetCoord(); - index = iRow*nColumns; + if(Interpolate == false) { - dist = 0.0; - for (unsigned short iDim = 0; iDim < nDim; iDim++) - dist += pow(Inlet_Data[index+iDim] - Coord[iDim], 2); - dist = sqrt(dist); + min_dist = 1e16; - /*--- Check is this is the closest point and store data if so. ---*/ + /*--- Find the distance to the closest point in our inlet profile data. ---*/ - if (dist < min_dist) { - min_dist = dist; - for (iVar = 0; iVar < nColumns; iVar++) - Inlet_Values[iVar] = Inlet_Data[index+iVar]; - } + for (iRow = 0; iRow < nRows; iRow++) { - } + /*--- Get the coords for this data point. ---*/ - /*--- If the diff is less than the tolerance, match the two. - We could modify this to simply use the nearest neighbor, or - eventually add something more elaborate here for interpolation. ---*/ + index = iRow*nColumns; - if (min_dist < tolerance) { + dist = 0.0; + for (unsigned short iDim = 0; iDim < nDim; iDim++) + dist += pow(Inlet_Data[index+iDim] - Coord[iDim], 2); + dist = sqrt(dist); - solver[MESH_0][KIND_SOLVER]->SetInletAtVertex(Inlet_Values.data(), iMarker, iVertex); + /*--- Check is this is the closest point and store data if so. ---*/ - } else { + if (dist < min_dist) { + min_dist = dist; + for (iVar = 0; iVar < nColumns; iVar++) + Inlet_Values[iVar] = Inlet_Data[index+iVar]; + } - unsigned long GlobalIndex = geometry[MESH_0]->node[iPoint]->GetGlobalIndex(); - cout << "WARNING: Did not find a match between the points in the inlet file" << endl; - cout << "and point " << GlobalIndex; - cout << std::scientific; - cout << " at location: [" << Coord[0] << ", " << Coord[1]; - if (nDim ==3) error_msg << ", " << Coord[2]; - cout << "]" << endl; - cout << "Distance to closest point: " << min_dist << endl; - cout << "Current tolerance: " << tolerance << endl; - cout << endl; - cout << "You can widen the tolerance for point matching by changing the value" << endl; - cout << "of the option INLET_MATCHING_TOLERANCE in your *.cfg file." << endl; - local_failure++; - break; - } + } - } + /*--- If the diff is less than the tolerance, match the two. + We could modify this to simply use the nearest neighbor, or + eventually add something more elaborate here for interpolation. ---*/ + + if (min_dist < tolerance) { + + solver[MESH_0][KIND_SOLVER]->SetInletAtVertex(Inlet_Values.data(), iMarker, iVertex); + + } else { + + unsigned long GlobalIndex = geometry[MESH_0]->node[iPoint]->GetGlobalIndex(); + cout << "WARNING: Did not find a match between the points in the inlet file" << endl; + cout << "and point " << GlobalIndex; + cout << std::scientific; + cout << " at location: [" << Coord[0] << ", " << Coord[1]; + if (nDim ==3) error_msg << ", " << Coord[2]; + cout << "]" << endl; + cout << "Distance to closest point: " << min_dist << endl; + cout << "Current tolerance: " << tolerance << endl; + cout << endl; + cout << "You can widen the tolerance for point matching by changing the value" << endl; + cout << "of the option INLET_MATCHING_TOLERANCE in your *.cfg file." << endl; + local_failure++; + break; + } - else if(Interpolate == true){ - - /* --- Calculating the radius and angle of the vertex ---*/ - /* --- Flow should be in z direction for 3D cases ---*/ - /* --- Or in x direction for 2D cases ---*/ - Interp_Radius = sqrt(pow(Coord[0],2)+ pow(Coord[1],2)); - Theta = atan2(Coord[1],Coord[0]); - - /* --- Evaluating and saving the final spline data ---*/ - for (unsigned short iVar=0; iVar < nColumns; iVar++){ - - /*---Evaluate spline will get the respective value of the Data set (column) specified - for that interpolator[iVar], cycling through all columns to get all the - data for that vertex ---*/ - Inlet_Interpolated[iVar]=interpolator[iVar]->EvaluateSpline(Interp_Radius); - if (interpolator[iVar]->GetPointMatch() == false){ - cout << "WARNING: Did not find a match between the radius in the inlet file " ; - cout << std::scientific; - cout << "at location: [" << Coord[0] << ", " << Coord[1]; - if (nDim == 3) {cout << ", " << Coord[2];} - cout << "]"; - cout << " with Radius: "<< Interp_Radius << endl; - cout << "You can add a row for Radius: " << Interp_Radius <<" in the inlet file "; - cout << "to eliminate this issue or give proper data" << endl; - local_failure++; - break; - } - } + } - /* --- Correcting for Interpolation Type ---*/ - switch(config->GetKindInletInterpolationType()){ - case(VR_VTHETA): - Inlet_Values = CorrectedInletValues(Inlet_Interpolated, Theta, nDim, Coord, nVar_Turb, VR_VTHETA); - break; - case(ALPHA_PHI): - Inlet_Values = CorrectedInletValues(Inlet_Interpolated, Theta, nDim, Coord, nVar_Turb, ALPHA_PHI); + else if(Interpolate == true) { + + /* --- Calculating the radius and angle of the vertex ---*/ + /* --- Flow should be in z direction for 3D cases ---*/ + /* --- Or in x direction for 2D cases ---*/ + Interp_Radius = sqrt(pow(Coord[0],2)+ pow(Coord[1],2)); + Theta = atan2(Coord[1],Coord[0]); + + /* --- Evaluating and saving the final spline data ---*/ + for (unsigned short iVar=0; iVar < nColumns; iVar++){ + + /*---Evaluate spline will get the respective value of the Data set (column) specified + for that interpolator[iVar], cycling through all columns to get all the + data for that vertex ---*/ + Inlet_Interpolated[iVar]=interpolator[iVar]->EvaluateSpline(Interp_Radius); + if (interpolator[iVar]->GetPointMatch() == false){ + cout << "WARNING: Did not find a match between the radius in the inlet file " ; + cout << std::scientific; + cout << "at location: [" << Coord[0] << ", " << Coord[1]; + if (nDim == 3) {cout << ", " << Coord[2];} + cout << "]"; + cout << " with Radius: "<< Interp_Radius << endl; + cout << "You can add a row for Radius: " << Interp_Radius <<" in the inlet file "; + cout << "to eliminate this issue or give proper data" << endl; + local_failure++; break; - } - - solver[MESH_0][KIND_SOLVER]->SetInletAtVertex(Inlet_Values.data(), iMarker, iVertex); - - for (unsigned short iVar=0; iVar < (nCol_InletFile+nDim); iVar++) - Inlet_Data_Interpolated[iVertex*(nCol_InletFile+nDim)+iVar] = Inlet_Values[iVar]; } } - if(config->GetPrintInlet_InterpolatedData() == true) - PrintInletInterpolatedData(Inlet_Data_Interpolated,profileReader.GetTagForProfile(jMarker),geometry[MESH_0]->nVertex[iMarker],nDim, nCol_InletFile+nDim); - - for (int i=0; iGetKindInletInterpolationType()){ + case(VR_VTHETA): + Inlet_Values = CorrectedInletValues(Inlet_Interpolated, Theta, nDim, Coord, nVar_Turb, VR_VTHETA); + break; + case(ALPHA_PHI): + Inlet_Values = CorrectedInletValues(Inlet_Interpolated, Theta, nDim, Coord, nVar_Turb, ALPHA_PHI); + break; + } + + solver[MESH_0][KIND_SOLVER]->SetInletAtVertex(Inlet_Values.data(), iMarker, iVertex); + + for (unsigned short iVar=0; iVar < (nCol_InletFile+nDim); iVar++) + Inlet_Data_Interpolated[iVertex*(nCol_InletFile+nDim)+iVar] = Inlet_Values[iVar]; + } + + } // end iVertex loop + + if(config->GetPrintInlet_InterpolatedData() == true) { + PrintInletInterpolatedData(Inlet_Data_Interpolated, profileReader.GetTagForProfile(jMarker), + geometry[MESH_0]->nVertex[iMarker], nDim, nCol_InletFile+nDim); } - if (local_failure > 0) break; - } - } + + for (int i=0; i 0) break; + + } // end iMarker loop SU2_MPI::Allreduce(&local_failure, &global_failure, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD); @@ -4473,8 +4471,6 @@ void CSolver::LoadInletProfile(CGeometry **geometry, for (jMarker = 0; jMarker < profileReader.GetNumberOfProfiles(); jMarker++) { if (profileReader.GetTagForProfile(jMarker) == Marker_Tag) { nColumns = profileReader.GetNumberOfColumnsInProfile(jMarker); - if(Interpolate == true) - nColumns+=nDim; } } vector Inlet_Values(nColumns); diff --git a/SU2_CFD/src/solvers/CTemplateSolver.cpp b/SU2_CFD/src/solvers/CTemplateSolver.cpp index b2328e580acc..b3b3bebff3f6 100644 --- a/SU2_CFD/src/solvers/CTemplateSolver.cpp +++ b/SU2_CFD/src/solvers/CTemplateSolver.cpp @@ -38,14 +38,14 @@ void CTemplateSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contai void CTemplateSolver::SetTime_Step(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned long Iteration) { } -void CTemplateSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, +void CTemplateSolver::Centered_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { } -void CTemplateSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, +void CTemplateSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { } -void CTemplateSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) { } +void CTemplateSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { } void CTemplateSolver::Source_Template(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short iMesh) { } diff --git a/SU2_CFD/src/solvers/CTransLMSolver.cpp b/SU2_CFD/src/solvers/CTransLMSolver.cpp index 7153c2113ecb..73f809b596b9 100644 --- a/SU2_CFD/src/solvers/CTransLMSolver.cpp +++ b/SU2_CFD/src/solvers/CTransLMSolver.cpp @@ -259,7 +259,11 @@ void CTransLMSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solv } -void CTransLMSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short iMesh) { +void CTransLMSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[CONV_TERM]; + su2double *trans_var_i, *trans_var_j, *U_i, *U_j; unsigned long iEdge, iPoint, jPoint; @@ -286,18 +290,18 @@ void CTransLMSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_conta LinSysRes.SubtractBlock(jPoint, Residual); /*--- Implicit part ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); - Jacobian.AddBlock(iPoint, jPoint, Jacobian_j); - Jacobian.SubtractBlock(jPoint, iPoint, Jacobian_i); - Jacobian.SubtractBlock(jPoint, jPoint, Jacobian_j); + Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, Jacobian_i, Jacobian_j); } } -void CTransLMSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, +void CTransLMSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { + + CNumerics* numerics = numerics_container[VISC_TERM]; + unsigned long iEdge, iPoint, jPoint; for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { @@ -339,16 +343,16 @@ void CTransLMSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_cont LinSysRes.SubtractBlock(iPoint, Residual); LinSysRes.AddBlock(jPoint, Residual); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); - Jacobian.SubtractBlock(iPoint, jPoint, Jacobian_j); - Jacobian.AddBlock(jPoint, iPoint, Jacobian_i); - Jacobian.AddBlock(jPoint, jPoint, Jacobian_j); + Jacobian.UpdateBlocksSub(iEdge, iPoint, jPoint, Jacobian_i, Jacobian_j); } } -void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) { +void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + CNumerics* numerics = numerics_container[SOURCE_FIRST_TERM]; + unsigned long iPoint; su2double gamma_sep = 0.0; @@ -394,7 +398,7 @@ void CTransLMSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta /*--- Subtract residual and the Jacobian ---*/ LinSysRes.SubtractBlock(iPoint, Residual); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i); } } @@ -449,7 +453,7 @@ void CTransLMSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_cont // cout << "Implicit part -AA" << endl; /*--- Jacobian contribution for implicit integration ---*/ if (implicit) { - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); } } } diff --git a/SU2_CFD/src/solvers/CTurbSASolver.cpp b/SU2_CFD/src/solvers/CTurbSASolver.cpp index 9030d0f8f775..61ed84e0d972 100644 --- a/SU2_CFD/src/solvers/CTurbSASolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSASolver.cpp @@ -25,18 +25,16 @@ * License along with SU2. If not, see . */ - #include "../../include/solvers/CTurbSASolver.hpp" #include "../../include/variables/CTurbSAVariable.hpp" +#include "../../../Common/include/omp_structure.hpp" -CTurbSASolver::CTurbSASolver(void) : CTurbSolver() { - - Inlet_TurbVars = NULL; -} +CTurbSASolver::CTurbSASolver(void) : CTurbSolver() { } CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned short iMesh, CFluidModel* FluidModel) - : CTurbSolver(geometry, config) { + : CTurbSolver(geometry, config) { + unsigned short iVar, iDim, nLineLets; unsigned long iPoint; su2double Density_Inf, Viscosity_Inf, Factor_nu_Inf, Factor_nu_Engine, Factor_nu_ActDisk; @@ -67,20 +65,18 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor /*--- 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_i = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_i[iVar] = 0.0; - Residual_j = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_j[iVar] = 0.0; - Residual_Max = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_Max[iVar] = 0.0; + Residual = new su2double[nVar](); + Residual_RMS = new su2double[nVar](); + Residual_i = new su2double[nVar](); + Residual_j = new su2double[nVar](); + Residual_Max = new su2double[nVar](); /*--- 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 = new unsigned long[nVar](); 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; + Point_Max_Coord[iVar] = new su2double[nDim](); } /*--- Define some auxiliar vector related with the solution ---*/ @@ -88,14 +84,6 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor Solution = new su2double[nVar]; Solution_i = new su2double[nVar]; Solution_j = new su2double[nVar]; - /*--- Define some auxiliar vector related with the geometry ---*/ - - Vector_i = new su2double[nDim]; Vector_j = new su2double[nDim]; - - /*--- Define some auxiliar vector related with the flow solution ---*/ - - FlowPrimVar_i = new su2double [nDim+9]; FlowPrimVar_j = new su2double [nDim+9]; - /*--- Jacobians and vector structures for implicit computations ---*/ Jacobian_i = new su2double* [nVar]; @@ -141,16 +129,15 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor /*--- Initialize the BGS residuals in multizone problems. ---*/ if (multizone){ - Residual_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_BGS[iVar] = 0.0; - Residual_Max_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_Max_BGS[iVar] = 0.0; + Residual_BGS = new su2double[nVar](); + Residual_Max_BGS = new su2double[nVar](); /*--- 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_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]; - for (iDim = 0; iDim < nDim; iDim++) Point_Max_Coord_BGS[iVar][iDim] = 0.0; + Point_Max_Coord_BGS[iVar] = new su2double[nDim] (); } } @@ -202,28 +189,20 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor unsigned long iMarker; - SlidingState = new su2double*** [nMarker]; - SlidingStateNodes = new int* [nMarker]; + SlidingState = new su2double*** [nMarker] (); + SlidingStateNodes = new int* [nMarker] (); for (iMarker = 0; iMarker < nMarker; iMarker++){ - SlidingState[iMarker] = NULL; - SlidingStateNodes[iMarker] = NULL; - 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] = NULL; - } + 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] (); } + } /*-- Allocation of inlets has to happen in derived classes (not CTurbSolver), @@ -231,11 +210,11 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor Inlet_TurbVars = new su2double**[nMarker]; for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) { - Inlet_TurbVars[iMarker] = new su2double*[nVertex[iMarker]]; - for(unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ - Inlet_TurbVars[iMarker][iVertex] = new su2double[nVar]; - Inlet_TurbVars[iMarker][iVertex][0] = nu_tilde_Inf; - } + Inlet_TurbVars[iMarker] = new su2double*[nVertex[iMarker]]; + for(unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ + Inlet_TurbVars[iMarker][iVertex] = new su2double[nVar] (); + Inlet_TurbVars[iMarker][iVertex][0] = nu_tilde_Inf; + } } /*--- The turbulence models are always solved implicitly, so set the @@ -263,11 +242,11 @@ CTurbSASolver::~CTurbSASolver(void) { unsigned long iMarker, iVertex; unsigned short iVar; - if ( SlidingState != NULL ) { + if ( SlidingState != nullptr ) { for (iMarker = 0; iMarker < nMarker; iMarker++) { - if ( SlidingState[iMarker] != NULL ) { + if ( SlidingState[iMarker] != nullptr ) { for (iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) - if ( SlidingState[iMarker][iVertex] != NULL ){ + if ( SlidingState[iMarker][iVertex] != nullptr ){ for (iVar = 0; iVar < nPrimVar+1; iVar++) delete [] SlidingState[iMarker][iVertex][iVar]; delete [] SlidingState[iMarker][iVertex]; @@ -278,35 +257,28 @@ CTurbSASolver::~CTurbSASolver(void) { delete [] SlidingState; } - if ( SlidingStateNodes != NULL ){ + if ( SlidingStateNodes != nullptr ){ for (iMarker = 0; iMarker < nMarker; iMarker++){ - if (SlidingStateNodes[iMarker] != NULL) - delete [] SlidingStateNodes[iMarker]; + if (SlidingStateNodes[iMarker] != nullptr) + delete [] SlidingStateNodes[iMarker]; } delete [] SlidingStateNodes; } } -void CTurbSASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { +void CTurbSASolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, + unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { - unsigned long iPoint; - bool limiter_turb = (config->GetKind_SlopeLimit_Turb() != NO_LIMITER) && (config->GetInnerIter() <= config->GetLimiterIter()); + bool limiter_turb = (config->GetKind_SlopeLimit_Turb() != NO_LIMITER) && + (config->GetInnerIter() <= config->GetLimiterIter()); unsigned short kind_hybridRANSLES = config->GetKind_HybridRANSLES(); - su2double** PrimGrad_Flow = NULL; - su2double* Vorticity = NULL; - su2double Laminar_Viscosity = 0; - - for (iPoint = 0; iPoint < nPoint; iPoint ++) { - - /*--- Initialize the residual vector ---*/ - - LinSysRes.SetBlock_Zero(iPoint); - - } - - /*--- Initialize the Jacobian matrices ---*/ + const su2double* const* PrimGrad_Flow = nullptr; + const su2double* Vorticity = nullptr; + su2double Laminar_Viscosity = 0.0; + /*--- Clear residual and system matrix. ---*/ + LinSysRes.SetValZero(); Jacobian.SetValZero(); /*--- Upwind second order reconstruction and gradients ---*/ @@ -319,21 +291,26 @@ void CTurbSASolver::Preprocessing(CGeometry *geometry, CSolver **solver_containe if (config->GetKind_Gradient_Method_Recon() == WEIGHTED_LEAST_SQUARES) SetSolution_Gradient_LS(geometry, config, true); } - if (config->GetKind_Gradient_Method() == GREEN_GAUSS) SetSolution_Gradient_GG(geometry, config); - if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) SetSolution_Gradient_LS(geometry, config); + + if (config->GetKind_Gradient_Method() == GREEN_GAUSS) + SetSolution_Gradient_GG(geometry, config); + + if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) + SetSolution_Gradient_LS(geometry, config); if (limiter_turb) SetSolution_Limiter(geometry, config); - if (kind_hybridRANSLES != NO_HYBRIDRANSLES){ + if (kind_hybridRANSLES != NO_HYBRIDRANSLES) { /*--- Set the vortex tilting coefficient at every node if required ---*/ if (kind_hybridRANSLES == SA_EDDES){ - for (iPoint = 0; iPoint < nPoint; iPoint++){ - PrimGrad_Flow = solver_container[FLOW_SOL]->GetNodes()->GetGradient_Primitive(iPoint); - Vorticity = solver_container[FLOW_SOL]->GetNodes()->GetVorticity(iPoint); + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint++){ + Vorticity = solver_container[FLOW_SOL]->GetNodes()->GetVorticity(iPoint); + PrimGrad_Flow = solver_container[FLOW_SOL]->GetNodes()->GetGradient_Primitive(iPoint); Laminar_Viscosity = solver_container[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); - nodes->SetVortex_Tilting(iPoint,PrimGrad_Flow, Vorticity, Laminar_Viscosity); + nodes->SetVortex_Tilting(iPoint, PrimGrad_Flow, Vorticity, Laminar_Viscosity); } } @@ -342,33 +319,33 @@ void CTurbSASolver::Preprocessing(CGeometry *geometry, CSolver **solver_containe SetDES_LengthScale(solver_container, geometry, config); } + } void CTurbSASolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh) { - su2double rho = 0.0, mu = 0.0, nu, *nu_hat, muT, Ji, Ji_3, fv1; - su2double cv1_3 = 7.1*7.1*7.1; - unsigned long iPoint; + const su2double cv1_3 = 7.1*7.1*7.1; - bool neg_spalart_allmaras = (config->GetKind_Turb_Model() == SA_NEG); + const bool neg_spalart_allmaras = (config->GetKind_Turb_Model() == SA_NEG); /*--- Compute eddy viscosity ---*/ - for (iPoint = 0; iPoint < nPoint; iPoint ++) { + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { - rho = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); - mu = solver_container[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); + su2double rho = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); + su2double mu = solver_container[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); - nu = mu/rho; - nu_hat = nodes->GetSolution(iPoint); + su2double nu = mu/rho; + su2double nu_hat = nodes->GetSolution(iPoint,0); - Ji = nu_hat[0]/nu; - Ji_3 = Ji*Ji*Ji; - fv1 = Ji_3/(Ji_3+cv1_3); + su2double Ji = nu_hat/nu; + su2double Ji_3 = Ji*Ji*Ji; + su2double fv1 = Ji_3/(Ji_3+cv1_3); - muT = rho*fv1*nu_hat[0]; + su2double muT = rho*fv1*nu_hat; - if (neg_spalart_allmaras && (muT < 0.0)) muT = 0.0; + if (neg_spalart_allmaras) muT = max(muT,0.0); nodes->SetmuT(iPoint,muT); @@ -376,29 +353,36 @@ void CTurbSASolver::Postprocessing(CGeometry *geometry, CSolver **solver_contain } -void CTurbSASolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, - CConfig *config, unsigned short iMesh) { - unsigned long iPoint; +void CTurbSASolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { + + const bool harmonic_balance = (config->GetTime_Marching() == HARMONIC_BALANCE); + const bool transition = (config->GetKind_Trans_Model() == LM); + const bool transition_BC = (config->GetKind_Trans_Model() == BC); - bool harmonic_balance = (config->GetTime_Marching() == HARMONIC_BALANCE); - bool transition = (config->GetKind_Trans_Model() == LM); - bool transition_BC = (config->GetKind_Trans_Model() == BC); + CVariable* flowNodes = solver_container[FLOW_SOL]->GetNodes(); - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + /*--- Pick one numerics object per thread. ---*/ + CNumerics* numerics = numerics_container[SOURCE_FIRST_TERM + omp_get_thread_num()*MAX_TERMS]; + + /*--- Loop over all points. ---*/ + + SU2_OMP_FOR_DYN(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Conservative variables w/o reconstruction ---*/ - numerics->SetPrimitive(solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(iPoint), NULL); + numerics->SetPrimitive(flowNodes->GetPrimitive(iPoint), nullptr); /*--- Gradient of the primitive and conservative variables ---*/ - numerics->SetPrimVarGradient(solver_container[FLOW_SOL]->GetNodes()->GetGradient_Primitive(iPoint), NULL); + numerics->SetPrimVarGradient(flowNodes->GetGradient_Primitive(iPoint), nullptr); /*--- Set vorticity and strain rate magnitude ---*/ - numerics->SetVorticity(solver_container[FLOW_SOL]->GetNodes()->GetVorticity(iPoint), NULL); + numerics->SetVorticity(flowNodes->GetVorticity(iPoint), nullptr); - numerics->SetStrainMag(solver_container[FLOW_SOL]->GetNodes()->GetStrainMag(iPoint), 0.0); + numerics->SetStrainMag(flowNodes->GetStrainMag(iPoint), 0.0); /*--- Set intermittency ---*/ @@ -408,8 +392,8 @@ void CTurbSASolver::Source_Residual(CGeometry *geometry, CSolver **solver_contai /*--- Turbulent variables w/o reconstruction, and its gradient ---*/ - numerics->SetTurbVar(nodes->GetSolution(iPoint), NULL); - numerics->SetTurbVarGradient(nodes->GetGradient(iPoint), NULL); + numerics->SetTurbVar(nodes->GetSolution(iPoint), nullptr); + numerics->SetTurbVarGradient(nodes->GetGradient(iPoint), nullptr); /*--- Set volume ---*/ @@ -433,7 +417,7 @@ void CTurbSASolver::Source_Residual(CGeometry *geometry, CSolver **solver_contai /*--- Compute the source term ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, NULL, config); + auto residual = numerics->ComputeResidual(config); /*--- Store the intermittency ---*/ @@ -443,36 +427,25 @@ void CTurbSASolver::Source_Residual(CGeometry *geometry, CSolver **solver_contai /*--- Subtract residual and the Jacobian ---*/ - LinSysRes.SubtractBlock(iPoint, Residual); + LinSysRes.SubtractBlock(iPoint, residual); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } if (harmonic_balance) { - su2double Volume, Source; - unsigned short nVar_Turb = solver_container[TURB_SOL]->GetnVar(); - - /*--- Loop over points ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { - - /*--- Get control volume ---*/ - - Volume = geometry->node[iPoint]->GetVolume(); + su2double Volume = geometry->node[iPoint]->GetVolume(); /*--- Access stored harmonic balance source term ---*/ - for (unsigned short iVar = 0; iVar < nVar_Turb; iVar++) { - Source = nodes->GetHarmonicBalance_Source(iPoint,iVar); - Residual[iVar] = Source*Volume; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + su2double Source = nodes->GetHarmonicBalance_Source(iPoint,iVar); + LinSysRes(iPoint,iVar) += Source*Volume; } - - /*--- Add Residual ---*/ - - LinSysRes.AddBlock(iPoint, Residual); - } } @@ -480,10 +453,10 @@ void CTurbSASolver::Source_Residual(CGeometry *geometry, CSolver **solver_contai void CTurbSASolver::Source_Template(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short iMesh) { - } -void CTurbSASolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CTurbSASolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned long iPoint, iVertex; unsigned short iVar; @@ -524,8 +497,8 @@ void CTurbSASolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_conta } -void CTurbSASolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, - unsigned short val_marker) { +void CTurbSASolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned long iPoint, iVertex; unsigned short iVar; @@ -551,7 +524,8 @@ void CTurbSASolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_con } -void CTurbSASolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CTurbSASolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned long iPoint, iVertex; unsigned short iVar, iDim; @@ -598,12 +572,12 @@ void CTurbSASolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container /*--- Compute residuals and Jacobians ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Add residuals and Jacobians ---*/ - LinSysRes.AddBlock(iPoint, Residual); - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.AddBlock(iPoint, residual); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } } @@ -612,7 +586,8 @@ void CTurbSASolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container } -void CTurbSASolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CTurbSASolver::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; @@ -669,12 +644,12 @@ void CTurbSASolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, CN /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -692,12 +667,12 @@ void CTurbSASolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, CN // // /*--- Compute residual, and Jacobians ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); +// auto residual = visc_numerics->ComputeResidual(config); // // /*--- Subtract residual, and update Jacobians ---*/ // -// LinSysRes.SubtractBlock(iPoint, Residual); -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// LinSysRes.SubtractBlock(iPoint, residual); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } } @@ -707,8 +682,9 @@ void CTurbSASolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, CN } -void CTurbSASolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, - CConfig *config, unsigned short val_marker) { +void CTurbSASolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + unsigned long iPoint, iVertex; unsigned short iVar, iDim; su2double *V_outlet, *V_domain, *Normal; @@ -761,12 +737,12 @@ void CTurbSASolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, C /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -784,12 +760,12 @@ void CTurbSASolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, C // // /*--- Compute residual, and Jacobians ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); +// auto residual = visc_numerics->ComputeResidual(config); // // /*--- Subtract residual, and update Jacobians ---*/ // -// LinSysRes.SubtractBlock(iPoint, Residual); -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// LinSysRes.SubtractBlock(iPoint, residual); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } } @@ -800,8 +776,8 @@ void CTurbSASolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, C } -void CTurbSASolver::BC_Engine_Inflow(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { - +void CTurbSASolver::BC_Engine_Inflow(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned long iPoint, iVertex; unsigned short iDim; su2double *V_inflow, *V_domain, *Normal; @@ -851,12 +827,12 @@ void CTurbSASolver::BC_Engine_Inflow(CGeometry *geometry, CSolver **solver_conta /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -874,12 +850,12 @@ void CTurbSASolver::BC_Engine_Inflow(CGeometry *geometry, CSolver **solver_conta // // /*--- Compute residual, and Jacobians ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); +// auto residual = visc_numerics->ComputeResidual(config); // // /*--- Subtract residual, and update Jacobians ---*/ // -// LinSysRes.SubtractBlock(iPoint, Residual); -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// LinSysRes.SubtractBlock(iPoint, residual); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } @@ -891,7 +867,8 @@ void CTurbSASolver::BC_Engine_Inflow(CGeometry *geometry, CSolver **solver_conta } -void CTurbSASolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CTurbSASolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iDim; unsigned long iVertex, iPoint; @@ -947,12 +924,12 @@ void CTurbSASolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_cont /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -970,12 +947,12 @@ void CTurbSASolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_cont // // /*--- Compute residual, and Jacobians ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); +// auto residual = visc_numerics->ComputeResidual(config); // // /*--- Subtract residual, and update Jacobians ---*/ // -// LinSysRes.SubtractBlock(iPoint, Residual); -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// LinSysRes.SubtractBlock(iPoint, residual); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } } @@ -989,20 +966,17 @@ void CTurbSASolver::BC_Engine_Exhaust(CGeometry *geometry, CSolver **solver_cont void CTurbSASolver::BC_ActDisk_Inlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { - BC_ActDisk(geometry, solver_container, conv_numerics, visc_numerics, - config, val_marker, true); - + BC_ActDisk(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker, true); } void CTurbSASolver::BC_ActDisk_Outlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { - BC_ActDisk(geometry, solver_container, conv_numerics, visc_numerics, - config, val_marker, false); - + BC_ActDisk(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker, false); } -void CTurbSASolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, +void CTurbSASolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, + CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker, bool val_inlet_surface) { unsigned long iPoint, iVertex, GlobalIndex_donor, GlobalIndex; @@ -1109,12 +1083,12 @@ void CTurbSASolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -1134,12 +1108,12 @@ void CTurbSASolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, // // /*--- Compute residual, and Jacobians ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); +// auto residual = visc_numerics->ComputeResidual(config); // // /*--- Subtract residual, and update Jacobians ---*/ // -// LinSysRes.SubtractBlock(iPoint, Residual); -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// LinSysRes.SubtractBlock(iPoint, residual); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } } @@ -1152,7 +1126,8 @@ void CTurbSASolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, } -void CTurbSASolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CTurbSASolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iDim, iSpan; unsigned long oldVertex, iPoint, Point_Normal, iVertex; @@ -1219,12 +1194,12 @@ void CTurbSASolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_c /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto conv_residual = conv_numerics->ComputeResidual(config); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.AddBlock(iPoint, conv_residual); + Jacobian.AddBlock2Diag(iPoint, conv_residual.jacobian_i); /*--- Viscous contribution ---*/ @@ -1242,12 +1217,12 @@ void CTurbSASolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_c /*--- Compute residual, and Jacobians ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto visc_residual = visc_numerics->ComputeResidual(config); /*--- Subtract residual, and update Jacobians ---*/ - LinSysRes.SubtractBlock(iPoint, Residual); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.SubtractBlock(iPoint, visc_residual); + Jacobian.SubtractBlock2Diag(iPoint, visc_residual.jacobian_i); } } @@ -1257,8 +1232,8 @@ void CTurbSASolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_c } -void CTurbSASolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { - +void CTurbSASolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iDim, iSpan; unsigned long oldVertex, iPoint, Point_Normal, iVertex; su2double *V_inlet, *V_domain, *Normal; @@ -1335,12 +1310,12 @@ void CTurbSASolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_contain /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto conv_residual = conv_numerics->ComputeResidual(config); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.AddBlock(iPoint, conv_residual); + Jacobian.AddBlock2Diag(iPoint, conv_residual.jacobian_i); /*--- Viscous contribution ---*/ @@ -1358,12 +1333,12 @@ void CTurbSASolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_contain /*--- Compute residual, and Jacobians ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto visc_residual = visc_numerics->ComputeResidual(config); /*--- Subtract residual, and update Jacobians ---*/ - LinSysRes.SubtractBlock(iPoint, Residual); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.SubtractBlock(iPoint, visc_residual); + Jacobian.SubtractBlock2Diag(iPoint, visc_residual.jacobian_i); } } @@ -1420,7 +1395,7 @@ void CTurbSASolver::BC_Interface_Boundary(CGeometry *geometry, CSolver **solver_ // /*--- Add Residuals and Jacobians ---*/ // numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); // LinSysRes.AddBlock(iPoint, Residual); - // Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + // Jacobian.AddBlock2Diag(iPoint, Jacobian_i); // // } // } @@ -1521,7 +1496,7 @@ void CTurbSASolver::BC_Interface_Boundary(CGeometry *geometry, CSolver **solver_ // // numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); // LinSysRes.AddBlock(iPoint, Residual); - // Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + // Jacobian.AddBlock2Diag(iPoint, Jacobian_i); // // } // } @@ -1536,17 +1511,16 @@ void CTurbSASolver::BC_Interface_Boundary(CGeometry *geometry, CSolver **solver_ // } -void CTurbSASolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, - CNumerics *visc_numerics, CConfig *config){ +void CTurbSASolver::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, iMarker; + unsigned short iDim, iVar, jVar, iMarker; unsigned short nPrimVar = solver_container[FLOW_SOL]->GetnPrimVar(); - su2double *Normal = new su2double[nDim]; + su2double Normal[MAXNDIM] = {0.0}; su2double *PrimVar_i = new su2double[nPrimVar]; su2double *PrimVar_j = new su2double[nPrimVar]; - su2double *tmp_residual = new su2double[nVar]; unsigned long nDonorVertex; su2double weight; @@ -1566,12 +1540,15 @@ void CTurbSASolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_con /*--- Initialize Residual, this will serve to accumulate the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) + 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++){ + for (jVertex = 0; jVertex < nDonorVertex; jVertex++) { geometry->vertex[iMarker][iVertex]->GetNormal(Normal); for (iDim = 0; iDim < nDim; iDim++) Normal[iDim] = -Normal[iDim]; @@ -1603,20 +1580,22 @@ void CTurbSASolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_con /*--- Compute the convective residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(tmp_residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Accumulate the residuals to compute the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] += weight*tmp_residual[iVar]; - + 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); - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); /*--- Set the normal vector and the coordinates ---*/ @@ -1635,13 +1614,13 @@ void CTurbSASolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_con /*--- Compute and update residual ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = visc_numerics->ComputeResidual(config); - LinSysRes.SubtractBlock(iPoint, Residual); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } } @@ -1650,8 +1629,6 @@ void CTurbSASolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_con /*--- Free locally allocated memory ---*/ - delete [] tmp_residual; - delete [] Normal; delete [] PrimVar_i; delete [] PrimVar_j; @@ -1704,7 +1681,7 @@ void CTurbSASolver::BC_NearField_Boundary(CGeometry *geometry, CSolver **solver_ // /*--- Add Residuals and Jacobians ---*/ // numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); // LinSysRes.AddBlock(iPoint, Residual); - // Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + // Jacobian.AddBlock2Diag(iPoint, Jacobian_i); // // } // } @@ -1805,7 +1782,7 @@ void CTurbSASolver::BC_NearField_Boundary(CGeometry *geometry, CSolver **solver_ // // numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); // LinSysRes.AddBlock(iPoint, Residual); - // Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + // Jacobian.AddBlock2Diag(iPoint, Jacobian_i); // // } // } @@ -1821,7 +1798,7 @@ void CTurbSASolver::BC_NearField_Boundary(CGeometry *geometry, CSolver **solver_ } void CTurbSASolver::SetNuTilde_WF(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, - CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { /*--- Local variables ---*/ @@ -2105,17 +2082,17 @@ void CTurbSASolver::SetDES_LengthScale(CSolver **solver, CGeometry *geometry, CC su2double density = 0.0, laminarViscosity = 0.0, kinematicViscosity = 0.0, eddyViscosity = 0.0, kinematicViscosityTurb = 0.0, wallDistance = 0.0, lengthScale = 0.0; - su2double maxDelta = 0.0, deltaAux = 0.0, distDES = 0.0, uijuij = 0.0, k2 = 0.0, r_d = 0.0, f_d = 0.0, - deltaDDES = 0.0, omega = 0.0, ln_max = 0.0, ln[3] = {0.0, 0.0, 0.0}, - aux_ln = 0.0, f_kh = 0.0; + su2double maxDelta = 0.0, deltaAux = 0.0, distDES = 0.0, uijuij = 0.0, k2 = 0.0, r_d = 0.0, f_d = 0.0; + su2double deltaDDES = 0.0, omega = 0.0, ln_max = 0.0, ln[3] = {0.0}, aux_ln = 0.0, f_kh = 0.0; su2double nu_hat, fw_star = 0.424, cv1_3 = pow(7.1, 3.0); k2 = pow(0.41, 2.0); su2double cb1 = 0.1355, ct3 = 1.2, ct4 = 0.5; su2double sigma = 2./3., cb2 = 0.622, f_max=1.0, f_min=0.1, a1=0.15, a2=0.3; su2double cw1 = 0.0, Ji = 0.0, Ji_2 = 0.0, Ji_3 = 0.0, fv1 = 0.0, fv2 = 0.0, ft2 = 0.0, psi_2 = 0.0; - su2double *coord_i = NULL, *coord_j = NULL, **primVarGrad = NULL, *vorticity = NULL, delta[3] = {0.0,0.0,0.0}, - ratioOmega[3] = {0.0, 0.0, 0.0}, vortexTiltingMeasure = 0.0; + const su2double *coord_i = nullptr, *coord_j = nullptr, *const *primVarGrad = nullptr, *vorticity = nullptr; + su2double delta[3] = {0.0}, ratioOmega[3] = {0.0}, vortexTiltingMeasure = 0.0; + SU2_OMP_FOR_DYN(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++){ coord_i = geometry->node[iPoint]->GetCoord(); @@ -2160,7 +2137,7 @@ void CTurbSASolver::SetDES_LengthScale(CSolver **solver, CGeometry *geometry, CC ---*/ maxDelta = geometry->node[iPoint]->GetMaxLength(); - distDES = constDES * maxDelta; + distDES = constDES * maxDelta; lengthScale = min(distDES,wallDistance); break; @@ -2190,8 +2167,8 @@ void CTurbSASolver::SetDES_LengthScale(CSolver **solver, CGeometry *geometry, CC jPoint = geometry->node[iPoint]->GetPoint(iNeigh); coord_j = geometry->node[jPoint]->GetCoord(); for ( iDim = 0; iDim < nDim; iDim++){ - deltaAux = abs(coord_j[iDim] - coord_i[iDim]); - delta[iDim] = max(delta[iDim], deltaAux); + deltaAux = abs(coord_j[iDim] - coord_i[iDim]); + delta[iDim] = max(delta[iDim], deltaAux); } deltaDDES = geometry->node[iPoint]->GetMaxLength(); } @@ -2273,7 +2250,7 @@ void CTurbSASolver::SetDES_LengthScale(CSolver **solver, CGeometry *geometry, CC } - nodes->SetDES_LengthScale(iPoint,lengthScale); + nodes->SetDES_LengthScale(iPoint, lengthScale); } } diff --git a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp index 3e8360d725f7..e8004e8ccf02 100644 --- a/SU2_CFD/src/solvers/CTurbSSTSolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSSTSolver.cpp @@ -25,17 +25,12 @@ * License along with SU2. If not, see . */ - #include "../../include/solvers/CTurbSSTSolver.hpp" #include "../../include/variables/CTurbSSTVariable.hpp" +#include "../../../Common/include/omp_structure.hpp" -CTurbSSTSolver::CTurbSSTSolver(void) : CTurbSolver() { - - /*--- Array initialization ---*/ - constants = NULL; - Inlet_TurbVars = NULL; -} +CTurbSSTSolver::CTurbSSTSolver(void) : CTurbSolver() { } CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned short iMesh) : CTurbSolver(geometry, config) { @@ -48,8 +43,6 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh /*--- Array initialization ---*/ - constants = NULL; - Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; @@ -74,20 +67,18 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh /*--- Define some auxiliary 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_i = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_i[iVar] = 0.0; - Residual_j = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_j[iVar] = 0.0; - Residual_Max = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_Max[iVar] = 0.0; + Residual = new su2double[nVar](); + Residual_RMS = new su2double[nVar](); + Residual_i = new su2double[nVar](); + Residual_j = new su2double[nVar](); + Residual_Max = new su2double[nVar](); /*--- 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 = new unsigned long[nVar](); 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; + Point_Max_Coord[iVar] = new su2double[nDim](); } /*--- Define some auxiliary vector related with the solution ---*/ @@ -95,14 +86,6 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh Solution = new su2double[nVar]; Solution_i = new su2double[nVar]; Solution_j = new su2double[nVar]; - /*--- Define some auxiliary vector related with the geometry ---*/ - - Vector_i = new su2double[nDim]; Vector_j = new su2double[nDim]; - - /*--- Define some auxiliary vector related with the flow solution ---*/ - - FlowPrimVar_i = new su2double [nDim+9]; FlowPrimVar_j = new su2double [nDim+9]; - /*--- Jacobians and vector structures for implicit computations ---*/ Jacobian_i = new su2double* [nVar]; @@ -127,16 +110,15 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh /*--- Initialize the BGS residuals in multizone problems. ---*/ if (multizone){ - Residual_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_BGS[iVar] = 0.0; - Residual_Max_BGS = new su2double[nVar]; for (iVar = 0; iVar < nVar; iVar++) Residual_Max_BGS[iVar] = 0.0; + Residual_BGS = new su2double[nVar](); + Residual_Max_BGS = new su2double[nVar](); /*--- 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_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]; - for (iDim = 0; iDim < nDim; iDim++) Point_Max_Coord_BGS[iVar][iDim] = 0.0; + Point_Max_Coord_BGS[iVar] = new su2double[nDim](); } } @@ -148,15 +130,14 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh /*--- S matrix := inv(R)*traspose(inv(R)) ---*/ Smatrix = new su2double* [nDim]; for (iDim = 0; iDim < nDim; iDim++) - Smatrix[iDim] = new su2double [nDim]; + Smatrix[iDim] = new su2double [nDim]; /*--- c vector := transpose(WA)*(Wb) ---*/ Cvector = new su2double* [nVar]; for (iVar = 0; iVar < nVar; iVar++) - Cvector[iVar] = new su2double [nDim]; + Cvector[iVar] = new su2double [nDim]; } /*--- Initialize value for model constants ---*/ - constants = new su2double[10]; constants[0] = 0.85; //sigma_k1 constants[1] = 1.0; //sigma_k2 constants[2] = 0.5; //sigma_om1 @@ -169,9 +150,6 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh constants[9] = constants[5]/constants[6] - constants[3]*0.41*0.41/sqrt(constants[6]); //alfa_2 /*--- Initialize lower and upper limits---*/ - lowerlimit = new su2double[nVar]; - upperlimit = new su2double[nVar]; - lowerlimit[0] = 1.0e-10; upperlimit[0] = 1.0e10; @@ -212,42 +190,33 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh unsigned long iMarker; - SlidingState = new su2double*** [nMarker]; - SlidingStateNodes = new int* [nMarker]; + SlidingState = new su2double*** [nMarker](); + SlidingStateNodes = new int* [nMarker](); for (iMarker = 0; iMarker < nMarker; iMarker++){ - SlidingState[iMarker] = NULL; - SlidingStateNodes[iMarker] = NULL; - 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] = NULL; - } + 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](); } } /*-- Allocation of inlets has to happen in derived classes (not CTurbSolver), due to arbitrary number of turbulence variables ---*/ - Inlet_TurbVars = new su2double**[nMarker]; - for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) { - Inlet_TurbVars[iMarker] = new su2double*[nVertex[iMarker]]; - for(unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ - Inlet_TurbVars[iMarker][iVertex] = new su2double[nVar]; - Inlet_TurbVars[iMarker][iVertex][0] = kine_Inf; - Inlet_TurbVars[iMarker][iVertex][1] = omega_Inf; - } - } + Inlet_TurbVars = new su2double**[nMarker]; + for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) { + Inlet_TurbVars[iMarker] = new su2double*[nVertex[iMarker]]; + for(unsigned long iVertex=0; iVertex < nVertex[iMarker]; iVertex++){ + Inlet_TurbVars[iMarker][iVertex] = new su2double[nVar]; + Inlet_TurbVars[iMarker][iVertex][0] = kine_Inf; + Inlet_TurbVars[iMarker][iVertex][1] = omega_Inf; + } + } /*--- The turbulence models are always solved implicitly, so set the implicit flag in case we have periodic BCs. ---*/ @@ -271,8 +240,6 @@ CTurbSSTSolver::CTurbSSTSolver(CGeometry *geometry, CConfig *config, unsigned sh CTurbSSTSolver::~CTurbSSTSolver(void) { - if (constants != NULL) delete [] constants; - unsigned long iMarker, iVertex; unsigned short iVar; @@ -301,23 +268,14 @@ CTurbSSTSolver::~CTurbSSTSolver(void) { } -void CTurbSSTSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { - - unsigned long iPoint; - - bool limiter_turb = (config->GetKind_SlopeLimit_Turb() != NO_LIMITER) && (config->GetInnerIter() <= config->GetLimiterIter()); - +void CTurbSSTSolver::Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, + unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output) { - for (iPoint = 0; iPoint < nPoint; iPoint ++) { - - /*--- Initialize the residual vector ---*/ - - LinSysRes.SetBlock_Zero(iPoint); - - } - - /*--- Initialize the Jacobian matrices ---*/ + const bool limiter_turb = (config->GetKind_SlopeLimit_Turb() != NO_LIMITER) && + (config->GetInnerIter() <= config->GetLimiterIter()); + /*--- Clear residual and system matrix. ---*/ + LinSysRes.SetValZero(); Jacobian.SetValZero(); /*--- Upwind second order reconstruction and gradients ---*/ @@ -330,19 +288,23 @@ void CTurbSSTSolver::Preprocessing(CGeometry *geometry, CSolver **solver_contain if (config->GetKind_Gradient_Method_Recon() == WEIGHTED_LEAST_SQUARES) SetSolution_Gradient_LS(geometry, config, true); } - if (config->GetKind_Gradient_Method() == GREEN_GAUSS) SetSolution_Gradient_GG(geometry, config); - if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) SetSolution_Gradient_LS(geometry, config); + + if (config->GetKind_Gradient_Method() == GREEN_GAUSS) + SetSolution_Gradient_GG(geometry, config); + + if (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES) + SetSolution_Gradient_LS(geometry, config); if (limiter_turb) SetSolution_Limiter(geometry, config); } -void CTurbSSTSolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh) { - su2double rho = 0.0, mu = 0.0, dist, omega, kine, F2, muT, zeta; - su2double a1 = constants[7]; - unsigned long iPoint; +void CTurbSSTSolver::Postprocessing(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iMesh) { + + const su2double a1 = constants[7]; - /*--- Compute mean flow and turbulence gradients ---*/ + /*--- Compute turbulence gradients. ---*/ if (config->GetKind_Gradient_Method() == GREEN_GAUSS) { SetSolution_Gradient_GG(geometry, config); @@ -351,54 +313,63 @@ void CTurbSSTSolver::Postprocessing(CGeometry *geometry, CSolver **solver_contai SetSolution_Gradient_LS(geometry, config); } - for (iPoint = 0; iPoint < nPoint; iPoint ++) { + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPoint; iPoint ++) { /*--- Compute blending functions and cross diffusion ---*/ - rho = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); - mu = solver_container[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); + su2double rho = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); + su2double mu = solver_container[FLOW_SOL]->GetNodes()->GetLaminarViscosity(iPoint); - dist = geometry->node[iPoint]->GetWall_Distance(); + su2double dist = geometry->node[iPoint]->GetWall_Distance(); - su2double *Vorticity = solver_container[FLOW_SOL]->GetNodes()->GetVorticity(iPoint); + const su2double *Vorticity = solver_container[FLOW_SOL]->GetNodes()->GetVorticity(iPoint); su2double VorticityMag = sqrt(Vorticity[0]*Vorticity[0] + Vorticity[1]*Vorticity[1] + Vorticity[2]*Vorticity[2]); - nodes->SetBlendingFunc(iPoint,mu, dist, rho); + nodes->SetBlendingFunc(iPoint, mu, dist, rho); - F2 = nodes->GetF2blending(iPoint); + su2double F2 = nodes->GetF2blending(iPoint); /*--- Compute the eddy viscosity ---*/ - kine = nodes->GetSolution(iPoint,0); - omega = nodes->GetSolution(iPoint,1); - zeta = min(1.0/omega, a1/(VorticityMag*F2)); - muT = max(rho*kine*zeta,0.0); + su2double kine = nodes->GetSolution(iPoint,0); + su2double omega = nodes->GetSolution(iPoint,1); + su2double zeta = min(1.0/omega, a1/(VorticityMag*F2)); + su2double muT = max(rho*kine*zeta,0.0); + nodes->SetmuT(iPoint,muT); } } -void CTurbSSTSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CNumerics *second_numerics, CConfig *config, unsigned short iMesh) { +void CTurbSSTSolver::Source_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { - unsigned long iPoint; + CVariable* flowNodes = solver_container[FLOW_SOL]->GetNodes(); + + /*--- Pick one numerics object per thread. ---*/ + CNumerics* numerics = numerics_container[SOURCE_FIRST_TERM + omp_get_thread_num()*MAX_TERMS]; + + /*--- Loop over all points. ---*/ - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + SU2_OMP_FOR_DYN(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Conservative variables w/o reconstruction ---*/ - numerics->SetPrimitive(solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(iPoint), NULL); + numerics->SetPrimitive(flowNodes->GetPrimitive(iPoint), nullptr); /*--- Gradient of the primitive and conservative variables ---*/ - numerics->SetPrimVarGradient(solver_container[FLOW_SOL]->GetNodes()->GetGradient_Primitive(iPoint), NULL); + numerics->SetPrimVarGradient(flowNodes->GetGradient_Primitive(iPoint), nullptr); /*--- Turbulent variables w/o reconstruction, and its gradient ---*/ - numerics->SetTurbVar(nodes->GetSolution(iPoint), NULL); - numerics->SetTurbVarGradient(nodes->GetGradient(iPoint), NULL); + numerics->SetTurbVar(nodes->GetSolution(iPoint), nullptr); + numerics->SetTurbVarGradient(nodes->GetGradient(iPoint), nullptr); /*--- Set volume ---*/ @@ -418,9 +389,9 @@ void CTurbSSTSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta /*--- Set vorticity and strain rate magnitude ---*/ - numerics->SetVorticity(solver_container[FLOW_SOL]->GetNodes()->GetVorticity(iPoint), NULL); + numerics->SetVorticity(flowNodes->GetVorticity(iPoint), nullptr); - numerics->SetStrainMag(solver_container[FLOW_SOL]->GetNodes()->GetStrainMag(iPoint), 0.0); + numerics->SetStrainMag(flowNodes->GetStrainMag(iPoint), 0.0); /*--- Cross diffusion ---*/ @@ -428,12 +399,12 @@ void CTurbSSTSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta /*--- Compute the source term ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, NULL, config); + auto residual = numerics->ComputeResidual(config); /*--- Subtract residual and the Jacobian ---*/ - LinSysRes.SubtractBlock(iPoint, Residual); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.SubtractBlock(iPoint, residual); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } @@ -441,10 +412,10 @@ void CTurbSSTSolver::Source_Residual(CGeometry *geometry, CSolver **solver_conta void CTurbSSTSolver::Source_Template(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short iMesh) { - } -void CTurbSSTSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CTurbSSTSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned long iPoint, jPoint, iVertex, total_index; unsigned short iDim, iVar; @@ -460,8 +431,8 @@ void CTurbSSTSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_cont jPoint = geometry->vertex[val_marker][iVertex]->GetNormal_Neighbor(); distance = 0.0; for (iDim = 0; iDim < nDim; iDim++) { - distance += (geometry->node[iPoint]->GetCoord(iDim) - geometry->node[jPoint]->GetCoord(iDim))* - (geometry->node[iPoint]->GetCoord(iDim) - geometry->node[jPoint]->GetCoord(iDim)); + distance += pow(geometry->node[iPoint]->GetCoord(iDim)- + geometry->node[jPoint]->GetCoord(iDim), 2); } distance = sqrt(distance); @@ -491,8 +462,8 @@ void CTurbSSTSolver::BC_HeatFlux_Wall(CGeometry *geometry, CSolver **solver_cont } -void CTurbSSTSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, - unsigned short val_marker) { +void CTurbSSTSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned long iPoint, jPoint, iVertex, total_index; unsigned short iDim, iVar; @@ -539,7 +510,8 @@ void CTurbSSTSolver::BC_Isothermal_Wall(CGeometry *geometry, CSolver **solver_co } -void CTurbSSTSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CTurbSSTSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned long iPoint, iVertex; su2double *Normal, *V_infty, *V_domain; @@ -589,12 +561,12 @@ void CTurbSSTSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_containe /*--- Compute residuals and Jacobians ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Add residuals and Jacobians ---*/ - LinSysRes.AddBlock(iPoint, Residual); - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.AddBlock(iPoint, residual); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); } } @@ -603,8 +575,8 @@ void CTurbSSTSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_containe } -void CTurbSSTSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, - unsigned short val_marker) { +void CTurbSSTSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iVar, iDim; unsigned long iVertex, iPoint; @@ -664,12 +636,12 @@ void CTurbSSTSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, C /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -691,12 +663,12 @@ void CTurbSSTSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, C // // /*--- Compute residual, and Jacobians ---*/ // - // visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + // auto residual = visc_numerics->ComputeResidual(config); // // /*--- Subtract residual, and update Jacobians ---*/ // - // LinSysRes.SubtractBlock(iPoint, Residual); - // Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + // LinSysRes.SubtractBlock(iPoint, residual); + // Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } @@ -708,7 +680,8 @@ void CTurbSSTSolver::BC_Inlet(CGeometry *geometry, CSolver **solver_container, C } -void CTurbSSTSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { +void CTurbSSTSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned long iPoint, iVertex; unsigned short iVar, iDim; @@ -762,12 +735,12 @@ void CTurbSSTSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto residual = conv_numerics->ComputeResidual(config); + LinSysRes.AddBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); // /*--- Viscous contribution, commented out because serious convergence problems ---*/ // @@ -789,12 +762,12 @@ void CTurbSSTSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, // // /*--- Compute residual, and Jacobians ---*/ // -// visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); +// auto residual = visc_numerics->ComputeResidual(config); // // /*--- Subtract residual, and update Jacobians ---*/ // -// LinSysRes.SubtractBlock(iPoint, Residual); -// Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); +// LinSysRes.SubtractBlock(iPoint, residual); +// Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } } @@ -805,8 +778,8 @@ void CTurbSSTSolver::BC_Outlet(CGeometry *geometry, CSolver **solver_container, } -void CTurbSSTSolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, - unsigned short val_marker) { +void CTurbSSTSolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iVar, iSpan, iDim; unsigned long oldVertex, iPoint, Point_Normal, iVertex; @@ -871,11 +844,11 @@ void CTurbSSTSolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_ geometry->node[iPoint]->GetGridVel()); /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto conv_residual = conv_numerics->ComputeResidual(config); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.AddBlock(iPoint, conv_residual); + Jacobian.AddBlock2Diag(iPoint, conv_residual.jacobian_i); /*--- Viscous contribution ---*/ visc_numerics->SetCoord(geometry->node[iPoint]->GetCoord(), geometry->node[Point_Normal]->GetCoord()); @@ -892,11 +865,11 @@ void CTurbSSTSolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_ visc_numerics->SetF1blending(nodes->GetF1blending(iPoint), nodes->GetF1blending(iPoint)); /*--- Compute residual, and Jacobians ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto visc_residual = visc_numerics->ComputeResidual(config); /*--- Subtract residual, and update Jacobians ---*/ - LinSysRes.SubtractBlock(iPoint, Residual); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.SubtractBlock(iPoint, visc_residual); + Jacobian.SubtractBlock2Diag(iPoint, visc_residual.jacobian_i); } } @@ -906,8 +879,8 @@ void CTurbSSTSolver::BC_Inlet_MixingPlane(CGeometry *geometry, CSolver **solver_ } -void CTurbSSTSolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, - unsigned short val_marker) { +void CTurbSSTSolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, + CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) { unsigned short iVar, iSpan, iDim; unsigned long oldVertex, iPoint, Point_Normal, iVertex; @@ -993,14 +966,14 @@ void CTurbSSTSolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_contai if (dynamic_grid) conv_numerics->SetGridVel(geometry->node[iPoint]->GetGridVel(), - geometry->node[iPoint]->GetGridVel()); + geometry->node[iPoint]->GetGridVel()); /*--- Compute the residual using an upwind scheme ---*/ - conv_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); - LinSysRes.AddBlock(iPoint, Residual); + auto conv_residual = conv_numerics->ComputeResidual(config); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.AddBlock(iPoint, conv_residual); + Jacobian.AddBlock2Diag(iPoint, conv_residual.jacobian_i); /*--- Viscous contribution ---*/ visc_numerics->SetCoord(geometry->node[iPoint]->GetCoord(), geometry->node[Point_Normal]->GetCoord()); @@ -1017,11 +990,11 @@ void CTurbSSTSolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_contai visc_numerics->SetF1blending(nodes->GetF1blending(iPoint), nodes->GetF1blending(iPoint)); /*--- Compute residual, and Jacobians ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto visc_residual = visc_numerics->ComputeResidual(config); /*--- Subtract residual, and update Jacobians ---*/ - LinSysRes.SubtractBlock(iPoint, Residual); - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + LinSysRes.SubtractBlock(iPoint, visc_residual); + Jacobian.SubtractBlock2Diag(iPoint, visc_residual.jacobian_i); } } @@ -1032,18 +1005,16 @@ void CTurbSSTSolver::BC_Inlet_Turbo(CGeometry *geometry, CSolver **solver_contai } - void CTurbSSTSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, - CNumerics *visc_numerics, CConfig *config){ + CNumerics *visc_numerics, CConfig *config){ unsigned long iVertex, jVertex, iPoint, Point_Normal = 0; - unsigned short iDim, iVar, iMarker; + unsigned short iDim, iVar, jVar, iMarker; unsigned short nPrimVar = solver_container[FLOW_SOL]->GetnPrimVar(); su2double *Normal = new su2double[nDim]; su2double *PrimVar_i = new su2double[nPrimVar]; su2double *PrimVar_j = new su2double[nPrimVar]; - su2double *tmp_residual = new su2double[nVar]; unsigned long nDonorVertex; su2double weight; @@ -1063,8 +1034,11 @@ void CTurbSSTSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_co /*--- Initialize Residual, this will serve to accumulate the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) + 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 ---*/ @@ -1102,19 +1076,22 @@ void CTurbSSTSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_co if (dynamic_grid) conv_numerics->SetGridVel(geometry->node[iPoint]->GetGridVel(), geometry->node[iPoint]->GetGridVel()); - conv_numerics->ComputeResidual(tmp_residual, Jacobian_i, Jacobian_j, config); + auto residual = conv_numerics->ComputeResidual(config); /*--- Accumulate the residuals to compute the average ---*/ - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] += weight*tmp_residual[iVar]; + 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); - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + Jacobian.AddBlock2Diag(iPoint, Jacobian_i); /*--- Set the normal vector and the coordinates ---*/ @@ -1133,13 +1110,13 @@ void CTurbSSTSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_co /*--- Compute and update residual ---*/ - visc_numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = visc_numerics->ComputeResidual(config); - LinSysRes.SubtractBlock(iPoint, Residual); + LinSysRes.SubtractBlock(iPoint, residual); /*--- Jacobian contribution for implicit integration ---*/ - Jacobian.SubtractBlock(iPoint, iPoint, Jacobian_i); + Jacobian.SubtractBlock2Diag(iPoint, residual.jacobian_i); } } @@ -1148,7 +1125,6 @@ void CTurbSSTSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_co /*--- Free locally allocated memory ---*/ - delete [] tmp_residual; delete [] Normal; delete [] PrimVar_i; delete [] PrimVar_j; diff --git a/SU2_CFD/src/solvers/CTurbSolver.cpp b/SU2_CFD/src/solvers/CTurbSolver.cpp index e843451486ac..82f27c6de917 100644 --- a/SU2_CFD/src/solvers/CTurbSolver.cpp +++ b/SU2_CFD/src/solvers/CTurbSolver.cpp @@ -27,30 +27,17 @@ #include "../../include/solvers/CTurbSolver.hpp" +#include "../../../Common/include/omp_structure.hpp" -CTurbSolver::CTurbSolver(void) : CSolver() { - - FlowPrimVar_i = NULL; - FlowPrimVar_j = NULL; - lowerlimit = NULL; - upperlimit = NULL; - nVertex = NULL; - nMarker = 0; - Inlet_TurbVars = NULL; - snode = nullptr; -} +CTurbSolver::CTurbSolver(void) : CSolver() { } CTurbSolver::CTurbSolver(CGeometry* geometry, CConfig *config) : CSolver() { Gamma = config->GetGamma(); Gamma_Minus_One = Gamma - 1.0; - FlowPrimVar_i = NULL; - FlowPrimVar_j = NULL; - lowerlimit = NULL; - upperlimit = NULL; - nMarker = config->GetnMarker_All(); + nMarker = config->GetnMarker_All(); /*--- Store the number of vertices on each marker for deallocation later ---*/ nVertex = new unsigned long[nMarker]; @@ -60,13 +47,33 @@ CTurbSolver::CTurbSolver(CGeometry* geometry, CConfig *config) : CSolver() { /* 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(); +#ifdef HAVE_OMP + /*--- Get the edge coloring. ---*/ + + const auto& coloring = geometry->GetEdgeColoring(); + + if (!coloring.empty()) { + auto nColor = coloring.getOuterSize(); + EdgeColoring.resize(nColor); + + for(auto iColor = 0ul; iColor < nColor; ++iColor) { + EdgeColoring.emplace_back(coloring.innerIdx(iColor), coloring.getNumNonZeros(iColor)); + } + } + ColorGroupSize = geometry->GetEdgeColorGroupSize(); + + nPoint = geometry->GetnPoint(); + omp_chunk_size = computeStaticChunkSize(nPoint, omp_get_max_threads(), OMP_MAX_SIZE); +#else + EdgeColoring[0] = DummyGridColor<>(geometry->GetnEdge()); +#endif } CTurbSolver::~CTurbSolver(void) { - if (Inlet_TurbVars != NULL) { + if (Inlet_TurbVars != nullptr) { for (unsigned short iMarker = 0; iMarker < nMarker; iMarker++) { - if (Inlet_TurbVars[iMarker] != NULL) { + if (Inlet_TurbVars[iMarker] != nullptr) { for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) { delete [] Inlet_TurbVars[iMarker][iVertex]; } @@ -76,84 +83,102 @@ CTurbSolver::~CTurbSolver(void) { delete [] Inlet_TurbVars; } - if (FlowPrimVar_i != NULL) delete [] FlowPrimVar_i; - if (FlowPrimVar_j != NULL) delete [] FlowPrimVar_j; - if (lowerlimit != NULL) delete [] lowerlimit; - if (upperlimit != NULL) delete [] upperlimit; - - if (nodes != nullptr) delete nodes; + delete nodes; } -void CTurbSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config, unsigned short iMesh) { +void CTurbSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_container, + CNumerics **numerics_container, CConfig *config, unsigned short iMesh) { - su2double *Turb_i, *Turb_j, *Limiter_i = NULL, *Limiter_j = NULL, *V_i, *V_j, **Gradient_i, **Gradient_j, Project_Grad_i, Project_Grad_j; - unsigned long iEdge, iPoint, jPoint; - unsigned short iDim, iVar; + const bool muscl = config->GetMUSCL_Turb(); + const bool limiter = (config->GetKind_SlopeLimit_Turb() != NO_LIMITER); - bool muscl = config->GetMUSCL_Turb(); - bool limiter = (config->GetKind_SlopeLimit_Turb() != NO_LIMITER); + CVariable* flowNodes = solver_container[FLOW_SOL]->GetNodes(); - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { + /*--- Pick one numerics object per thread. ---*/ + CNumerics* numerics = numerics_container[CONV_TERM + omp_get_thread_num()*MAX_TERMS]; + + /*--- Static arrays of MUSCL-reconstructed flow primitives and turbulence variables (thread safety). ---*/ + su2double solution_i[MAXNVAR] = {0.0}, flowPrimVar_i[MAXNVARFLOW] = {0.0}; + su2double solution_j[MAXNVAR] = {0.0}, flowPrimVar_j[MAXNVARFLOW] = {0.0}; + + /*--- Loop over edge colors. ---*/ + for (auto color : EdgeColoring) + { + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) + for(auto k = 0ul; k < color.size; ++k) { + + auto iEdge = color.indices[k]; + + unsigned short iDim, iVar; /*--- Points in edge and normal vectors ---*/ - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); + auto iPoint = geometry->edge[iEdge]->GetNode(0); + auto jPoint = geometry->edge[iEdge]->GetNode(1); + numerics->SetNormal(geometry->edge[iEdge]->GetNormal()); /*--- Primitive variables w/o reconstruction ---*/ - V_i = solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(iPoint); - V_j = solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(jPoint); + auto V_i = flowNodes->GetPrimitive(iPoint); + auto V_j = flowNodes->GetPrimitive(jPoint); numerics->SetPrimitive(V_i, V_j); /*--- Turbulent variables w/o reconstruction ---*/ - Turb_i = nodes->GetSolution(iPoint); - Turb_j = nodes->GetSolution(jPoint); + auto Turb_i = nodes->GetSolution(iPoint); + auto Turb_j = nodes->GetSolution(jPoint); numerics->SetTurbVar(Turb_i, Turb_j); /*--- Grid Movement ---*/ if (dynamic_grid) - numerics->SetGridVel(geometry->node[iPoint]->GetGridVel(), geometry->node[jPoint]->GetGridVel()); + numerics->SetGridVel(geometry->node[iPoint]->GetGridVel(), + geometry->node[jPoint]->GetGridVel()); if (muscl) { + su2double *Limiter_i = nullptr, *Limiter_j = nullptr; + + auto Coord_i = geometry->node[iPoint]->GetCoord(); + auto Coord_j = geometry->node[jPoint]->GetCoord(); + + /*--- Reconstruct flow variables. ---*/ + su2double Vector_ij[MAXNDIM] = {0.0}; for (iDim = 0; iDim < nDim; iDim++) { - Vector_i[iDim] = 0.5*(geometry->node[jPoint]->GetCoord(iDim) - geometry->node[iPoint]->GetCoord(iDim)); - Vector_j[iDim] = 0.5*(geometry->node[iPoint]->GetCoord(iDim) - geometry->node[jPoint]->GetCoord(iDim)); + Vector_ij[iDim] = 0.5*(Coord_j[iDim] - Coord_i[iDim]); } /*--- Mean flow primitive variables using gradient reconstruction and limiters ---*/ - Gradient_i = solver_container[FLOW_SOL]->GetNodes()->GetGradient_Reconstruction(iPoint); - Gradient_j = solver_container[FLOW_SOL]->GetNodes()->GetGradient_Reconstruction(jPoint); + auto Gradient_i = flowNodes->GetGradient_Reconstruction(iPoint); + auto Gradient_j = flowNodes->GetGradient_Reconstruction(jPoint); if (limiter) { - Limiter_i = solver_container[FLOW_SOL]->GetNodes()->GetLimiter_Primitive(iPoint); - Limiter_j = solver_container[FLOW_SOL]->GetNodes()->GetLimiter_Primitive(jPoint); + Limiter_i = flowNodes->GetLimiter_Primitive(iPoint); + Limiter_j = flowNodes->GetLimiter_Primitive(jPoint); } for (iVar = 0; iVar < solver_container[FLOW_SOL]->GetnPrimVarGrad(); iVar++) { - Project_Grad_i = 0.0; Project_Grad_j = 0.0; + su2double Project_Grad_i = 0.0, Project_Grad_j = 0.0; for (iDim = 0; iDim < nDim; iDim++) { - Project_Grad_i += Vector_i[iDim]*Gradient_i[iVar][iDim]; - Project_Grad_j += Vector_j[iDim]*Gradient_j[iVar][iDim]; + Project_Grad_i += Vector_ij[iDim]*Gradient_i[iVar][iDim]; + Project_Grad_j -= Vector_ij[iDim]*Gradient_j[iVar][iDim]; } if (limiter) { - FlowPrimVar_i[iVar] = V_i[iVar] + Limiter_i[iVar]*Project_Grad_i; - FlowPrimVar_j[iVar] = V_j[iVar] + Limiter_j[iVar]*Project_Grad_j; + flowPrimVar_i[iVar] = V_i[iVar] + Limiter_i[iVar]*Project_Grad_i; + flowPrimVar_j[iVar] = V_j[iVar] + Limiter_j[iVar]*Project_Grad_j; } else { - FlowPrimVar_i[iVar] = V_i[iVar] + Project_Grad_i; - FlowPrimVar_j[iVar] = V_j[iVar] + Project_Grad_j; + flowPrimVar_i[iVar] = V_i[iVar] + Project_Grad_i; + flowPrimVar_j[iVar] = V_j[iVar] + Project_Grad_j; } } - numerics->SetPrimitive(FlowPrimVar_i, FlowPrimVar_j); + numerics->SetPrimitive(flowPrimVar_i, flowPrimVar_j); - /*--- Turbulent variables using gradient reconstruction and limiters ---*/ + /*--- Reconstruct turbulence variables. ---*/ Gradient_i = nodes->GetGradient_Reconstruction(iPoint); Gradient_j = nodes->GetGradient_Reconstruction(jPoint); @@ -164,50 +189,62 @@ void CTurbSolver::Upwind_Residual(CGeometry *geometry, CSolver **solver_containe } for (iVar = 0; iVar < nVar; iVar++) { - Project_Grad_i = 0.0; Project_Grad_j = 0.0; + su2double Project_Grad_i = 0.0, Project_Grad_j = 0.0; for (iDim = 0; iDim < nDim; iDim++) { - Project_Grad_i += Vector_i[iDim]*Gradient_i[iVar][iDim]; - Project_Grad_j += Vector_j[iDim]*Gradient_j[iVar][iDim]; + Project_Grad_i += Vector_ij[iDim]*Gradient_i[iVar][iDim]; + Project_Grad_j -= Vector_ij[iDim]*Gradient_j[iVar][iDim]; } if (limiter) { - Solution_i[iVar] = Turb_i[iVar] + Limiter_i[iVar]*Project_Grad_i; - Solution_j[iVar] = Turb_j[iVar] + Limiter_j[iVar]*Project_Grad_j; + solution_i[iVar] = Turb_i[iVar] + Limiter_i[iVar]*Project_Grad_i; + solution_j[iVar] = Turb_j[iVar] + Limiter_j[iVar]*Project_Grad_j; } else { - Solution_i[iVar] = Turb_i[iVar] + Project_Grad_i; - Solution_j[iVar] = Turb_j[iVar] + Project_Grad_j; + solution_i[iVar] = Turb_i[iVar] + Project_Grad_i; + solution_j[iVar] = Turb_j[iVar] + Project_Grad_j; } } - numerics->SetTurbVar(Solution_i, Solution_j); + numerics->SetTurbVar(solution_i, solution_j); } /*--- Add and subtract residual ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = numerics->ComputeResidual(config); - LinSysRes.AddBlock(iPoint, Residual); - LinSysRes.SubtractBlock(jPoint, Residual); + LinSysRes.AddBlock(iPoint, residual); + LinSysRes.SubtractBlock(jPoint, residual); /*--- Implicit part ---*/ - Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, Jacobian_i, Jacobian_j); + Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, residual.jacobian_i, residual.jacobian_j); } + } // end color loop } -void CTurbSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, +void CTurbSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_container, CNumerics **numerics_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep) { - unsigned long iEdge, iPoint, jPoint; - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { + CVariable* flowNodes = solver_container[FLOW_SOL]->GetNodes(); + + /*--- Pick one numerics object per thread. ---*/ + CNumerics* numerics = numerics_container[VISC_TERM + omp_get_thread_num()*MAX_TERMS]; + + /*--- Loop over edge colors. ---*/ + for (auto color : EdgeColoring) + { + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) + for(auto k = 0ul; k < color.size; ++k) { + + auto iEdge = color.indices[k]; /*--- Points in edge ---*/ - iPoint = geometry->edge[iEdge]->GetNode(0); - jPoint = geometry->edge[iEdge]->GetNode(1); + auto iPoint = geometry->edge[iEdge]->GetNode(0); + auto jPoint = geometry->edge[iEdge]->GetNode(1); /*--- Points coordinates, and normal vector ---*/ @@ -217,30 +254,34 @@ void CTurbSolver::Viscous_Residual(CGeometry *geometry, CSolver **solver_contain /*--- Conservative variables w/o reconstruction ---*/ - numerics->SetPrimitive(solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(iPoint), - solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(jPoint)); + numerics->SetPrimitive(flowNodes->GetPrimitive(iPoint), + flowNodes->GetPrimitive(jPoint)); /*--- Turbulent variables w/o reconstruction, and its gradients ---*/ - numerics->SetTurbVar(nodes->GetSolution(iPoint), nodes->GetSolution(jPoint)); - numerics->SetTurbVarGradient(nodes->GetGradient(iPoint), nodes->GetGradient(jPoint)); + numerics->SetTurbVar(nodes->GetSolution(iPoint), + nodes->GetSolution(jPoint)); + numerics->SetTurbVarGradient(nodes->GetGradient(iPoint), + nodes->GetGradient(jPoint)); /*--- Menter's first blending function (only SST)---*/ if ((config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST)) - numerics->SetF1blending(nodes->GetF1blending(iPoint), nodes->GetF1blending(jPoint)); + numerics->SetF1blending(nodes->GetF1blending(iPoint), + nodes->GetF1blending(jPoint)); /*--- Compute residual, and Jacobians ---*/ - numerics->ComputeResidual(Residual, Jacobian_i, Jacobian_j, config); + auto residual = numerics->ComputeResidual(config); /*--- Add and subtract residual, and update Jacobians ---*/ - LinSysRes.SubtractBlock(iPoint, Residual); - LinSysRes.AddBlock(jPoint, Residual); + LinSysRes.SubtractBlock(iPoint, residual); + LinSysRes.AddBlock(jPoint, residual); - Jacobian.UpdateBlocks(iEdge, iPoint, jPoint, Jacobian_i, Jacobian_j); + Jacobian.UpdateBlocksSub(iEdge, iPoint, jPoint, residual.jacobian_i, residual.jacobian_j); } + } // end color loop } @@ -339,64 +380,84 @@ void CTurbSolver::BC_Periodic(CGeometry *geometry, CSolver **solver_container, void CTurbSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) { - unsigned short iVar; - unsigned long iPoint, total_index; - su2double Delta, Vol, density_old = 0.0, density = 0.0; + const bool adjoint = config->GetContinuous_Adjoint() || (config->GetDiscrete_Adjoint() && config->GetFrozen_Visc_Disc()); + const bool compressible = (config->GetKind_Regime() == COMPRESSIBLE); - bool adjoint = config->GetContinuous_Adjoint() || (config->GetDiscrete_Adjoint() && config->GetFrozen_Visc_Disc()); - bool compressible = (config->GetKind_Regime() == COMPRESSIBLE); - bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); + CVariable* flowNodes = solver_container[FLOW_SOL]->GetNodes(); - /*--- Set maximum residual to zero ---*/ + /*--- Set shared residual variables to 0 and declare + * local ones for current thread to work on. ---*/ - for (iVar = 0; iVar < nVar; iVar++) { + 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}; /*--- Build implicit system ---*/ - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + SU2_OMP(for schedule(static,omp_chunk_size) nowait) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Read the volume ---*/ - Vol = (geometry->node[iPoint]->GetVolume() + - geometry->node[iPoint]->GetPeriodicVolume()); + su2double Vol = (geometry->node[iPoint]->GetVolume() + geometry->node[iPoint]->GetPeriodicVolume()); /*--- Modify matrix diagonal to assure diagonal dominance ---*/ - Delta = Vol / ((nodes->GetLocalCFL(iPoint)/solver_container[FLOW_SOL]->GetNodes()->GetLocalCFL(iPoint))*solver_container[FLOW_SOL]->GetNodes()->GetDelta_Time(iPoint)); + su2double Delta = Vol / ((nodes->GetLocalCFL(iPoint)/flowNodes->GetLocalCFL(iPoint))*flowNodes->GetDelta_Time(iPoint)); Jacobian.AddVal2Diag(iPoint, Delta); /*--- Right hand side of the system (-Residual) and initial guess (x = 0) ---*/ - for (iVar = 0; iVar < nVar; iVar++) { - total_index = iPoint*nVar+iVar; - LinSysRes[total_index] = - LinSysRes[total_index]; + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + unsigned long total_index = iPoint*nVar + iVar; + LinSysRes[total_index] = -LinSysRes[total_index]; LinSysSol[total_index] = 0.0; - AddRes_RMS(iVar, LinSysRes[total_index]*LinSysRes[total_index]); - AddRes_Max(iVar, fabs(LinSysRes[total_index]), geometry->node[iPoint]->GetGlobalIndex(), geometry->node[iPoint]->GetCoord()); + + su2double Res = fabs(LinSysRes[total_index]); + resRMS[iVar] += Res*Res; + if (Res > resMax[iVar]) { + resMax[iVar] = Res; + idxMax[iVar] = iPoint; + coordMax[iVar] = geometry->node[iPoint]->GetCoord(); + } } } + SU2_OMP_CRITICAL + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + AddRes_RMS(iVar, resRMS[iVar]); + AddRes_Max(iVar, resMax[iVar], geometry->node[idxMax[iVar]]->GetGlobalIndex(), coordMax[iVar]); + } /*--- Initialize residual and solution at the ghost points ---*/ - for (iPoint = nPointDomain; iPoint < nPoint; iPoint++) { - for (iVar = 0; iVar < nVar; iVar++) { - total_index = iPoint*nVar + iVar; - LinSysRes[total_index] = 0.0; - LinSysSol[total_index] = 0.0; - } + SU2_OMP(sections) + { + SU2_OMP(section) + for (unsigned long iPoint = nPointDomain; iPoint < nPoint; iPoint++) + LinSysRes.SetBlock_Zero(iPoint); + + SU2_OMP(section) + for (unsigned long iPoint = nPointDomain; iPoint < nPoint; iPoint++) + LinSysSol.SetBlock_Zero(iPoint); } /*--- Solve or smooth the linear system ---*/ - unsigned long IterLinSol = System.Solve(Jacobian, LinSysRes, LinSysSol, geometry, config); - SetIterLinSolver(IterLinSol); - - /*--- Store the value of the residual. ---*/ + auto iter = System.Solve(Jacobian, LinSysRes, LinSysSol, geometry, config); + SU2_OMP_MASTER + { + SetIterLinSolver(iter); + SetResLinSolver(System.GetResidual()); + } + SU2_OMP_BARRIER - SetResLinSolver(System.GetResidual()); ComputeUnderRelaxationFactor(solver_container, config); @@ -410,49 +471,51 @@ void CTurbSolver::ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_ case SA: case SA_E: case SA_COMP: case SA_E_COMP: case SA_NEG: - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { nodes->AddSolution(iPoint, 0, nodes->GetUnderRelaxation(iPoint)*LinSysSol[iPoint]); } - break; case SST: case SST_SUST: - for (iPoint = 0; iPoint < nPointDomain; iPoint++) { + SU2_OMP_FOR_STAT(omp_chunk_size) + for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { - if (compressible) { - density_old = solver_container[FLOW_SOL]->GetNodes()->GetSolution_Old(iPoint,0); - density = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); - } - if (incompressible) { - density_old = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); - density = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); - } + su2double density = flowNodes->GetDensity(iPoint); + su2double density_old = density; - for (iVar = 0; iVar < nVar; iVar++) { - nodes->AddConservativeSolution(iPoint, iVar, nodes->GetUnderRelaxation(iPoint)*LinSysSol[iPoint*nVar+iVar], density, density_old, lowerlimit[iVar], upperlimit[iVar]); - } + if (compressible) + density_old = flowNodes->GetSolution_Old(iPoint,0); + for (unsigned short iVar = 0; iVar < nVar; iVar++) { + nodes->AddConservativeSolution(iPoint, iVar, + nodes->GetUnderRelaxation(iPoint)*LinSysSol(iPoint,iVar), + density, density_old, lowerlimit[iVar], upperlimit[iVar]); + } } - break; } } - for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { - InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT); - CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT); - } + SU2_OMP_MASTER + { + for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) { + InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT); + CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT); + } - /*--- MPI solution ---*/ + /*--- MPI solution ---*/ - InitiateComms(geometry, config, SOLUTION_EDDY); - CompleteComms(geometry, config, SOLUTION_EDDY); + InitiateComms(geometry, config, SOLUTION_EDDY); + CompleteComms(geometry, config, SOLUTION_EDDY); - /*--- Compute the root mean square residual ---*/ + /*--- Compute the root mean square residual ---*/ - SetResidual_RMS(geometry, config); + SetResidual_RMS(geometry, config); + } + SU2_OMP_BARRIER } @@ -474,6 +537,7 @@ void CTurbSolver::ComputeUnderRelaxationFactor(CSolver **solver_container, CConf const su2double allowableDecrease = -0.99; const su2double allowableIncrease = 0.99; + SU2_OMP_FOR_STAT(omp_chunk_size) for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) { localUnderRelaxation = 1.0; @@ -515,24 +579,26 @@ void CTurbSolver::ComputeUnderRelaxationFactor(CSolver **solver_container, CConf void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iRKStep, unsigned short iMesh, unsigned short RunTime_EqSystem) { - /*--- Local variables ---*/ + const bool sst_model = (config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST); + const bool implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); + const bool first_order = (config->GetTime_Marching() == DT_STEPPING_1ST); + const bool second_order = (config->GetTime_Marching() == DT_STEPPING_2ND); + const bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - unsigned short iVar, jVar, iMarker, iDim; - unsigned long iPoint, jPoint, iEdge, iVertex; - - su2double *U_time_nM1, *U_time_n, *U_time_nP1; - su2double Volume_nM1, Volume_nP1, TimeStep; - su2double Density_nM1, Density_n, Density_nP1; - su2double *Normal = NULL, *GridVel_i = NULL, *GridVel_j = NULL, Residual_GCL; + /*--- Store the physical time step ---*/ - bool implicit = (config->GetKind_TimeIntScheme_Turb() == EULER_IMPLICIT); + const su2double TimeStep = config->GetDelta_UnstTimeND(); - bool incompressible = (config->GetKind_Regime() == INCOMPRESSIBLE); - unsigned short turbModel = config->GetKind_Turb_Model(); + /*--- Local variables ---*/ - /*--- Store the physical time step ---*/ + unsigned short iVar, iMarker, iDim; + unsigned long iPoint, jPoint, iVertex; - TimeStep = config->GetDelta_UnstTimeND(); + const su2double *U_time_nM1 = nullptr, *U_time_n = nullptr, *U_time_nP1 = nullptr; + su2double Volume_nM1, Volume_nP1; + su2double Density_nM1, Density_n, Density_nP1; + const su2double *Normal = nullptr, *GridVel_i = nullptr, *GridVel_j = nullptr; + su2double Residual_GCL; /*--- Compute the dual time-stepping source term for static meshes ---*/ @@ -540,6 +606,7 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con /*--- Loop over all nodes (excluding halos) ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Retrieve the solution at time levels n-1, n, and n+1. Note that @@ -558,7 +625,7 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con /*--- Compute the dual time-stepping source term based on the chosen time discretization scheme (1st- or 2nd-order).---*/ - if ((turbModel == SST) || (turbModel == SST_SUST)) { + if (sst_model) { /*--- If this is the SST model, we need to multiply by the density in order to get the conservative variables ---*/ @@ -578,38 +645,30 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con } for (iVar = 0; iVar < nVar; iVar++) { - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Residual[iVar] = ( Density_nP1*U_time_nP1[iVar] - Density_n*U_time_n[iVar])*Volume_nP1 / TimeStep; - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Residual[iVar] = ( 3.0*Density_nP1*U_time_nP1[iVar] - 4.0*Density_n*U_time_n[iVar] - +1.0*Density_nM1*U_time_nM1[iVar])*Volume_nP1 / (2.0*TimeStep); + if (first_order) + LinSysRes(iPoint,iVar) += ( Density_nP1*U_time_nP1[iVar] - Density_n*U_time_n[iVar])*Volume_nP1 / TimeStep; + if (second_order) + LinSysRes(iPoint,iVar) += ( 3.0*Density_nP1*U_time_nP1[iVar] - 4.0*Density_n*U_time_n[iVar] + +1.0*Density_nM1*U_time_nM1[iVar] ) * Volume_nP1/(2.0*TimeStep); } } else { for (iVar = 0; iVar < nVar; iVar++) { - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Residual[iVar] = (U_time_nP1[iVar] - U_time_n[iVar])*Volume_nP1 / TimeStep; - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Residual[iVar] = ( 3.0*U_time_nP1[iVar] - 4.0*U_time_n[iVar] - +1.0*U_time_nM1[iVar])*Volume_nP1 / (2.0*TimeStep); + if (first_order) + LinSysRes(iPoint,iVar) += (U_time_nP1[iVar] - U_time_n[iVar])*Volume_nP1 / TimeStep; + if (second_order) + LinSysRes(iPoint,iVar) += ( 3.0*U_time_nP1[iVar] - 4.0*U_time_n[iVar] + +1.0*U_time_nM1[iVar] ) * Volume_nP1/(2.0*TimeStep); } } - /*--- Store the residual and compute the Jacobian contribution due - to the dual time source term. ---*/ - - LinSysRes.AddBlock(iPoint, Residual); + /*--- Compute the Jacobian contribution due to the dual time source term. ---*/ if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] = 0.0; - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Jacobian_i[iVar][iVar] = Volume_nP1 / TimeStep; - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Jacobian_i[iVar][iVar] = (Volume_nP1*3.0)/(2.0*TimeStep); - } - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (first_order) Jacobian.AddVal2Diag(iPoint, Volume_nP1/TimeStep); + if (second_order) Jacobian.AddVal2Diag(iPoint, (Volume_nP1*3.0)/(2.0*TimeStep)); } + } } else { @@ -622,7 +681,14 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con we will loop over the edges and boundaries to compute the GCL component of the dual time source term that depends on grid velocities. ---*/ - for (iEdge = 0; iEdge < geometry->GetnEdge(); iEdge++) { + /*--- Loop over edge colors. ---*/ + for (auto color : EdgeColoring) + { + /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/ + SU2_OMP_FOR_DYN(roundUpDiv(OMP_MIN_SIZE, ColorGroupSize)*ColorGroupSize) + for(auto k = 0ul; k < color.size; ++k) { + + auto iEdge = color.indices[k]; /*--- Get indices for nodes i & j plus the face normal ---*/ @@ -648,16 +714,19 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con /*--- Multiply by density at node i for the SST model ---*/ - if ((turbModel == SST) || (turbModel == SST_SUST)) { - if (incompressible) Density_n = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); // Temporary fix - else Density_n = solver_container[FLOW_SOL]->GetNodes()->GetSolution_time_n(iPoint,0); + if (sst_model) { + if (incompressible) + Density_n = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); // Temporary fix + else + Density_n = solver_container[FLOW_SOL]->GetNodes()->GetSolution_time_n(iPoint,0); + for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] = Density_n*U_time_n[iVar]*Residual_GCL; - } else { + LinSysRes(iPoint,iVar) += Density_n*U_time_n[iVar]*Residual_GCL; + } + else { for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] = U_time_n[iVar]*Residual_GCL; + LinSysRes(iPoint,iVar) += U_time_n[iVar]*Residual_GCL; } - LinSysRes.AddBlock(iPoint, Residual); /*--- Compute the GCL component of the source term for node j ---*/ @@ -665,66 +734,76 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con /*--- Multiply by density at node j for the SST model ---*/ - if ((turbModel == SST) || (turbModel == SST_SUST)) { - if (incompressible) Density_n = solver_container[FLOW_SOL]->GetNodes()->GetDensity(jPoint); // Temporary fix - else Density_n = solver_container[FLOW_SOL]->GetNodes()->GetSolution_time_n(jPoint)[0]; + if (sst_model) { + if (incompressible) + Density_n = solver_container[FLOW_SOL]->GetNodes()->GetDensity(jPoint); // Temporary fix + else + Density_n = solver_container[FLOW_SOL]->GetNodes()->GetSolution_time_n(jPoint)[0]; + for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] = Density_n*U_time_n[iVar]*Residual_GCL; - } else { + LinSysRes(jPoint,iVar) -= Density_n*U_time_n[iVar]*Residual_GCL; + } + else { for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] = U_time_n[iVar]*Residual_GCL; + LinSysRes(jPoint,iVar) -= U_time_n[iVar]*Residual_GCL; } - LinSysRes.SubtractBlock(jPoint, Residual); } + } // end color loop /*--- Loop over the boundary edges ---*/ for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) { if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) && (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) { - for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - /*--- Get the index for node i plus the boundary face normal ---*/ + SU2_OMP_FOR_STAT(OMP_MIN_SIZE) + for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) { - iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); - Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); + /*--- Get the index for node i plus the boundary face normal ---*/ - /*--- Grid velocities stored at boundary node i ---*/ + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + Normal = geometry->vertex[iMarker][iVertex]->GetNormal(); - GridVel_i = geometry->node[iPoint]->GetGridVel(); + /*--- Grid velocities stored at boundary node i ---*/ - /*--- Compute the GCL term by dotting the grid velocity with the face - normal. The normal is negated to match the boundary convention. ---*/ + GridVel_i = geometry->node[iPoint]->GetGridVel(); - Residual_GCL = 0.0; - for (iDim = 0; iDim < nDim; iDim++) - Residual_GCL -= 0.5*(GridVel_i[iDim]+GridVel_i[iDim])*Normal[iDim]; + /*--- Compute the GCL term by dotting the grid velocity with the face + normal. The normal is negated to match the boundary convention. ---*/ - /*--- Compute the GCL component of the source term for node i ---*/ + Residual_GCL = 0.0; + for (iDim = 0; iDim < nDim; iDim++) + Residual_GCL -= 0.5*(GridVel_i[iDim]+GridVel_i[iDim])*Normal[iDim]; - U_time_n = nodes->GetSolution_time_n(iPoint); + /*--- Compute the GCL component of the source term for node i ---*/ - /*--- Multiply by density at node i for the SST model ---*/ + U_time_n = nodes->GetSolution_time_n(iPoint); - if ((turbModel == SST) || (turbModel == SST_SUST)) { - if (incompressible) Density_n = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); // Temporary fix - else Density_n = solver_container[FLOW_SOL]->GetNodes()->GetSolution_time_n(iPoint,0); - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] = Density_n*U_time_n[iVar]*Residual_GCL; - } else { - for (iVar = 0; iVar < nVar; iVar++) - Residual[iVar] = U_time_n[iVar]*Residual_GCL; - } - LinSysRes.AddBlock(iPoint, Residual); + /*--- Multiply by density at node i for the SST model ---*/ - } + if (sst_model) { + if (incompressible) + Density_n = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); // Temporary fix + else + Density_n = solver_container[FLOW_SOL]->GetNodes()->GetSolution_time_n(iPoint,0); + + for (iVar = 0; iVar < nVar; iVar++) + LinSysRes(iPoint,iVar) += Density_n*U_time_n[iVar]*Residual_GCL; + } + else { + for (iVar = 0; iVar < nVar; iVar++) + LinSysRes(iPoint,iVar) += U_time_n[iVar]*Residual_GCL; + } + + } } } /*--- Loop over all nodes (excluding halos) to compute the remainder of the dual time-stepping source term. ---*/ + SU2_OMP_FOR_STAT(omp_chunk_size) for (iPoint = 0; iPoint < nPointDomain; iPoint++) { /*--- Retrieve the solution at time levels n-1, n, and n+1. Note that @@ -746,11 +825,11 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con introduction of the GCL term above, the remainder of the source residual due to the time discretization has a new form.---*/ - if ((turbModel == SST) || (turbModel == SST_SUST)) { + if (sst_model) { /*--- If this is the SST model, we need to multiply by the density in order to get the conservative variables ---*/ - if (incompressible){ + if (incompressible) { /*--- This is temporary and only valid for constant-density problems: density could also be temperature dependent, but as it is not a part of the solution vector it's neither stored for previous time steps @@ -759,47 +838,39 @@ void CTurbSolver::SetResidual_DualTime(CGeometry *geometry, CSolver **solver_con Density_n = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); Density_nP1 = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint); } - else{ + else { Density_nM1 = solver_container[FLOW_SOL]->GetNodes()->GetSolution_time_n1(iPoint)[0]; Density_n = solver_container[FLOW_SOL]->GetNodes()->GetSolution_time_n(iPoint,0); Density_nP1 = solver_container[FLOW_SOL]->GetNodes()->GetSolution(iPoint,0); } for (iVar = 0; iVar < nVar; iVar++) { - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Residual[iVar] = (Density_nP1*U_time_nP1[iVar] - Density_n*U_time_n[iVar])*(Volume_nP1/TimeStep); - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Residual[iVar] = (Density_nP1*U_time_nP1[iVar] - Density_n*U_time_n[iVar])*(3.0*Volume_nP1/(2.0*TimeStep)) - + (Density_nM1*U_time_nM1[iVar] - Density_n*U_time_n[iVar])*(Volume_nM1/(2.0*TimeStep)); + if (first_order) + LinSysRes(iPoint,iVar) += (Density_nP1*U_time_nP1[iVar] - Density_n*U_time_n[iVar])*(Volume_nP1/TimeStep); + if (second_order) + LinSysRes(iPoint,iVar) += (Density_nP1*U_time_nP1[iVar] - Density_n*U_time_n[iVar])*(3.0*Volume_nP1/(2.0*TimeStep)) + + (Density_nM1*U_time_nM1[iVar] - Density_n*U_time_n[iVar])*(Volume_nM1/(2.0*TimeStep)); } } else { for (iVar = 0; iVar < nVar; iVar++) { - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Residual[iVar] = (U_time_nP1[iVar] - U_time_n[iVar])*(Volume_nP1/TimeStep); - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Residual[iVar] = (U_time_nP1[iVar] - U_time_n[iVar])*(3.0*Volume_nP1/(2.0*TimeStep)) - + (U_time_nM1[iVar] - U_time_n[iVar])*(Volume_nM1/(2.0*TimeStep)); + if (first_order) + LinSysRes(iPoint,iVar) += (U_time_nP1[iVar] - U_time_n[iVar])*(Volume_nP1/TimeStep); + if (second_order) + LinSysRes(iPoint,iVar) += (U_time_nP1[iVar] - U_time_n[iVar])*(3.0*Volume_nP1/(2.0*TimeStep)) + + (U_time_nM1[iVar] - U_time_n[iVar])*(Volume_nM1/(2.0*TimeStep)); } } - /*--- Store the residual and compute the Jacobian contribution due - to the dual time source term. ---*/ - - LinSysRes.AddBlock(iPoint, Residual); + /*--- Compute the Jacobian contribution due to the dual time source term. ---*/ if (implicit) { - for (iVar = 0; iVar < nVar; iVar++) { - for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] = 0.0; - if (config->GetTime_Marching() == DT_STEPPING_1ST) - Jacobian_i[iVar][iVar] = Volume_nP1/TimeStep; - if (config->GetTime_Marching() == DT_STEPPING_2ND) - Jacobian_i[iVar][iVar] = (3.0*Volume_nP1)/(2.0*TimeStep); - } - Jacobian.AddBlock(iPoint, iPoint, Jacobian_i); + if (first_order) Jacobian.AddVal2Diag(iPoint, Volume_nP1/TimeStep); + if (second_order) Jacobian.AddVal2Diag(iPoint, (Volume_nP1*3.0)/(2.0*TimeStep)); } } - } + + } // end dynamic grid } @@ -824,7 +895,6 @@ void CTurbSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig * int counter = 0; long iPoint_Local = 0; unsigned long iPoint_Global = 0; unsigned long iPoint_Global_Local = 0; - unsigned short rbuf_NotMatching = 0, sbuf_NotMatching = 0; /*--- Skip flow variables ---*/ @@ -874,14 +944,7 @@ void CTurbSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig * /*--- Detect a wrong solution file ---*/ - if (iPoint_Global_Local < nPointDomain) { sbuf_NotMatching = 1; } - -#ifndef HAVE_MPI - rbuf_NotMatching = sbuf_NotMatching; -#else - SU2_MPI::Allreduce(&sbuf_NotMatching, &rbuf_NotMatching, 1, MPI_UNSIGNED_SHORT, MPI_SUM, MPI_COMM_WORLD); -#endif - if (rbuf_NotMatching != 0) { + if (iPoint_Global_Local < nPointDomain) { SU2_MPI::Error(string("The solution file ") + restart_filename + string(" doesn't match with the mesh file!\n") + string("It could be empty lines at the end of the file."), CURRENT_FUNCTION); } @@ -918,8 +981,7 @@ void CTurbSolver::LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig * /*--- Delete the class memory that is used to load the restart. ---*/ - if (Restart_Vars != NULL) delete [] Restart_Vars; - if (Restart_Data != NULL) delete [] Restart_Data; - Restart_Vars = NULL; Restart_Data = NULL; + delete [] Restart_Vars; Restart_Vars = nullptr; + delete [] Restart_Data; Restart_Data = nullptr; } diff --git a/SU2_CFD/src/variables/CFEABoundVariable.cpp b/SU2_CFD/src/variables/CFEABoundVariable.cpp index c1aec8e7d992..55c02be64430 100644 --- a/SU2_CFD/src/variables/CFEABoundVariable.cpp +++ b/SU2_CFD/src/variables/CFEABoundVariable.cpp @@ -68,6 +68,8 @@ void CFEABoundVariable::Set_SurfaceLoad_Res_n() { Residual_Ext_Surf_n = Residual void CFEABoundVariable::Clear_FlowTraction() { FlowTraction.setConstant(0.0); } +void CFEABoundVariable::Clear_SurfaceLoad_Res() { Residual_Ext_Surf.setConstant(0.0); } + void CFEABoundVariable::RegisterFlowTraction() { if (!fsi_analysis) return; for (unsigned long iVertex = 0; iVertex < FlowTraction.rows(); iVertex++) diff --git a/SU2_CFD/src/variables/CNSVariable.cpp b/SU2_CFD/src/variables/CNSVariable.cpp index 29f34c94316e..c6b02d574ca6 100644 --- a/SU2_CFD/src/variables/CNSVariable.cpp +++ b/SU2_CFD/src/variables/CNSVariable.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -25,8 +25,8 @@ * License along with SU2. If not, see . */ - #include "../../include/variables/CNSVariable.hpp" +#include "../../../Common/include/omp_structure.hpp" CNSVariable::CNSVariable(su2double density, const su2double *velocity, su2double energy, @@ -46,6 +46,7 @@ CNSVariable::CNSVariable(su2double density, const su2double *velocity, su2double bool CNSVariable::SetVorticity_StrainMag() { + SU2_OMP_FOR_STAT(256) for (unsigned long iPoint = 0; iPoint < nPoint; ++iPoint) { /*--- Vorticity ---*/ diff --git a/SU2_CFD/src/variables/CTurbSAVariable.cpp b/SU2_CFD/src/variables/CTurbSAVariable.cpp index fa099ceb6759..eb48ec0a6ad1 100644 --- a/SU2_CFD/src/variables/CTurbSAVariable.cpp +++ b/SU2_CFD/src/variables/CTurbSAVariable.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -29,8 +29,9 @@ #include "../../include/variables/CTurbSAVariable.hpp" -CTurbSAVariable::CTurbSAVariable(su2double val_nu_tilde, su2double val_muT, unsigned long npoint, unsigned long ndim, unsigned long nvar, - CConfig *config) : CTurbVariable(npoint, ndim, nvar, config) { +CTurbSAVariable::CTurbSAVariable(su2double val_nu_tilde, su2double val_muT, unsigned long npoint, + unsigned long ndim, unsigned long nvar, CConfig *config) : + CTurbVariable(npoint, ndim, nvar, config) { Solution_Old = Solution = val_nu_tilde; @@ -50,8 +51,8 @@ CTurbSAVariable::CTurbSAVariable(su2double val_nu_tilde, su2double val_muT, unsi Vortex_Tilting.resize(nPoint); } -void CTurbSAVariable::SetVortex_Tilting(unsigned long iPoint, su2double **PrimGrad_Flow, - su2double* Vorticity, su2double LaminarViscosity) { +void CTurbSAVariable::SetVortex_Tilting(unsigned long iPoint, const su2double* const* PrimGrad_Flow, + const su2double* Vorticity, su2double LaminarViscosity) { su2double Strain[3][3] = {{0,0,0}, {0,0,0}, {0,0,0}}, Omega, StrainDotVort[3], numVecVort[3]; su2double numerator, trace0, trace1, denominator; diff --git a/SU2_CFD/src/variables/CVariable.cpp b/SU2_CFD/src/variables/CVariable.cpp index e3aeae191f7d..66e093b1143c 100644 --- a/SU2_CFD/src/variables/CVariable.cpp +++ b/SU2_CFD/src/variables/CVariable.cpp @@ -6,7 +6,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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -27,6 +27,7 @@ #include "../../include/variables/CVariable.hpp" +#include "../../../Common/include/omp_structure.hpp" CVariable::CVariable(unsigned long npoint, unsigned long nvar, CConfig *config) { @@ -79,23 +80,39 @@ CVariable::CVariable(unsigned long npoint, unsigned long ndim, unsigned long nva Solution_BGS_k.resize(nPoint,nVar) = su2double(0.0); } -void CVariable::Set_OldSolution() { Solution_Old = Solution; } - -void CVariable::Set_Solution() { Solution = Solution_Old; } +void CVariable::Set_OldSolution() { + assert(Solution_Old.size() == Solution.size()); + parallelCopy(Solution.size(), Solution.data(), Solution_Old.data()); +} -void CVariable::Set_Solution_time_n() { Solution_time_n = Solution; } +void CVariable::Set_Solution() { + assert(Solution.size() == Solution_Old.size()); + parallelCopy(Solution_Old.size(), Solution_Old.data(), Solution.data()); +} -void CVariable::Set_Solution_time_n1() { Solution_time_n1 = Solution_time_n; } +void CVariable::Set_Solution_time_n() { + assert(Solution_time_n.size() == Solution.size()); + parallelCopy(Solution.size(), Solution.data(), Solution_time_n.data()); +} -void CVariable::Set_BGSSolution_k() { Solution_BGS_k = Solution; } +void CVariable::Set_Solution_time_n1() { + assert(Solution_time_n1.size() == Solution_time_n.size()); + parallelCopy(Solution_time_n.size(), Solution_time_n.data(), Solution_time_n1.data()); +} -void CVariable::Restore_BGSSolution_k() { Solution = Solution_BGS_k; } +void CVariable::Set_BGSSolution_k() { + assert(Solution_BGS_k.size() == Solution.size()); + parallelCopy(Solution.size(), Solution.data(), Solution_BGS_k.data()); +} -void CVariable::SetResidualSumZero() { Residual_Sum.setConstant(0.0); } +void CVariable::Restore_BGSSolution_k() { + assert(Solution.size() == Solution_BGS_k.size()); + parallelCopy(Solution_BGS_k.size(), Solution_BGS_k.data(), Solution.data()); +} -void CVariable::SetUnd_LaplZero() { Undivided_Laplacian.setConstant(0.0); } +void CVariable::SetUnd_LaplZero() { parallelSet(Undivided_Laplacian.size(), 0.0, Undivided_Laplacian.data()); } -void CVariable::SetExternalZero() { External.setConstant(0.0); } +void CVariable::SetExternalZero() { parallelSet(External.size(), 0.0, External.data()); } void CVariable::RegisterSolution(bool input, bool push_index) { for (unsigned long iPoint = 0; iPoint < nPoint; ++iPoint) { diff --git a/SU2_DEF/src/meson.build b/SU2_DEF/src/meson.build index 2c0b5d456e38..531b19fb1184 100644 --- a/SU2_DEF/src/meson.build +++ b/SU2_DEF/src/meson.build @@ -5,7 +5,7 @@ if get_option('enable-normal') 'solvers/CBaselineSolver.cpp', 'CMarkerProfileReaderFVM.cpp', 'output/COutput.cpp', - 'output/tools/CWindowingTools.cpp', + 'output/tools/CWindowingTools.cpp', 'output/CMeshOutput.cpp', 'output/output_structure_legacy.cpp', 'variables/CBaselineVariable.cpp', @@ -26,7 +26,8 @@ if get_option('enable-normal') 'output/filewriter/CSU2BinaryFileWriter.cpp', 'output/filewriter/CParaviewXMLFileWriter.cpp', 'output/filewriter/CParaviewVTMFileWriter.cpp', - 'output/filewriter/CSU2MeshFileWriter.cpp']) + 'output/filewriter/CSU2MeshFileWriter.cpp', + 'limiters/CLimiterDetails.cpp']) su2_def = executable('SU2_DEF', su2_def_src, diff --git a/SU2_DOT/include/SU2_DOT.hpp b/SU2_DOT/include/SU2_DOT.hpp index 2a1947ccc8b1..73a46ef311cb 100644 --- a/SU2_DOT/include/SU2_DOT.hpp +++ b/SU2_DOT/include/SU2_DOT.hpp @@ -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-2019, SU2 Contributors (cf. AUTHORS.md) @@ -29,13 +29,13 @@ #pragma once -#include "../../Common/include/mpi_structure.hpp" -#include "../../Common/include/omp_structure.hpp" - #define ENABLE_MAPS #include "../../Common/include/CConfig.hpp" #undef ENABLE_MAPS +#include "../../Common/include/mpi_structure.hpp" +#include "../../Common/include/omp_structure.hpp" + #include #include #include diff --git a/SU2_DOT/src/meson.build b/SU2_DOT/src/meson.build index 083a1c3ed569..d286c0f45b37 100644 --- a/SU2_DOT/src/meson.build +++ b/SU2_DOT/src/meson.build @@ -25,7 +25,8 @@ if get_option('enable-normal') 'output/filewriter/CParaviewXMLFileWriter.cpp', 'output/filewriter/CParaviewVTMFileWriter.cpp', 'variables/CBaselineVariable.cpp', - 'variables/CVariable.cpp']) + 'variables/CVariable.cpp', + 'limiters/CLimiterDetails.cpp']) su2_dot = executable('SU2_DOT', su2_dot_src, @@ -63,7 +64,8 @@ if get_option('enable-autodiff') 'output/filewriter/CParaviewXMLFileWriter.cpp', 'output/filewriter/CParaviewVTMFileWriter.cpp', 'variables/CBaselineVariable.cpp', - 'variables/CVariable.cpp']) + 'variables/CVariable.cpp', + 'limiters/CLimiterDetails.cpp']) su2_dot_ad = executable('SU2_DOT_AD', su2_dot_src_ad, diff --git a/SU2_SOL/src/meson.build b/SU2_SOL/src/meson.build index d43b59837803..c782fb6f2169 100644 --- a/SU2_SOL/src/meson.build +++ b/SU2_SOL/src/meson.build @@ -6,7 +6,7 @@ if get_option('enable-normal') 'CMarkerProfileReaderFVM.cpp', 'output/COutput.cpp', 'output/output_structure_legacy.cpp', - 'output/tools/CWindowingTools.cpp', + 'output/tools/CWindowingTools.cpp', 'output/CBaselineOutput.cpp', 'output/filewriter/CParallelDataSorter.cpp', 'output/filewriter/CParallelFileWriter.cpp', @@ -26,8 +26,8 @@ if get_option('enable-normal') 'output/filewriter/CParaviewXMLFileWriter.cpp', 'output/filewriter/CParaviewVTMFileWriter.cpp', 'variables/CBaselineVariable.cpp', - 'variables/CVariable.cpp']) - + 'variables/CVariable.cpp', + 'limiters/CLimiterDetails.cpp']) su2_sol = executable('SU2_SOL', su2_sol_src, diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index 837cbe696f48..52e4741097e0 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -91,7 +91,7 @@ def main(): fixedCL_naca0012.cfg_dir = "fixed_cl/naca0012" fixedCL_naca0012.cfg_file = "inv_NACA0012.cfg" fixedCL_naca0012.test_iter = 10 - fixedCL_naca0012.test_vals = [-12.137680, -6.705671, 0.300000, 0.019470] #last 4 columns + fixedCL_naca0012.test_vals = [-12.137879, -6.705803, 0.300000, 0.019470] #last 4 columns fixedCL_naca0012.su2_exec = "parallel_computation.py -f" fixedCL_naca0012.timeout = 1600 fixedCL_naca0012.tol = 0.00001 @@ -173,7 +173,7 @@ def main(): poiseuille_profile.cfg_dir = "navierstokes/poiseuille" poiseuille_profile.cfg_file = "profile_poiseuille.cfg" poiseuille_profile.test_iter = 10 - poiseuille_profile.test_vals = [-12.493462, -7.671815, -0.000000, 2.085796] #last 4 columns + poiseuille_profile.test_vals = [-12.493492, -7.671588, -0.000000, 2.085796] #last 4 columns poiseuille_profile.su2_exec = "parallel_computation.py -f" poiseuille_profile.timeout = 1600 poiseuille_profile.tol = 0.00001 @@ -243,7 +243,7 @@ def main(): turb_naca0012_sa.cfg_dir = "rans/naca0012" turb_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" turb_naca0012_sa.test_iter = 10 - turb_naca0012_sa.test_vals = [-12.078482, -16.147828, 1.064326, 0.019770] #last 4 columns + turb_naca0012_sa.test_vals = [-12.078361, -16.147829, 1.064326, 0.019770] #last 4 columns turb_naca0012_sa.su2_exec = "parallel_computation.py -f" turb_naca0012_sa.timeout = 3200 turb_naca0012_sa.tol = 0.00001 @@ -631,7 +631,7 @@ def main(): turb_naca0012_1c.cfg_dir = "rans_uq/naca0012" turb_naca0012_1c.cfg_file = "turb_NACA0012_uq_1c.cfg" turb_naca0012_1c.test_iter = 10 - turb_naca0012_1c.test_vals = [-4.906243, 1.337959, 6.052221, 2.395629] #last 4 columns + turb_naca0012_1c.test_vals = [-4.907889, 1.337608, 6.052866, 2.396063] #last 4 columns turb_naca0012_1c.su2_exec = "parallel_computation.py -f" turb_naca0012_1c.timeout = 1600 turb_naca0012_1c.tol = 0.00001 @@ -642,7 +642,7 @@ def main(): turb_naca0012_2c.cfg_dir = "rans_uq/naca0012" turb_naca0012_2c.cfg_file = "turb_NACA0012_uq_2c.cfg" turb_naca0012_2c.test_iter = 10 - turb_naca0012_2c.test_vals = [-5.230215, 1.262233, 6.052131, 2.395642] #last 4 columns + turb_naca0012_2c.test_vals = [-5.230205, 1.262234, 6.052183, 2.395669] #last 4 columns turb_naca0012_2c.su2_exec = "parallel_computation.py -f" turb_naca0012_2c.timeout = 1600 turb_naca0012_2c.tol = 0.00001 @@ -664,7 +664,7 @@ def main(): turb_naca0012_p1c1.cfg_dir = "rans_uq/naca0012" turb_naca0012_p1c1.cfg_file = "turb_NACA0012_uq_p1c1.cfg" turb_naca0012_p1c1.test_iter = 10 - turb_naca0012_p1c1.test_vals = [-5.007909, 1.310935, 6.054741, 2.397402] #last 4 columns + turb_naca0012_p1c1.test_vals = [-5.008192, 1.310849, 6.054689, 2.397346] #last 4 columns turb_naca0012_p1c1.su2_exec = "parallel_computation.py -f" turb_naca0012_p1c1.timeout = 1600 turb_naca0012_p1c1.tol = 0.00001 @@ -675,7 +675,7 @@ def main(): turb_naca0012_p1c2.cfg_dir = "rans_uq/naca0012" turb_naca0012_p1c2.cfg_file = "turb_NACA0012_uq_p1c2.cfg" turb_naca0012_p1c2.test_iter = 10 - turb_naca0012_p1c2.test_vals = [-5.264043, 1.251313, 6.055013, 2.397532] #last 4 columns + turb_naca0012_p1c2.test_vals = [-5.264112, 1.251274, 6.054818, 2.397393] #last 4 columns turb_naca0012_p1c2.su2_exec = "parallel_computation.py -f" turb_naca0012_p1c2.timeout = 1600 turb_naca0012_p1c2.tol = 0.00001 @@ -911,7 +911,7 @@ def main(): channel_2D.cfg_dir = "sliding_interface/channel_2D" channel_2D.cfg_file = "channel_2D_WA.cfg" channel_2D.test_iter = 2 - channel_2D.test_vals = [2.000000, 0.000000, 0.398157, 0.353079, 0.405679] #last 4 columns + channel_2D.test_vals = [2.000000, 0.000000, 0.397891, 0.352785, 0.405448] #last 4 columns channel_2D.su2_exec = "parallel_computation.py -f" channel_2D.timeout = 100 channel_2D.tol = 0.00001 @@ -924,7 +924,7 @@ def main(): channel_3D.cfg_dir = "sliding_interface/channel_3D" channel_3D.cfg_file = "channel_3D_WA.cfg" channel_3D.test_iter = 2 - channel_3D.test_vals = [2.000000, 0.000000, 0.620137, 0.505221, 0.415605] #last 4 columns + channel_3D.test_vals = [2.000000, 0.000000, 0.620166, 0.505156, 0.415129] #last 4 columns channel_3D.su2_exec = "parallel_computation.py -f" channel_3D.timeout = 1600 channel_3D.tol = 0.00001 @@ -950,7 +950,7 @@ def main(): rotating_cylinders.cfg_dir = "sliding_interface/rotating_cylinders" rotating_cylinders.cfg_file = "rot_cylinders_WA.cfg" rotating_cylinders.test_iter = 3 - rotating_cylinders.test_vals = [3.000000, 0.000000, 0.777044, 1.134689, 1.224326] #last 4 columns + rotating_cylinders.test_vals = [3.000000, 0.000000, 0.777274, 1.134742, 1.224125] #last 4 columns rotating_cylinders.su2_exec = "parallel_computation.py -f" rotating_cylinders.timeout = 1600 rotating_cylinders.tol = 0.00001 @@ -963,7 +963,7 @@ def main(): supersonic_vortex_shedding.cfg_dir = "sliding_interface/supersonic_vortex_shedding" supersonic_vortex_shedding.cfg_file = "sup_vor_shed_WA.cfg" supersonic_vortex_shedding.test_iter = 5 - supersonic_vortex_shedding.test_vals = [5.000000, 0.000000, 1.228298, 1.648277] #last 4 columns + supersonic_vortex_shedding.test_vals = [5.000000, 0.000000, 1.227386, 1.638722] #last 4 columns supersonic_vortex_shedding.su2_exec = "parallel_computation.py -f" supersonic_vortex_shedding.timeout = 1600 supersonic_vortex_shedding.tol = 0.00001 diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index 5c7b744216fc..7debff8fe571 100644 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -101,7 +101,7 @@ def main(): fixedCL_naca0012.cfg_dir = "fixed_cl/naca0012" fixedCL_naca0012.cfg_file = "inv_NACA0012.cfg" fixedCL_naca0012.test_iter = 10 - fixedCL_naca0012.test_vals = [-12.129591, -6.702940, 0.300000, 0.019470] #last 4 columns + fixedCL_naca0012.test_vals = [-12.129044, -6.702294, 0.300000, 0.019470] #last 4 columns fixedCL_naca0012.su2_exec = "SU2_CFD" fixedCL_naca0012.new_output = True fixedCL_naca0012.timeout = 1600 @@ -198,7 +198,7 @@ def main(): poiseuille_profile.cfg_dir = "navierstokes/poiseuille" poiseuille_profile.cfg_file = "profile_poiseuille.cfg" poiseuille_profile.test_iter = 10 - poiseuille_profile.test_vals = [-12.494733, -7.712320, -0.000000, 2.085796] #last 4 columns + poiseuille_profile.test_vals = [-12.494705, -7.711759, -0.000000, 2.085796] #last 4 columns poiseuille_profile.su2_exec = "SU2_CFD" poiseuille_profile.new_output = True poiseuille_profile.timeout = 1600 @@ -281,7 +281,7 @@ def main(): turb_naca0012_sa.cfg_dir = "rans/naca0012" turb_naca0012_sa.cfg_file = "turb_NACA0012_sa.cfg" turb_naca0012_sa.test_iter = 10 - turb_naca0012_sa.test_vals = [-12.075973, -16.146770, 1.064326, 0.019770] #last 4 columns + turb_naca0012_sa.test_vals = [-12.075893, -16.146770, 1.064326, 0.019770] #last 4 columns turb_naca0012_sa.su2_exec = "SU2_CFD" turb_naca0012_sa.new_output = True turb_naca0012_sa.timeout = 3200 @@ -754,7 +754,7 @@ def main(): turb_naca0012_1c.cfg_dir = "rans_uq/naca0012" turb_naca0012_1c.cfg_file = "turb_NACA0012_uq_1c.cfg" turb_naca0012_1c.test_iter = 10 - turb_naca0012_1c.test_vals = [-4.906675, 1.337889, 6.085815, 2.413950] #last 4 columns + turb_naca0012_1c.test_vals = [-4.910211, 1.337024, 6.085849, 2.414025] #last 4 columns turb_naca0012_1c.su2_exec = "SU2_CFD" turb_naca0012_1c.new_output = True turb_naca0012_1c.timeout = 1600 @@ -766,7 +766,7 @@ def main(): turb_naca0012_2c.cfg_dir = "rans_uq/naca0012" turb_naca0012_2c.cfg_file = "turb_NACA0012_uq_2c.cfg" turb_naca0012_2c.test_iter = 10 - turb_naca0012_2c.test_vals = [-5.230275, 1.262205, 6.085899, 2.413590] #last 4 columns + turb_naca0012_2c.test_vals = [-5.230242, 1.262219, 6.085926, 2.413617] #last 4 columns turb_naca0012_2c.su2_exec = "SU2_CFD" turb_naca0012_2c.new_output = True turb_naca0012_2c.timeout = 1600 @@ -790,7 +790,7 @@ def main(): turb_naca0012_p1c1.cfg_dir = "rans_uq/naca0012" turb_naca0012_p1c1.cfg_file = "turb_NACA0012_uq_p1c1.cfg" turb_naca0012_p1c1.test_iter = 10 - turb_naca0012_p1c1.test_vals = [-5.003083, 1.312255, 6.085205, 2.413463] #last 4 columns + turb_naca0012_p1c1.test_vals = [-5.003327, 1.312032, 6.085201, 2.413460] #last 4 columns turb_naca0012_p1c1.su2_exec = "SU2_CFD" turb_naca0012_p1c1.new_output = True turb_naca0012_p1c1.timeout = 1600 @@ -802,7 +802,7 @@ def main(): turb_naca0012_p1c2.cfg_dir = "rans_uq/naca0012" turb_naca0012_p1c2.cfg_file = "turb_NACA0012_uq_p1c2.cfg" turb_naca0012_p1c2.test_iter = 10 - turb_naca0012_p1c2.test_vals = [-5.263968, 1.251341, 6.085723, 2.413449] #last 4 columns + turb_naca0012_p1c2.test_vals = [-5.263992, 1.251332, 6.085705, 2.413434] #last 4 columns turb_naca0012_p1c2.su2_exec = "SU2_CFD" turb_naca0012_p1c2.new_output = True turb_naca0012_p1c2.timeout = 1600 @@ -1056,7 +1056,7 @@ def main(): uniform_flow.cfg_dir = "sliding_interface/uniform_flow" uniform_flow.cfg_file = "uniform_NN.cfg" uniform_flow.test_iter = 2 - uniform_flow.test_vals = [2.000000, 0.000000, -0.205134, -13.254129] #last 4 columns + uniform_flow.test_vals = [2.000000, 0.000000, -0.205134, -13.250256] #last 4 columns uniform_flow.su2_exec = "SU2_CFD" uniform_flow.timeout = 1600 uniform_flow.tol = 0.000001 @@ -1069,7 +1069,7 @@ def main(): channel_2D.cfg_dir = "sliding_interface/channel_2D" channel_2D.cfg_file = "channel_2D_WA.cfg" channel_2D.test_iter = 2 - channel_2D.test_vals = [2.000000, 0.000000, 0.398070, 0.353082, 0.405729] #last 4 columns + channel_2D.test_vals = [2.000000, 0.000000, 0.397985, 0.352786, 0.405475] #last 4 columns channel_2D.su2_exec = "SU2_CFD" channel_2D.timeout = 100 channel_2D.tol = 0.00001 @@ -1082,7 +1082,7 @@ def main(): channel_3D.cfg_dir = "sliding_interface/channel_3D" channel_3D.cfg_file = "channel_3D_WA.cfg" channel_3D.test_iter = 1 - channel_3D.test_vals = [1.000000, 0.000000, 0.661403, 0.769795, 0.696074] #last 5 columns + channel_3D.test_vals = [1.000000, 0.000000, 0.661408, 0.769920, 0.696040] #last 5 columns channel_3D.su2_exec = "SU2_CFD" channel_3D.timeout = 1600 channel_3D.tol = 0.00001 @@ -1108,7 +1108,7 @@ def main(): rotating_cylinders.cfg_dir = "sliding_interface/rotating_cylinders" rotating_cylinders.cfg_file = "rot_cylinders_WA.cfg" rotating_cylinders.test_iter = 3 - rotating_cylinders.test_vals = [3.000000, 0.000000, 0.777044, 1.134679, 1.224316] #last 4 columns + rotating_cylinders.test_vals = [3.000000, 0.000000, 0.777273, 1.134732, 1.224115] #last 4 columns rotating_cylinders.su2_exec = "SU2_CFD" rotating_cylinders.timeout = 1600 rotating_cylinders.tol = 0.00001 @@ -1121,7 +1121,7 @@ def main(): supersonic_vortex_shedding.cfg_dir = "sliding_interface/supersonic_vortex_shedding" supersonic_vortex_shedding.cfg_file = "sup_vor_shed_WA.cfg" supersonic_vortex_shedding.test_iter = 5 - supersonic_vortex_shedding.test_vals = [5.000000, 0.000000, 1.228735, 1.648284] #last 4 columns + supersonic_vortex_shedding.test_vals = [5.000000, 0.000000, 1.227921, 1.638901] #last 4 columns supersonic_vortex_shedding.su2_exec = "SU2_CFD" supersonic_vortex_shedding.timeout = 1600 supersonic_vortex_shedding.tol = 0.00001