diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp index cc99113ae0f2..f8c3bde89bd5 100644 --- a/Common/include/CConfig.hpp +++ b/Common/include/CConfig.hpp @@ -227,6 +227,7 @@ class CConfig { bool Inlet_From_File; /*!< \brief True if the inlet profile is to be loaded from a file. */ string Inlet_Filename; /*!< \brief Filename specifying an inlet profile. */ su2double Inlet_Matching_Tol; /*!< \brief Tolerance used when matching a point to a point from the inlet file. */ + string ActDisk_FileName; /*!< \brief Filename specifying an actuator disk. */ string *Marker_Euler, /*!< \brief Euler wall markers. */ *Marker_FarField, /*!< \brief Far field markers. */ @@ -4709,6 +4710,12 @@ class CConfig { */ string GetInlet_FileName(void) const { return Inlet_Filename; } + /*! + * \brief Get name of the input file for the specified actuator disk. + * \return Name of the input file for the specified actuator disk. + */ + string GetActDisk_FileName(void) const { return ActDisk_FileName; } + /*! * \brief Get the tolerance used for matching two points on a specified inlet * \return Tolerance used for matching a point to a specified inlet diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index d947b6da1af9..597a0886a012 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -1381,7 +1381,8 @@ enum ACTDISK_TYPE { NET_THRUST = 3, /*!< \brief User specifies the Net thrust. */ DRAG_MINUS_THRUST = 4, /*!< \brief User specifies the D-T. */ MASSFLOW = 5, /*!< \brief User specifies the massflow. */ - POWER = 6 /*!< \brief User specifies the power. */ + POWER = 6, /*!< \brief User specifies the power. */ + VARIABLE_LOAD = 7 /*!< \brief User specifies the load distribution. */ }; static const MapType ActDisk_Map = { MakePair("VARIABLES_JUMP", VARIABLES_JUMP) @@ -1390,6 +1391,7 @@ static const MapType ActDisk_Map = { MakePair("DRAG_MINUS_THRUST", DRAG_MINUS_THRUST) MakePair("MASSFLOW", MASSFLOW) MakePair("POWER", POWER) + MakePair("VARIABLE_LOAD", VARIABLE_LOAD) }; /*! diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index ffd40b74bb58..1d50138f570d 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -1403,6 +1403,9 @@ void CConfig::SetConfig_Options() { nMarker_ActDiskInlet, nMarker_ActDiskOutlet, Marker_ActDiskInlet, Marker_ActDiskOutlet, ActDisk_PressJump, ActDisk_TempJump, ActDisk_Omega); + /*!\brief ACTDISK_FILENAME \n DESCRIPTION: Input file for a specified actuator disk (w/ extension) \n DEFAULT: actdiskinput.dat \ingroup Config*/ + addStringOption("ACTDISK_FILENAME", ActDisk_FileName, string("actdiskinput.dat")); + /*!\brief INLET_TYPE \n DESCRIPTION: Inlet boundary type \n OPTIONS: see \link Inlet_Map \endlink \n DEFAULT: TOTAL_CONDITIONS \ingroup Config*/ addEnumOption("INLET_TYPE", Kind_Inlet, Inlet_Map, TOTAL_CONDITIONS); /*!\brief INC_INLET_TYPE \n DESCRIPTION: List of inlet types for incompressible flows. List length must match number of inlet markers. Options: VELOCITY_INLET, PRESSURE_INLET. \ingroup Config*/ @@ -6895,6 +6898,13 @@ void CConfig::SetOutput(unsigned short val_software, unsigned short val_izone) { BoundaryTable.PrintFooter(); } + if (nMarker_ActDiskOutlet != 0) { + if (GetKind_ActDisk() == VARIABLE_LOAD) { + cout << endl << "Actuator disk with variable load." << endl; + cout << "Actuator disk data read from file: " << GetActDisk_FileName() << endl; + } + } + } bool CConfig::TokenizeString(string & str, string & option_name, diff --git a/SU2_CFD/include/solvers/CEulerSolver.hpp b/SU2_CFD/include/solvers/CEulerSolver.hpp index fc177e7e6d6b..8d973b101eec 100644 --- a/SU2_CFD/include/solvers/CEulerSolver.hpp +++ b/SU2_CFD/include/solvers/CEulerSolver.hpp @@ -155,6 +155,17 @@ class CEulerSolver : public CSolver { **Inlet_Ttotal = nullptr, /*!< \brief Value of the Total T. */ ***Inlet_FlowDir = nullptr; /*!< \brief Value of the Flow Direction. */ + su2activevector + ActDisk_R; /*!< \brief Value of the actuator disk Radius. */ + su2activematrix + ActDisk_C, /*!< \brief Value of the actuator disk Center. */ + ActDisk_Axis; /*!< \brief Value of the actuator disk Axis. */ + su2double + **ActDisk_Fa, /*!< \brief Value of the actuator disk Axial Force per Unit Area. */ + **ActDisk_Fx, /*!< \brief Value of the actuator disk X component of the radial and tangential forces per Unit Area resultant. */ + **ActDisk_Fy, /*!< \brief Value of the actuator disk Y component of the radial and tangential forces per Unit Area resultant. */ + **ActDisk_Fz; /*!< \brief Value of the actuator disk Z component of the radial and tangential forces per Unit Area resultant. */ + su2double Total_ComboObj = 0.0, /*!< \brief Total 'combo' objective for all monitored boundaries */ Total_CL_Prev = 0.0, /*!< \brief Total lift coefficient for all the boundaries (fixed lift mode). */ @@ -358,6 +369,16 @@ class CEulerSolver : public CSolver { void SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, bool Output); + /*! + * \brief Read the actuator disk input file for the VARIABLE_LOAD type. + * \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 ReadActDisk_InputFile(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. @@ -775,6 +796,24 @@ class CEulerSolver : public CSolver { unsigned short val_marker, bool val_inlet_surface) final; + /*! + * \brief Impose an actuator disk with variable load boundary condition. + * \param[in] geometry - Geometrical definition of the problem. + * \param[in] solver_container - Container vector with all the solutions. + * \param[in] conv_numerics - Description of the numerical method. + * \param[in] visc_numerics - Description of the numerical method. + * \param[in] config - Definition of the particular problem. + * \param[in] val_marker - Surface marker where the boundary condition is applied. + * \param[in] val_inlet_surface - Boolean for whether val_marker is an inlet + */ + void BC_ActDisk_VariableLoad(CGeometry *geometry, + CSolver **solver_container, + CNumerics *conv_numerics, + CNumerics *visc_numerics, + CConfig *config, + unsigned short val_marker, + bool val_inlet_surface); + /*! * \brief Impose the interface boundary condition using the residual. * \param[in] geometry - Geometrical definition of the problem. @@ -2057,6 +2096,90 @@ class CEulerSolver : public CSolver { DonorGlobalIndex[val_marker][val_vertex] = val_index; } + /*! + * \brief Value of the characteristic global index at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the axial force per unit area. + */ + inline su2double GetActDisk_Fa(unsigned short val_marker, + unsigned long val_vertex) const { + return ActDisk_Fa[val_marker][val_vertex]; + } + + /*! + * \brief Value of the characteristic global index at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the axial force per unit area. + */ + inline void SetActDisk_Fa(unsigned short val_marker, + unsigned long val_vertex, + su2double val_fa) { ActDisk_Fa[val_marker][val_vertex] = val_fa; } + + /*! + * \brief Value of the characteristic global index at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the x component of the radial and tangential forces per unit area resultant. + */ + inline su2double GetActDisk_Fx(unsigned short val_marker, + unsigned long val_vertex) const { + return ActDisk_Fx[val_marker][val_vertex]; + } + + /*! + * \brief Value of the characteristic global index at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the x component of the radial and tangential forces per unit area resultant. + */ + inline void SetActDisk_Fx(unsigned short val_marker, + unsigned long val_vertex, + su2double val_fx) { ActDisk_Fx[val_marker][val_vertex] = val_fx; } + + /*! + * \brief Value of the characteristic global index at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the y component of the radial and tangential forces per unit area resultant. + */ + inline su2double GetActDisk_Fy(unsigned short val_marker, + unsigned long val_vertex) const { + return ActDisk_Fy[val_marker][val_vertex]; + } + + /*! + * \brief Value of the characteristic global index at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the y component of the radial and tangential forces per unit area resultant. + */ + inline void SetActDisk_Fy(unsigned short val_marker, + unsigned long val_vertex, + su2double val_fy) { ActDisk_Fy[val_marker][val_vertex] = val_fy; } + + /*! + * \brief Value of the characteristic global index at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the z component of the radial and tangential forces per unit area resultant. + */ + inline su2double GetActDisk_Fz(unsigned short val_marker, + unsigned long val_vertex) const { + return ActDisk_Fz[val_marker][val_vertex]; + } + + /*! + * \brief Value of the characteristic global index at the boundaries. + * \param[in] val_marker - Surface marker where the coefficient is computed. + * \param[in] val_vertex - Vertex of the marker val_marker where the coefficient is evaluated. + * \return Value of the z component of the radial and tangential forces per unit area resultant. + */ + inline void SetActDisk_Fz(unsigned short val_marker, + unsigned long val_vertex, + su2double val_fz) { ActDisk_Fz[val_marker][val_vertex] = val_fz; } + /*! * \brief Value of the characteristic global index at the boundaries. * \param[in] val_marker - Surface marker where the coefficient is computed. diff --git a/SU2_CFD/src/solvers/CEulerSolver.cpp b/SU2_CFD/src/solvers/CEulerSolver.cpp index fd7202d5e92d..ce5b2eb59b3f 100644 --- a/SU2_CFD/src/solvers/CEulerSolver.cpp +++ b/SU2_CFD/src/solvers/CEulerSolver.cpp @@ -306,6 +306,21 @@ CEulerSolver::CEulerSolver(CGeometry *geometry, CConfig *config, DonorGlobalIndex[iMarker] = new unsigned long [nVertex[iMarker]](); } + /*--- Actuator Disk Radius allocation ---*/ + ActDisk_R.resize(nMarker); + + /*--- Actuator Disk Center allocation ---*/ + ActDisk_C.resize(nMarker, MAXNDIM); + + /*--- Actuator Disk Axis allocation ---*/ + ActDisk_Axis.resize(nMarker, MAXNDIM); + + /*--- Actuator Disk Fa, Fx, Fy and Fz allocations ---*/ + Alloc2D(nMarker, nVertex, ActDisk_Fa); + Alloc2D(nMarker, nVertex, ActDisk_Fx); + Alloc2D(nMarker, nVertex, ActDisk_Fy); + Alloc2D(nMarker, nVertex, ActDisk_Fz); + /*--- Store the value of the Delta P at the Actuator Disk ---*/ Alloc2D(nMarker, nVertex, ActDisk_DeltaP); @@ -619,6 +634,30 @@ CEulerSolver::~CEulerSolver(void) { delete [] DonorGlobalIndex; } + if (ActDisk_Fa != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) + delete [] ActDisk_Fa[iMarker]; + delete [] ActDisk_Fa; + } + + if (ActDisk_Fx != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) + delete [] ActDisk_Fx[iMarker]; + delete [] ActDisk_Fx; + } + + if (ActDisk_Fy != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) + delete [] ActDisk_Fy[iMarker]; + delete [] ActDisk_Fy; + } + + if (ActDisk_Fz != nullptr) { + for (iMarker = 0; iMarker < nMarker; iMarker++) + delete [] ActDisk_Fz[iMarker]; + delete [] ActDisk_Fz; + } + if (ActDisk_DeltaP != nullptr) { for (iMarker = 0; iMarker < nMarker; iMarker++) delete [] ActDisk_DeltaP[iMarker]; @@ -5764,9 +5803,16 @@ void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_con Factor = (0.5*RefDensity*RefArea*RefVel2); Ref = config->GetDensity_Ref() * config->GetVelocity_Ref() * config->GetVelocity_Ref() * 1.0 * 1.0; + /*--- Variable load distribution is in input file. ---*/ + if (Kind_ActDisk == VARIABLE_LOAD) { + if(InnerIter == 0) { + ReadActDisk_InputFile(geometry, solver_container, config, iMesh, Output); + } + } /*--- Delta P and delta T are inputs ---*/ - if (Kind_ActDisk == VARIABLES_JUMP) { + else { + if (Kind_ActDisk == VARIABLES_JUMP) { for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { if ((config->GetMarker_All_KindBC(iMarker) == ACTDISK_INLET) || @@ -6152,7 +6198,7 @@ void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_con } } } - +} /*--- Broadcast some information to the master node ---*/ ActDisk_Info = false; @@ -6170,6 +6216,207 @@ void CEulerSolver::SetActDisk_BCThrust(CGeometry *geometry, CSolver **solver_con } +void CEulerSolver::ReadActDisk_InputFile(CGeometry *geometry, CSolver **solver_container, + CConfig *config, unsigned short iMesh, bool Output) { + /*--- Input file provides force coefficients distributions along disk radius. Initialization + necessary only at initial iteration. ---*/ + + unsigned short iDim, iMarker; + unsigned long iVertex, iPoint; + string Marker_Tag; + int iRow, nRow, iEl; + std::vector rad_v, dCt_v, dCp_v, dCr_v; + su2double r_ = 0.0, r[MAXNDIM] = {0.0}, + AD_Center[MAXNDIM] = {0.0}, AD_Axis[MAXNDIM] = {0.0}, AD_Radius = 0.0, AD_J = 0.0; + std::vector Fa, Ft, Fr; + su2double Fx = 0.0, Fy = 0.0, Fz = 0.0, + Fx_inf = 0.0, Fy_inf = 0.0, Fz_inf = 0.0, Fx_sup = 0.0, Fy_sup = 0.0, Fz_sup = 0.0, h = 0.0; + const su2double *P = nullptr; + + su2double Dens_FreeStream = config->GetDensity_FreeStream(); + const su2double *Vel_FreeStream = config->GetVelocity_FreeStream(); + + /*--- Get the file name that contains the propeller data. ---*/ + string ActDisk_filename = config->GetActDisk_FileName(); + /*--- Loop over the markers. ---*/ + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + if ((config->GetMarker_All_KindBC(iMarker) == ACTDISK_INLET) || + (config->GetMarker_All_KindBC(iMarker) == ACTDISK_OUTLET)) { + + /*--- Get the marker tag of the current BC marker. ---*/ + Marker_Tag = config->GetMarker_All_TagBound(iMarker); + ifstream ActDisk_file; + /*--- Open the file that contains the propeller data. ---*/ + ActDisk_file.open(ActDisk_filename.data(), ios::in); + + /*--- Error message if the propeller data input file fails to open. ---*/ + if (ActDisk_file.fail()) SU2_MPI::Error("Unable to open Actuator Disk Input File", CURRENT_FUNCTION); + + string text_line, text_line_appo, name[2]; + string::size_type position; + + while (getline (ActDisk_file, text_line)) { + /*--- Check if there is the "MARKER_ACTDISK=" string in the current line. If not keep on reading. ---*/ + position = text_line.find ("MARKER_ACTDISK="); + if(position == string::npos){continue;} + text_line.erase (0,15); + /*--- Read the names of the two faces of the actuator disk and assign them to the name[] array. ---*/ + istringstream NameID(text_line); + for (int i = 0; i < 2; i++){ + NameID >> name[i]; + } + + /*--- Check if the propeller data correspond to the actual BC marker. ---*/ + if (Marker_Tag == name[0] || Marker_Tag == name[1]){ + /*--- Read and assign the coordinates of the actuator disk center. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,7); + istringstream C_value(text_line_appo); + for (iDim = 0; iDim < nDim; iDim++){ + C_value >> AD_Center[iDim]; + } + + /*--- Read and assign the components of the actuator disk axis versor pointing backward. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,5); + istringstream axis_value(text_line_appo); + for (iDim = 0; iDim < nDim; iDim++){ + axis_value >> AD_Axis[iDim]; + } + + /*--- Read and assign the value of the actuator disk radius. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,7); + istringstream R_value(text_line_appo); + R_value >> AD_Radius; + + /*--- Read and assign the value of the actuator disk advance ratio. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,10); + istringstream J_value(text_line_appo); + J_value >> AD_J; + + /*--- Read and assign the number of radial stations contained in the propeller data file. ---*/ + getline (ActDisk_file, text_line_appo); + text_line_appo.erase (0,5); + istringstream row_value(text_line_appo); + row_value >> nRow; + + /*--- Assign the vectors dimension. ---*/ + rad_v.resize(nRow); + dCt_v.resize(nRow); + dCp_v.resize(nRow); + dCr_v.resize(nRow); + + Fa.resize(nRow); + Ft.resize(nRow); + Fr.resize(nRow); + + /*--- Read and assign the values of the non-dimensional radius, thrust coefficient, power coefficient + and radial force coefficient. ---*/ + getline (ActDisk_file, text_line_appo); + for (iRow = 0; iRow < nRow; iRow++){ + getline (ActDisk_file, text_line_appo); + istringstream row_val_value(text_line_appo); + row_val_value >> rad_v[iRow] >> dCt_v[iRow] >> dCp_v[iRow] >> dCr_v[iRow]; + } + + /*--- Set the actuator disk radius value, center coordiantes values and axis coordinates values. ---*/ + ActDisk_R(iMarker) = AD_Radius; + for (iDim = 0; iDim < nDim; iDim++){ + ActDisk_C(iMarker, iDim) = AD_Center[iDim]; + ActDisk_Axis(iMarker, iDim) = AD_Axis[iDim]; + } + + /*--- If the first radial station corresponds to the actuator disk center, the radial and tangential forces + per unit area (Fr and Ft) are equal to zero, while the axial force per unit area (Fa) is computed using + a linear interpolation in order to avoid a mathematical singularity at actuator disk center. ---*/ + if (rad_v[0] == 0.0){ + Fa[0] = (((2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER))*((dCt_v[1] - dCt_v[0])/rad_v[1])) / config->GetPressure_Ref(); + Ft[0] = 0.0; + Fr[0] = 0.0; + } + else { + Fa[0] = (dCt_v[0]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER*rad_v[0])) / config->GetPressure_Ref(); + Ft[0] = (dCp_v[0]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + ((AD_J*PI_NUMBER*rad_v[0])*(AD_J*PI_NUMBER*rad_v[0]))) / config->GetPressure_Ref(); + Fr[0] = (dCr_v[0]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER*rad_v[0])) / config->GetPressure_Ref(); + } + + /*--- Loop over the radial stations. Computation of Fa (axial force per unit area), Ft (tangential force per unit area) + and Fr (radial force per unit area). + These equations are not valid if the freestream velocity is equal to zero (hovering condition not enabled yet). ---*/ + for (iEl = 1; iEl < nRow; iEl++){ + Fa[iEl] = (dCt_v[iEl]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER*rad_v[iEl])) / config->GetPressure_Ref(); + Ft[iEl] = (dCp_v[iEl]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + ((AD_J*PI_NUMBER*rad_v[iEl])*(AD_J*PI_NUMBER*rad_v[iEl]))) / config->GetPressure_Ref(); + Fr[iEl] = (dCr_v[iEl]*(2*Dens_FreeStream*pow(Vel_FreeStream[0],2))/ + (pow(AD_J,2)*PI_NUMBER*rad_v[iEl])) / config->GetPressure_Ref(); + } + + /*--- Loop over the marker nodes. ---*/ + for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) { + /*--- Get the coordinates of the current node. ---*/ + iPoint = geometry->vertex[iMarker][iVertex]->GetNode(); + P = geometry->nodes->GetCoord(iPoint); + + /*--- Computation of the radius coordinates for the current node. ---*/ + GeometryToolbox::Distance(nDim, P, AD_Center, r); + + /*--- Computation of the non-dimensional radius for the current node. ---*/ + r_ = GeometryToolbox::Norm(nDim, r) / AD_Radius; + + /*--- Loop over the actuator disk radial stations. ---*/ + for (iEl = 0; iEl < nRow; iEl++){ + /*--- Check if the current node is located between rad_v[iEl] and rad_v[iEl-1]. ---*/ + if (r_ <= rad_v[iEl]){ + /*--- h is the dinstance of the current node from the previous radial element (iEl-1) + divided by the length of the radial element in which the node is contained. ---*/ + h = (r_-rad_v[iEl-1])/(rad_v[iEl]-rad_v[iEl-1]); + /*--- Fx, Fy and Fz are the x, y and z components of the tangential and radial forces + per unit area resultant. ---*/ + if(r_ == 0.0){ + Fx = 0.0; + Fy = 0.0; + Fz = 0.0; + } + /*--- _inf is the value of the previous radial element. _sup is the value of the + following radial element. ---*/ + else{ + Fx_inf = (Ft[iEl-1]+Fr[iEl-1])*(r[0]/(r_*AD_Radius)); + Fy_inf = (Ft[iEl-1]+Fr[iEl-1])*(r[2]/(r_*AD_Radius)); + Fz_inf = -(Ft[iEl-1]+Fr[iEl-1])*(r[1]/(r_*AD_Radius)); + Fx_sup = (Ft[iEl]+Fr[iEl])*(r[0]/(r_*AD_Radius)); + Fy_sup = (Ft[iEl]+Fr[iEl])*(r[2]/(r_*AD_Radius)); + Fz_sup = -(Ft[iEl]+Fr[iEl])*(r[1]/(r_*AD_Radius)); + + /*--- Fx, Fy and Fz at the current node are evaluated using a linear interpolation between + the end vaues of the radial element in which the current node is contained. ---*/ + Fx = Fx_inf + (Fx_sup - Fx_inf)*h; + Fy = Fy_inf + (Fy_sup - Fy_inf)*h; + Fz = Fz_inf + (Fz_sup - Fz_inf)*h; + } + /*--- Set the values of Fa, Fx, Fy and Fz. Fa is evaluated using a linear interpolation. ---*/ + SetActDisk_Fa(iMarker, iVertex, Fa[iEl-1] + (Fa[iEl]-Fa[iEl-1])*h); + SetActDisk_Fx(iMarker, iVertex, Fx); + SetActDisk_Fy(iMarker, iVertex, Fy); + SetActDisk_Fz(iMarker, iVertex, Fz); + + break; + } + } + } + } + } + ActDisk_file.close(); + } + } +} + void CEulerSolver::SetFarfield_AoA(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, bool Output) { @@ -10672,14 +10919,28 @@ void CEulerSolver::BC_NearField_Boundary(CGeometry *geometry, CSolver **solver_c void CEulerSolver::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); + unsigned short Kind_ActDisk = config->GetKind_ActDisk(); + + if(Kind_ActDisk == VARIABLE_LOAD){ + BC_ActDisk_VariableLoad(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker, true); + } + else{ + BC_ActDisk(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker, true); + } } void CEulerSolver::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); + unsigned short Kind_ActDisk = config->GetKind_ActDisk(); + + if(Kind_ActDisk == VARIABLE_LOAD){ + BC_ActDisk_VariableLoad(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker, false); + } + else{ + BC_ActDisk(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker, false); + } } @@ -11097,6 +11358,246 @@ void CEulerSolver::BC_ActDisk(CGeometry *geometry, CSolver **solver_container, C } +void CEulerSolver::BC_ActDisk_VariableLoad(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, + CConfig *config, unsigned short val_marker, bool val_inlet_surface) { + + /*! + * \function BC_ActDisk_VariableLoad + * \brief Actuator disk model with variable load along disk radius. + * \author: E. Saetta, L. Russo, R. Tognaccini (GitHub references EttoreSaetta, lorenzorusso07, rtogna). + * Theoretical and Applied Aerodynamics Research Group (TAARG), University of Naples Federico II. + * \version 7.0.5 “Blackbird” + * First release date : July 1st 2020 + * modified on: + * + * Force coefficients distribution given in an input file. Actuator disk data initialized in function SetActDisk_BCThrust. + * Entropy, acoustic Riemann invariant R+ and tangential velocity extrapolated from upstream flow; + * acoustic Riemann invariant R- is extrapolated from downstream. + * Hovering condition simulation not available yet: freestream velocity must be different than zero. + */ + + unsigned short iDim; + unsigned long iVertex, iPoint, GlobalIndex_donor, GlobalIndex; + su2double Pressure, Velocity[MAXNDIM], + Velocity2, Entropy, Density, Energy, Riemann, Vn, SoundSpeed, Vn_Inlet, + Area, UnitNormal[MAXNDIM] = {0.0}, *V_outlet, *V_domain, *V_inlet; + + su2double Pressure_out, Density_out, + Pressure_in, Density_in; + + su2double C[MAXNDIM], Prop_Axis[MAXNDIM], R, r[MAXNDIM], r_; + su2double Fa, Fx, Fy, Fz; + su2double u_in, v_in, w_in, u_out, v_out, w_out, uJ, vJ, wJ; + su2double Temperature_out, H_in, H_out; + su2double FQ, Q_out, Density_Disk; + su2double SoSextr, Vnextr[MAXNDIM], Vnextr_, RiemannExtr, QdMnorm[MAXNDIM], QdMnorm2, appo2, SoS_out; + const su2double *P = nullptr; + + bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT); + su2double Gas_Constant = config->GetGas_ConstantND(); + bool tkeNeeded = (config->GetKind_Turb_Model() == SST) || (config->GetKind_Turb_Model() == SST_SUST); + bool ratio = (config->GetActDisk_Jump() == RATIO); + + su2double Normal[MAXNDIM]; + + /*--- Get the actuator disk center and axis coordinates for the current marker. ---*/ + for (iDim = 0; iDim < nDim; iDim++){ + C[iDim] = ActDisk_C(val_marker, iDim); + Prop_Axis[iDim] = ActDisk_Axis(val_marker, iDim); + } + + /*--- Get the actuator disk radius for the current marker. ---*/ + R = ActDisk_R(val_marker); + + /*--- Loop over all the vertices on this boundary marker. ---*/ + SU2_OMP_FOR_DYN(OMP_MIN_SIZE) + for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) { + + iPoint = geometry->vertex[val_marker][iVertex]->GetNode(); + GlobalIndex = geometry->nodes->GetGlobalIndex(iPoint); + GlobalIndex_donor = GetDonorGlobalIndex(val_marker, iVertex); + + /*--- Check if the node belongs to the domain (i.e., not a halo node) ---*/ + + if ((geometry->nodes->GetDomain(iPoint)) && + (GlobalIndex != GlobalIndex_donor)) { + + /*--- Normal vector for this vertex (negative for outward convention) ---*/ + + geometry->vertex[val_marker][iVertex]->GetNormal(Normal); + for (iDim = 0; iDim < nDim; iDim++) Normal[iDim] = -Normal[iDim]; + conv_numerics->SetNormal(Normal); + + Area = GeometryToolbox::Norm(nDim, Normal); + for (iDim = 0; iDim < nDim; iDim++) + UnitNormal[iDim] = Normal[iDim]/Area; + + /*--- Current solution at this boundary node. ---*/ + + V_domain = nodes->GetPrimitive(iPoint); + + /*--- Get the values of Fa (axial force per unit area), Fx, Fy and Fz (x, y and z components of the tangential and + radial forces per unit area resultant). ---*/ + Fa = GetActDisk_Fa(val_marker, iVertex); + Fx = GetActDisk_Fx(val_marker, iVertex); + Fy = GetActDisk_Fy(val_marker, iVertex); + Fz = GetActDisk_Fz(val_marker, iVertex); + + /*--- Get the primitive variables and the extrapolated variables. ---*/ + if (val_inlet_surface){ + V_inlet = nodes->GetPrimitive(iPoint); + V_outlet = GetDonorPrimVar(val_marker, iVertex);} + else{ + V_outlet = nodes->GetPrimitive(iPoint); + V_inlet = GetDonorPrimVar(val_marker, iVertex);} + + /*--- u, v and w are the three momentum components. ---*/ + Pressure_out = V_outlet[nDim+1]; + Density_out = V_outlet[nDim+2]; + u_out = V_outlet[1]*V_outlet[nDim+2]; + v_out = V_outlet[2]*V_outlet[nDim+2]; + w_out = V_outlet[3]*V_outlet[nDim+2]; + + Pressure_in = V_inlet[nDim+1]; + Density_in = V_inlet[nDim+2]; + u_in = V_inlet[1]*Density_in; + v_in = V_inlet[2]*Density_in; + w_in = V_inlet[3]*Density_in; + H_in = V_inlet[nDim+3]*Density_in; + + /*--- Density on the disk is computed as an everage value between the inlet and outlet values. ---*/ + Density_Disk = 0.5*(Density_in + Density_out); + + /*--- Computation of the normal momentum flowing through the disk. ---*/ + Q_out = 0.5*((u_in + u_out)*Prop_Axis[0] + (v_in + v_out)*Prop_Axis[1] + (w_in + w_out)*Prop_Axis[2]); + + FQ = Q_out/Density_Disk; + + /*--- Computation of the momentum jumps due to the tnagential and radial forces per unit area. ---*/ + if (FQ < EPS){ + uJ = 0.0; + vJ = 0.0; + wJ = 0.0;} + else{ + uJ = Fx/FQ; + vJ = Fy/FQ; + wJ = Fz/FQ;} + + if (val_inlet_surface) { + /*--- Build the fictitious intlet state based on characteristics. + Retrieve the specified back pressure for this inlet ---*/ + + Density = V_domain[nDim+2]; + Velocity2 = 0.0; Vn = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity[iDim] = V_domain[iDim+1]; + Velocity2 += Velocity[iDim]*Velocity[iDim]; + Vn += Velocity[iDim]*UnitNormal[iDim]; + } + Pressure = V_domain[nDim+1]; + SoundSpeed = sqrt(Gamma*Pressure/Density); + + Entropy = Pressure*pow(1.0/Density, Gamma); + Riemann = Vn + 2.0*SoundSpeed/Gamma_Minus_One; + + /*--- Compute the new fictious state at the outlet ---*/ + + Pressure = Pressure_out - Fa; + Density = pow(Pressure/Entropy,1.0/Gamma); + SoundSpeed = sqrt(Gamma*Pressure/Density); + Vn_Inlet = Riemann - 2.0*SoundSpeed/Gamma_Minus_One; + + Velocity2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) { + Velocity[iDim] = Velocity[iDim] + (Vn_Inlet-Vn)*UnitNormal[iDim]; + Velocity2 += Velocity[iDim]*Velocity[iDim]; + } + Energy = Pressure/(Density*Gamma_Minus_One) + 0.5*Velocity2; + if (tkeNeeded) Energy += GetTke_Inf(); + + /*--- Conservative variables, using the derived quantities ---*/ + + V_inlet[0] = Pressure / ( Gas_Constant * Density); + for (iDim = 0; iDim < nDim; iDim++) + V_inlet[iDim+1] = Velocity[iDim]; + V_inlet[nDim+1] = Pressure; + V_inlet[nDim+2] = Density; + V_inlet[nDim+3] = Energy + Pressure/Density; + V_inlet[nDim+4] = SoundSpeed; + conv_numerics->SetPrimitive(V_domain, V_inlet); + }else{ + /*--- Acoustic Riemann invariant extrapolation form the interior domain. ---*/ + SoSextr = V_domain[nDim+4]; + + Vnextr_ = 0.0; + for (iDim = 0; iDim < nDim; iDim++){ + Vnextr[iDim] = V_domain[iDim+1]*Prop_Axis[iDim]; + Vnextr_ += Vnextr[iDim]*Vnextr[iDim]; + } + Vnextr_ = sqrt(max(0.0,Vnextr_)); + RiemannExtr = Vnextr_ - ((2*SoSextr)/(Gamma_Minus_One)); + + /*--- Assigning the momentum in tangential direction jump and the pressure jump. ---*/ + Velocity[0] = u_in + uJ; + Velocity[1] = v_in + vJ; + Velocity[2] = w_in + wJ; + Pressure_out = Pressure_in + Fa; + + /*--- Computation of the momentum normal to the disk plane. ---*/ + QdMnorm[0] = u_in*Prop_Axis[0]; + QdMnorm[1] = v_in*Prop_Axis[1]; + QdMnorm[2] = w_in*Prop_Axis[2]; + + QdMnorm2 = 0.0; + for (iDim = 0; iDim < nDim; iDim++) QdMnorm2 += QdMnorm[iDim]*QdMnorm[iDim]; + + /*--- Resolving the second grade equation for the density. ---*/ + appo2 = -((2*sqrt(QdMnorm2)*RiemannExtr)+((4*Gamma*Pressure_out)/(pow(Gamma_Minus_One,2)))); + Density_out = (-appo2+sqrt(max(0.0,pow(appo2,2)-4*QdMnorm2*pow(RiemannExtr,2))))/(2*pow(RiemannExtr,2)); + + Velocity2 = 0; + for (iDim = 0; iDim < nDim; iDim++) Velocity2 += (Velocity[iDim]*Velocity[iDim]); + + /*--- Computation of the enthalpy, total energy, temperature and speed of sound. ---*/ + H_out = H_in/Density_in + Fa/Density_out; + Energy = H_out - Pressure_out/Density_out; + if (tkeNeeded) Energy += GetTke_Inf(); + Temperature_out = (Energy-0.5*Velocity2/(pow(Density_out,2)))*(Gamma_Minus_One/Gas_Constant); + + SoS_out = sqrt(Gamma*Gas_Constant*Temperature_out); + + /*--- Set the primitive variables. ---*/ + V_outlet[0] = Temperature_out; + for (iDim = 0; iDim < nDim; iDim++) + V_outlet[iDim+1] = Velocity[iDim]/Density_out; + V_outlet[nDim+1] = Pressure_out; + V_outlet[nDim+2] = Density_out; + V_outlet[nDim+3] = H_out; + V_outlet[nDim+4] = SoS_out; + conv_numerics->SetPrimitive(V_domain, V_outlet); + } + + /*--- Grid Movement (NOT TESTED!)---*/ + + if (dynamic_grid) + conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint)); + + /*--- Compute the residual using an upwind scheme ---*/ + + auto residual = conv_numerics->ComputeResidual(config); + + /*--- Update residual value ---*/ + + LinSysRes.AddBlock(iPoint, residual); + + /*--- Jacobian contribution for implicit integration ---*/ + + if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i); + + } + } +} + void CEulerSolver::BC_Periodic(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config) { diff --git a/TestCases/hybrid_regression.py b/TestCases/hybrid_regression.py index 13f303abaa9b..b61ba02b39f8 100644 --- a/TestCases/hybrid_regression.py +++ b/TestCases/hybrid_regression.py @@ -210,6 +210,14 @@ def main(): propeller.test_vals = [-3.389576, -8.409529, 0.000048, 0.056329] test_list.append(propeller) + # PROPELLER VARIBLE LOAD + propeller_var_load = TestCase('propeller_variable_load') + propeller_var_load.cfg_dir = "rans/actuatordisk_variable_load" + propeller_var_load.cfg_file = "propeller_variable_load.cfg" + propeller_var_load.test_iter = 20 + propeller_var_load.test_vals = [-1.810684, -4.535582, 0.000252, 0.170455] + test_list.append(propeller_var_load) + ################################# ## Compressible RANS Restart ### ################################# diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index 9fe9af292804..1ef2733a158a 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -282,6 +282,17 @@ def main(): propeller.tol = 0.00001 test_list.append(propeller) + # PROPELLER VARIBLE LOAD + propeller_var_load = TestCase('propeller_variable_load') + propeller_var_load.cfg_dir = "rans/actuatordisk_variable_load" + propeller_var_load.cfg_file = "propeller_variable_load.cfg" + propeller_var_load.test_iter = 20 + propeller_var_load.test_vals = [-1.839227, -4.535048, -0.000314, 0.169980] #last 4 columns + propeller_var_load.su2_exec = "parallel_computation.py -f" + propeller_var_load.timeout = 3200 + propeller_var_load.tol = 0.00001 + test_list.append(propeller_var_load) + ################################# ## Compressible RANS Restart ### ################################# diff --git a/TestCases/rans/actuatordisk_variable_load/ActuatorDisk.dat b/TestCases/rans/actuatordisk_variable_load/ActuatorDisk.dat new file mode 100644 index 000000000000..9188b3cd45d6 --- /dev/null +++ b/TestCases/rans/actuatordisk_variable_load/ActuatorDisk.dat @@ -0,0 +1,54 @@ +# TEST CASE PROPELLER DATA. +# ADV_RATIO defined as Vinf/(nD) where n: propeller rounds per second, D: propeller diameter. +# "Renard" definition of propeller coefficients: +# reference force = rho*n^2*D^4, reference power = rho*n^3*D^5. +# Propeller center in grid coordinates. +# Propeller axis versor pointing backward. +# Total thrust coefficient CT = 0.15. +# ----------------------------------------------------------------------------------------------- # +MARKER_ACTDISK= DISK DISK_BACK +CENTER= 0.0 0.0 0.0 +AXIS= 1.0 0.0 0.0 +RADIUS= 2.5146 +ADV_RATIO= 2.81487 +NROW= 37 +# rs=r/R dCT/drs dCP/drs dCR/drs + 0.2031 0.020066 0.0890674 0.0 + 0.2235 0.019963 0.0932674 0.0 + 0.2439 0.021707 0.0982980 0.0 + 0.2644 0.024667 0.1064153 0.0 + 0.2848 0.029147 0.1189045 0.0 + 0.3257 0.043674 0.1588513 0.0 + 0.3461 0.053380 0.1849900 0.0 + 0.3665 0.064327 0.2145367 0.0 + 0.3870 0.076521 0.2471873 0.0 + 0.4278 0.103679 0.3203392 0.0 + 0.4483 0.118918 0.3609085 0.0 + 0.4687 0.135619 0.4051864 0.0 + 0.4891 0.152986 0.4518863 0.0 + 0.5096 0.171453 0.5011266 0.0 + 0.5300 0.190755 0.5528521 0.0 + 0.5504 0.211062 0.6072281 0.0 + 0.5709 0.231313 0.6620508 0.0 + 0.5913 0.251252 0.7161404 0.0 + 0.6117 0.271376 0.7700722 0.0 + 0.6322 0.290980 0.8219708 0.0 + 0.6526 0.309848 0.8715231 0.0 + 0.6730 0.328502 0.9202496 0.0 + 0.6935 0.346774 0.9681596 0.0 + 0.7139 0.364895 1.0156277 0.0 + 0.7343 0.381991 1.0603740 0.0 + 0.7548 0.398417 1.1036331 0.0 + 0.7752 0.413550 1.1442054 0.0 + 0.7956 0.427447 1.1820164 0.0 + 0.8161 0.440093 1.2163819 0.0 + 0.8365 0.451007 1.2453084 0.0 + 0.8569 0.460535 1.2682212 0.0 + 0.8774 0.467765 1.2823500 0.0 + 0.8978 0.471296 1.2839416 0.0 + 0.9182 0.470303 1.2701343 0.0 + 0.9387 0.460921 1.2317719 0.0 + 0.9591 0.434937 1.1470356 0.0 + 0.9795 0.377288 0.9746048 0.0 + +# More than one propeller data can be appended here. diff --git a/TestCases/rans/actuatordisk_variable_load/propeller_variable_load.cfg b/TestCases/rans/actuatordisk_variable_load/propeller_variable_load.cfg new file mode 100644 index 000000000000..1afbe6db96d4 --- /dev/null +++ b/TestCases/rans/actuatordisk_variable_load/propeller_variable_load.cfg @@ -0,0 +1,239 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% SU2 configuration file % +% Case description: Actuator Disk with a semi-infinite spinner % +% Author: E. Saetta, L. Russo, R. Tognaccini % +% Institution: Theoretical and Applied Aerodynamic Research Group (TAARG) % +% University of Naples Federico II % +% Comments: Grid file and propeller data courtesy of Mauro Minervino, % +% Centro Italiano Ricerche Aerospaziali (CIRA) % +% Date: 07/08/2020 % +% File Version 7.0.6 "Blackbird" % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%----------- DIRECT, ADJOINT, AND LINEARIZED PROBLEM DEFINITION -------------------------% +% Solver type (EULER, NAVIER_STOKES, RANS, +% INC_EULER, INC_NAVIER_STOKES, INC_RANS +% FEM_EULER, FEM_NAVIER_STOKES, FEM_RANS, FEM_LES, +% HEAT_EQUATION_FVM, ELASTICITY) +SOLVER= RANS +% +% Specify turbulence model (NONE, SA, SA_NEG, SST, SA_E, SA_COMP, SA_E_COMP, SST_SUST) +KIND_TURB_MODEL= SA +% +% Turbulence intensity at freestream +FREESTREAM_TURBULENCEINTENSITY=0.01 +% +% Mathematical problem (DIRECT, CONTINUOUS_ADJOINT, DISCRETE_ADJOINT) +MATH_PROBLEM= DIRECT +% +% Restart solution (NO, YES) +RESTART_SOL= NO +% +% System of measurements (SI, US) +% International system of units (SI): ( meters, kilograms, Kelvins, +% Newtons = kg m/s^2, Pascals = N/m^2, +% Density = kg/m^3, Speed = m/s, +% Equiv. Area = m^2 ) +SYSTEM_MEASUREMENTS= SI +% -------------------- COMPRESSIBLE FREE-STREAM DEFINITION --------------------% +% Mach number (non-dimensional, based on the free-stream values) +MACH_NUMBER= 0.55996 +% +% Angle of attack (degrees, only for compressible flows) +AOA= 0.0 +% +% Side-slip angle (degrees, only for compressible flows) +SIDESLIP_ANGLE= 0.0 +% +% Reynolds number (non-dimensional, based on the free-stream values) +REYNOLDS_NUMBER= 3.65E7 +% +% Reynolds length (1 m, 1 inch by default) +REYNOLDS_LENGTH= 5.0292 +% +% ---------------------- REFERENCE VALUE DEFINITION ---------------------------% +% Reference origin for moment computation (m or in) +REF_ORIGIN_MOMENT_X = 0.0 +REF_ORIGIN_MOMENT_Y = 0.0 +REF_ORIGIN_MOMENT_Z = 0.0 +% +% Reference length for moment non-dimensional coefficients (m or in) +REF_LENGTH= 1.0 +% +% Reference area for non-dimensional force coefficients (0 implies automatic +% calculation) (m^2 or in^2) +REF_AREA= 19.8649 +% +% Compressible flow non-dimensionalization (DIMENSIONAL, FREESTREAM_PRESS_EQ_ONE, +% FREESTREAM_VEL_EQ_MACH, FREESTREAM_VEL_EQ_ONE) +REF_DIMENSIONALIZATION= DIMENSIONAL +% +% --------------- ENGINE AND ACTUATOR DISK SIMULATION -------------------------% +% Highlite area to compute MFR (1 in by default) +HIGHLITE_AREA= 19.8649 +% +% Engine nu factor (SA model). +ENGINE_NU_FACTOR= 0.0 +% +% -------------------- BOUNDARY CONDITION DEFINITION --------------------------% +ACTDISK_DOUBLE_SURFACE = YES +% +% Actuator disk boundary type (VARIABLE_LOAD, VARIABLES_JUMP, BC_THRUST, +% DRAG_MINUS_THRUST) +ACTDISK_TYPE= VARIABLE_LOAD +% +% Actuator disk data input file name +ACTDISK_FILENAME= ActuatorDisk.dat +% +% Actuator disk boundary marker(s) with the following formats (NONE = no marker) +% Variable Load: (inlet face marker, outlet face marker, +% 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) Markers only effectively used. +MARKER_ACTDISK = ( DISK, DISK_BACK, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ) +% +% Far-field boundary marker(s) (NONE = no marker) +MARKER_FAR= ( FF ) +% +% Outlet boundary marker(s) (NONE = no marker) +% Compressible: ( outlet marker, back pressure (static thermodynamic), ... ) +MARKER_OUTLET = ( OUT , 56370.2) +% +% Navier-Stokes (no-slip), constant heat flux wall marker(s) (NONE = no marker) +% Format: ( marker name, constant heat flux (J/m^2), ... ) +MARKER_HEATFLUX = (SPINNER, 0.0) +% +% ------------------------ SURFACES IDENTIFICATION ----------------------------% +% Marker(s) of the surface in the surface flow solution file +MARKER_PLOTTING = ( DISK, DISK_BACK, SPINNER ) +% +% Marker(s) of the surface where the non-dimensional coefficients are evaluated. +MARKER_MONITORING = ( DISK, DISK_BACK, SPINNER ) +% +% Marker(s) of the surface that is going to be analyzed in detail (massflow, average pressure, distortion, etc) +MARKER_ANALYZE = ( DISK, DISK_BACK ) +% +% Method to compute the average value in MARKER_ANALYZE (AREA, MASSFLUX). +MARKER_ANALYZE_AVERAGE = MASSFLUX +% +% ------------- COMMON PARAMETERS DEFINING THE NUMERICAL METHOD ---------------% +% Numerical method for spatial gradients (GREEN_GAUSS, WEIGHTED_LEAST_SQUARES) +NUM_METHOD_GRAD= GREEN_GAUSS +% +% CFL number (initial value for the adaptive CFL number) +CFL_NUMBER= 20.0 +% +% Adaptive CFL number (NO, YES) +CFL_ADAPT= NO +% +% Objective function in gradient evaluation (DRAG, LIFT, SIDEFORCE, MOMENT_X, +% MOMENT_Y, MOMENT_Z, EFFICIENCY, BUFFET, +% EQUIVALENT_AREA, NEARFIELD_PRESSURE, +% FORCE_X, FORCE_Y, FORCE_Z, THRUST, +% TORQUE, TOTAL_HEATFLUX, +% MAXIMUM_HEATFLUX, INVERSE_DESIGN_PRESSURE, +% INVERSE_DESIGN_HEATFLUX, SURFACE_TOTAL_PRESSURE, +% SURFACE_MASSFLOW, SURFACE_STATIC_PRESSURE, SURFACE_MACH) +% For a weighted sum of objectives: separate by commas, add OBJECTIVE_WEIGHT and MARKER_MONITORING in matching order. +OBJECTIVE_FUNCTION= DRAG +% +% ------------------------ LINEAR SOLVER DEFINITION ---------------------------% +% Linear solver or smoother for implicit formulations: +% BCGSTAB, FGMRES, RESTARTED_FGMRES, CONJUGATE_GRADIENT (self-adjoint problems only), SMOOTHER. +LINEAR_SOLVER= FGMRES +% +% Preconditioner of the Krylov linear solver or type of smoother (ILU, LU_SGS, LINELET, JACOBI) +LINEAR_SOLVER_PREC= ILU +% +% Minimum error of the linear solver for implicit formulations +LINEAR_SOLVER_ERROR= 1E-12 +% +% Max number of iterations of the linear solver for the implicit formulation +LINEAR_SOLVER_ITER= 3 +% +% Number of elements to apply the criteria +CONV_CAUCHY_ELEMS= 1000 +% +% Epsilon to control the series convergence +CONV_CAUCHY_EPS= 1E-10 +% +% -------------------- FLOW NUMERICAL METHOD DEFINITION -----------------------% +% Convective numerical method (JST, LAX-FRIEDRICH, CUSP, ROE, AUSM, AUSMPLUSUP, +% AUSMPLUSUP2, HLLC, TURKEL_PREC, MSW, FDS, SLAU, SLAU2) +CONV_NUM_METHOD_FLOW= JST +% +% Time discretization (RUNGE-KUTTA_EXPLICIT, EULER_IMPLICIT, EULER_EXPLICIT) +TIME_DISCRE_FLOW= EULER_IMPLICIT +% +% -------------------- TURBULENT NUMERICAL METHOD DEFINITION ------------------% +% Convective numerical method (SCALAR_UPWIND) +CONV_NUM_METHOD_TURB= SCALAR_UPWIND +% +% Monotonic Upwind Scheme for Conservation Laws (TVD) in the turbulence equations. +% Required for 2nd order upwind schemes (NO, YES) +MUSCL_TURB= NO +% +% Slope limiter (NONE, VENKATAKRISHNAN, VENKATAKRISHNAN_WANG, +% BARTH_JESPERSEN, VAN_ALBADA_EDGE) +SLOPE_LIMITER_TURB= VENKATAKRISHNAN +% +% Time discretization (EULER_IMPLICIT) +TIME_DISCRE_TURB= EULER_IMPLICIT +% +% --------------------------- CONVERGENCE PARAMETERS --------------------------% +% Maximum number of iterations +ITER= 1500 +% +% Convergence criteria (CAUCHY, RESIDUAL) +CONV_CRITERIA= RESIDUAL +% +% Min value of the residual (log10 of the residual) +CONV_RESIDUAL_MINVAL= -8 +% +% Start convergence criteria at iteration number +CONV_STARTITER= 10 +% +% ------------------------- INPUT/OUTPUT INFORMATION --------------------------% +% Mesh input file +MESH_FILENAME= propeller_variable_load.su2 +% +% Mesh input file format (SU2, CGNS) +MESH_FORMAT= SU2 +% +% Mesh output file +MESH_OUT_FILENAME= mesh_out.su2 +% +% Restart flow input file +SOLUTION_FILENAME= restart_flow.dat +% +% Output tabular file format (TECPLOT, CSV) +TABULAR_FORMAT= TECPLOT +% +% Output file convergence history (w/o extension) +CONV_FILENAME= history +% +% Write the forces breakdown file option (NO, YES) +WRT_FORCES_BREAKDOWN= YES +% +% Output file with the forces breakdown +BREAKDOWN_FILENAME= forces_breakdown.dat +% +% Output file restart flow +RESTART_FILENAME= restart_flow.dat +% +% Output file flow (w/o extension) variables +VOLUME_FILENAME= flow +% +% Output file surface flow coefficient (w/o extension) +SURFACE_FILENAME= surface_flow +% +% Writing solution file frequency +WRT_SOL_FREQ= 250 +% +% Writing convergence history frequency +WRT_CON_FREQ= 1 +% +% +% +% Screen output fields +SCREEN_OUTPUT= (INNER_ITER, RMS_DENSITY, RMS_NU_TILDE, LIFT, DRAG) diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index 525494b70bc6..8f70735bc261 100644 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -323,6 +323,18 @@ def main(): propeller.tol = 0.00001 test_list.append(propeller) + # PROPELLER VARIBLE LOAD + propeller_var_load = TestCase('propeller_variable_load') + propeller_var_load.cfg_dir = "rans/actuatordisk_variable_load" + propeller_var_load.cfg_file = "propeller_variable_load.cfg" + propeller_var_load.test_iter = 20 + propeller_var_load.test_vals = [-1.826392, -4.535254, 0.000003, 0.170298] #last 4 columns + propeller_var_load.su2_exec = "SU2_CFD" + propeller_var_load.new_output = True + propeller_var_load.timeout = 3200 + propeller_var_load.tol = 0.00001 + test_list.append(propeller_var_load) + ################################# ## Compressible RANS Restart ### ################################# diff --git a/config_template.cfg b/config_template.cfg index 56ee2e54d969..14f8749e6322 100644 --- a/config_template.cfg +++ b/config_template.cfg @@ -700,11 +700,12 @@ MARKER_INLET= ( NONE ) % Inc. Mass Flow: ( outlet marker, mass flow target (kg/s), ... ) MARKER_OUTLET= ( NONE ) % -% Actuator disk boundary type (VARIABLES_JUMP, BC_THRUST, +% Actuator disk boundary type (VARIABLE_LOAD, VARIABLES_JUMP, BC_THRUST, % DRAG_MINUS_THRUST) ACTDISK_TYPE= VARIABLES_JUMP % % Actuator disk boundary marker(s) with the following formats (NONE = no marker) +% Variable Load: (inlet face marker, outlet face marker, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) % Variables Jump: ( inlet face marker, outlet face marker, % Takeoff pressure jump (psf), Takeoff temperature jump (R), Takeoff rev/min, % Cruise pressure jump (psf), Cruise temperature jump (R), Cruise rev/min ) @@ -716,6 +717,9 @@ ACTDISK_TYPE= VARIABLES_JUMP % Cruise Drag-Thrust (lbs), 0.0, Cruise rev/min ) MARKER_ACTDISK= ( NONE ) % +% Actuator disk data input file name +ACTDISK_FILENAME= actuatordisk.dat +% % Supersonic inlet boundary marker(s) (NONE = no marker) % Format: (inlet marker, temperature, static pressure, velocity_x, % velocity_y, velocity_z, ... ), i.e. primitive variables specified.