Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Fix symmetry plane issues in SU2, change SU2-NEMO sym plane to match flow solver #1635

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 83 additions & 10 deletions SU2_CFD/include/solvers/CFVMFlowSolverBase.inl
Original file line number Diff line number Diff line change
Expand Up @@ -1062,23 +1062,90 @@ void CFVMFlowSolverBase<V, R>::PushSolutionBackInTime(unsigned long TimeIter, bo
template <class V, ENUM_REGIME R>
void CFVMFlowSolverBase<V, R>::BC_Sym_Plane(CGeometry* geometry, CSolver** solver_container, CNumerics* conv_numerics,
CNumerics* visc_numerics, CConfig* config, unsigned short val_marker) {
unsigned short iDim, iVar;
unsigned long iVertex, iPoint;
unsigned short iDim, iVar, iNeigh;
unsigned long iVertex, iPoint, jPoint, iEdge, iMarker;
su2double Tangent[MAXNDIM] = {0.0};
su2double Normal_Sym[MAXNDIM] = {0.0}, UnitNormal_Sym[MAXNDIM] = {0.0};
su2double Normal_Product, Product, tol = 1e-16;

bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
bool viscous = config->GetViscous();
const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
const bool viscous = config->GetViscous();
const bool nemo = config->GetNEMOProblem();
bool preprocessed = false;
const unsigned short nSpecies = config->GetnSpecies();

/*--- Allocation of variables necessary for convective fluxes. ---*/
su2double Area, ProjVelocity_i, *V_reflected, *V_domain, Normal[MAXNDIM] = {0.0}, UnitNormal[MAXNDIM] = {0.0};

/*--- Allocation of variables necessary for viscous fluxes. ---*/
su2double ProjGradient, ProjNormVelGrad, ProjTangVelGrad, TangentialNorm,
Tangential[MAXNDIM] = {0.0}, GradNormVel[MAXNDIM] = {0.0}, GradTangVel[MAXNDIM] = {0.0};
Tangential[MAXNDIM] = {0.0}, GradNormVel[MAXNDIM] = {0.0}, GradTangVel[MAXNDIM] = {0.0}, Residual[MAXNVAR] = {0.0};

Check notice

Code scanning / CodeQL

Unused local variable

Variable Residual is not used.

/*--- Allocation of primitive gradient arrays for viscous fluxes. ---*/
su2activematrix Grad_Reflected(nPrimVarGrad, nDim);

/*--- Count number of symmetry planes where each Vertex is inserted ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
if (config->GetMarker_All_KindBC(iMarker) == SYMMETRY_PLANE){
for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
nodes->SetSymmetry(iPoint);
}
}
}

/*--- Correct normal directions of edges ---*/
for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
if (config->GetMarker_All_KindBC(iMarker) == SYMMETRY_PLANE){

for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {

iPoint = geometry->vertex[iMarker][iVertex]->GetNode();

geometry->vertex[iMarker][iVertex]->GetNormal(Normal_Sym);

Area = GeometryToolbox::Norm(nDim, Normal_Sym);

for(iDim = 0; iDim<nDim; iDim++){
UnitNormal_Sym[iDim] = Normal_Sym[iDim]/Area;
}

for (iNeigh = 0; iNeigh < geometry->nodes->GetnPoint(iPoint); ++iNeigh){
Product = 0.0;

jPoint = geometry->nodes->GetPoint(iPoint,iNeigh);

/*---Check if neighbour point is on the same plane as the Symmetry_Plane
by computing the internal product and of the Normal Vertex vector and
the vector connecting iPoint and jPoint. If the product is lower than
estabilished tolerance (to account for Numerical errors) both points are
in the same plane as SYMMETRY_PLANE---*/

for(iDim = 0; iDim<nDim; iDim++){
Tangent[iDim] = geometry->nodes->GetCoord(jPoint,iDim) - geometry->nodes->GetCoord(iPoint,iDim);
Product += Tangent[iDim] * Normal_Sym[iDim];
}

if (abs(Product) < tol) {
Product = 0.0;

iEdge = geometry->nodes->GetEdge(iPoint,iNeigh);

geometry->edges->GetNormal(iEdge,Normal);

for(iDim = 0; iDim<nDim; iDim++)
Product += Normal[iDim]*UnitNormal_Sym[iDim];

for(iDim = 0; iDim<nDim; iDim++)
Normal[iDim]-=Product*UnitNormal_Sym[iDim];

geometry->edges->SetNormal(iEdge,Normal);
}
}
}
}
}

/*--- Loop over all the vertices on this boundary marker. ---*/

SU2_OMP_FOR_DYN(OMP_MIN_SIZE)
Expand Down Expand Up @@ -1143,9 +1210,10 @@ void CFVMFlowSolverBase<V, R>::BC_Sym_Plane(CGeometry* geometry, CSolver** solve
} // if bound_is_straight

iPoint = geometry->vertex[val_marker][iVertex]->GetNode();

/*--- Check if the node belongs to the domain (i.e., not a halo node) ---*/
if (geometry->nodes->GetDomain(iPoint)) {
Normal_Product = 0.0;
/*-------------------------------------------------------------------------------*/
/*--- Step 1: For the convective fluxes, create a reflected state of the ---*/
/*--- Primitive variables by copying all interior values to the ---*/
Expand All @@ -1172,25 +1240,30 @@ void CFVMFlowSolverBase<V, R>::BC_Sym_Plane(CGeometry* geometry, CSolver** solve
the velocity is mirrored along the symmetry boundary, i.e. the velocity in
normal direction is substracted twice. ---*/
for (iVar = 0; iVar < nPrimVar; iVar++) V_reflected[iVar] = nodes->GetPrimitive(iPoint, iVar);

/*--- Compute velocity in normal direction (ProjVelcity_i=(v*n)) und substract twice from
velocity in normal direction: v_r = v - 2 (v*n)n ---*/
ProjVelocity_i = nodes->GetProjVel(iPoint, UnitNormal);

/*--- Adjustment to v.n due to grid movement. ---*/
if (dynamic_grid) {
ProjVelocity_i -= GeometryToolbox::DotProduct(nDim, geometry->nodes->GetGridVel(iPoint), UnitNormal);
}

for (iDim = 0; iDim < nDim; iDim++)
V_reflected[iDim + 1] = nodes->GetVelocity(iPoint, iDim) - 2.0 * ProjVelocity_i * UnitNormal[iDim];
V_reflected[prim_idx.Velocity() + iDim] = nodes->GetVelocity(iPoint, iDim) - 2.0 * ProjVelocity_i * UnitNormal[iDim];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this and it gave an error when running with nemo, which is why I didn't push it. Did you test and ensured this gave correct results?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On my machine, it didn't seem to have any issues. What issues did you see?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case solution I was using gave the wrong solution when I used this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange, I just double checked (after I fixed my compilation errors I caused). The value of the velocity index was 7 for AIR-5.


/*--- Set Primitive and Secondary for numerics class. ---*/
conv_numerics->SetPrimitive(V_domain, V_reflected);
conv_numerics->SetSecondary(nodes->GetSecondary(iPoint), nodes->GetSecondary(iPoint));

/*--- Compute the residual using an upwind scheme. ---*/
if (nemo) {
conv_numerics->SetEve(nodes->GetEve(iPoint), nodes->GetEve(iPoint));
conv_numerics->SetCvve(nodes->GetCvve(iPoint), nodes->GetCvve(iPoint));
conv_numerics->SetGamma(nodes->GetGamma(iPoint), nodes->GetGamma(iPoint));
}

/*--- Compute the residual using an upwind scheme. ---*/
auto residual = conv_numerics->ComputeResidual(config);

/*--- Update residual value ---*/
Expand Down
12 changes: 0 additions & 12 deletions SU2_CFD/include/solvers/CNEMOEulerSolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,18 +238,6 @@ class CNEMOEulerSolver : public CFVMFlowSolverBase<CNEMOEulerVariable, ENUM_REGI
void BC_Far_Field(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics,
CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) override;

/*!
* \brief Impose the symmetry boundary condition using the residual.
* \param[in] geometry - Geometrical definition of the problem.
* \param[in] solver_container - Container vector with all the solutions.
* \param[in] conv_numerics - Description of the numerical method for convective terms.
* \param[in] visc_numerics - Description of the numerical method for viscous terms.
* \param[in] config - Definition of the particular problem.
* \param[in] val_marker - Surface marker where the boundary condition is applied.
*/
void BC_Sym_Plane(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics,
CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) final;

/*!
* \brief Impose a subsonic inlet boundary condition.
* \param[in] geometry - Geometrical definition of the problem.
Expand Down
28 changes: 28 additions & 0 deletions SU2_CFD/include/variables/CEulerVariable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class CEulerVariable : public CFlowVariable {
MatrixType WindGust; /*! < \brief Wind gust value */
MatrixType WindGustDer; /*! < \brief Wind gust derivatives value */

VectorType symmetry; /*!< \brief Nodes in symmetry planes. */

public:
/*!
* \brief Constructor of the class.
Expand Down Expand Up @@ -321,4 +323,30 @@ class CEulerVariable : public CFlowVariable {
for (unsigned long iDim = 0; iDim < nDim; iDim++) Solution(iPoint, iDim+1) = GetDensity(iPoint) * val_vector[iDim];
}

/*!
* \brief Returns the stored value of Eve at the specified node
*/
su2double *GetEve(unsigned long iPoint) {return nullptr;}

/*!
* \brief Returns the value of Cvve at the specified node
*/
su2double *GetCvve(unsigned long iPoint) {return nullptr;}

/*!
* \brief Returns the stored value of Gamma at the specified node
*/
su2double GetGamma(unsigned long iPoint) {return 0;}

/*!
* \brief Retrieves the number of symmetry planes at the specified node.
*/
inline su2double GetSymmetry(unsigned long iPoint) { return symmetry[iPoint]; }

/*!
* \brief Increases the number of symmetry planes at the specified node by one.
*/
inline void SetSymmetry(unsigned long iPoint) {symmetry[iPoint] += 1.0;}


};
27 changes: 27 additions & 0 deletions SU2_CFD/include/variables/CIncEulerVariable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class CIncEulerVariable : public CFlowVariable {

VectorType Streamwise_Periodic_RecoveredPressure, /*!< \brief Recovered/Physical pressure [Pa] for streamwise periodic flow. */
Streamwise_Periodic_RecoveredTemperature; /*!< \brief Recovered/Physical temperature [K] for streamwise periodic flow. */

VectorType symmetry; /*!< \brief Nodes in symmetry planes. */

public:
/*!
* \brief Constructor of the class.
Expand Down Expand Up @@ -271,5 +274,29 @@ class CIncEulerVariable : public CFlowVariable {
inline void SetVelSolutionVector(unsigned long iPoint, const su2double *val_vector) final {
for (unsigned long iDim = 0; iDim < nDim; iDim++) Solution(iPoint, iDim+1) = val_vector[iDim];
}
/*!
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better way to do this rather an than adding dummy functions to these variable classes? The compiler throws an error since NEMO requires these 3 functions, which don't exist in the other solvers. Would it be better to pass the variable type into the sym plane template explicitly somehow, like what is done for conv_numerics?

Copy link
Member

@pcarruscag pcarruscag May 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable type is known in CFVMFlowSolverBase, but to do something conditionally on a type in C++11 you need to create a helper function that is specialized for the type (CNEMOEulerVariable in this case)

template <class VariableType>
void SetExtraVars(unsigned long, VariableType*, CNumerics*) {
  // Do nothing for non-NEMO solvers.
}

template <>
void SetExtraVars<CNEMOEulerVariable>(unsigned long iPoint, CNEMOEulerVariable* nodes, CNumerics* numerics) {
  // Template specialization for NEMO variables, here you set Eve, etc.
  ...
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pcarruscag Do both the general template function declaration and the specialized declaration go in the inl file (i.e. implemented as you have it above? I get a compilation error of "unknown type name 'CNEMOEulerVariable'; did you mean 'CEulerVariable'?".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try putting the specialization in CNEMOEulerSolver.h

* \brief Returns the stored value of Eve at the specified node
*/
su2double *GetEve(unsigned long iPoint) {return nullptr;}

/*!
* \brief Returns the value of Cvve at the specified node
*/
su2double *GetCvve(unsigned long iPoint) {return nullptr;}

/*!
* \brief Returns the stored value of Gamma at the specified node
*/
su2double GetGamma(unsigned long iPoint) {return 0;}

/*!
* \brief Retrieves the number of symmetry planes at the specified node.
*/
inline su2double GetSymmetry(unsigned long iPoint) { return symmetry[iPoint]; }

/*!
* \brief Increases the number of symmetry planes at the specified node by one.
*/
inline void SetSymmetry(unsigned long iPoint) {symmetry[iPoint] += 1.0;}

};
12 changes: 12 additions & 0 deletions SU2_CFD/include/variables/CNEMOEulerVariable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ class CNEMOEulerVariable : public CFlowVariable {
LAM_VISC_INDEX, EDDY_VISC_INDEX, nSpecies;

su2double Tve_Freestream; /*!< \brief Freestream vib-el temperature. */
VectorType symmetry;

const bool implicit; /*!< \brief Implicit flag. */

public:
Expand Down Expand Up @@ -420,4 +422,14 @@ class CNEMOEulerVariable : public CFlowVariable {
for (unsigned long iDim = 0; iDim < nDim; iDim++) Res_TruncError(iPoint,nSpecies+iDim) = 0.0;
}

/*!
* \brief Increases the number of symmetry planes at the specified node by one.
*/
inline void SetSymmetry(unsigned long iPoint) {symmetry[iPoint] += 1.0;}

/*!
* \brief Retrieves the number of symmetry planes at the specified node.
*/
inline su2double GetSymmetry(unsigned long iPoint) { return symmetry[iPoint]; }

};
101 changes: 0 additions & 101 deletions SU2_CFD/src/solvers/CNEMOEulerSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1408,107 +1408,6 @@ void CNEMOEulerSolver::SetReferenceValues(const CConfig& config) {

}

void CNEMOEulerSolver::BC_Sym_Plane(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics,
CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) {

unsigned short iDim, jDim, iSpecies, iVar, jVar;
unsigned long iPoint, iVertex;

/*--- Allocate the necessary vector structures ---*/
su2double Normal[MAXNDIM] = {0.0}, UnitNormal[MAXNDIM] = {0.0};

bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);

/*--- Loop over all the vertices on this boundary (val_marker) ---*/
for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) {
iPoint = geometry->vertex[val_marker][iVertex]->GetNode();

/*--- Check if the node belongs to the domain (i.e, not a halo node) ---*/
if (geometry->nodes->GetDomain(iPoint)) {

/*--- Normal vector for this vertex (negative for outward convention) ---*/
geometry->vertex[val_marker][iVertex]->GetNormal(Normal);

/*--- Calculate parameters from the geometry ---*/
su2double Area = GeometryToolbox::Norm(nDim, Normal);

for (iDim = 0; iDim < nDim; iDim++){
UnitNormal[iDim] = -Normal[iDim]/Area;
}

/*--- Retrieve the pressure on the vertex ---*/
su2double P = nodes->GetPressure(iPoint);

/*--- Apply the flow-tangency b.c. to the convective flux ---*/
for (iSpecies = 0; iSpecies < nSpecies; iSpecies++)
Residual[iSpecies] = 0.0;
for (iDim = 0; iDim < nDim; iDim++){
Residual[nSpecies+iDim] = P * UnitNormal[iDim] * Area;
}
Residual[nSpecies+nDim] = 0.0;
Residual[nSpecies+nDim+1] = 0.0;

/*--- Add value to the residual ---*/
LinSysRes.AddBlock(iPoint, Residual);

/*--- If using implicit time-stepping, calculate b.c. contribution to Jacobian ---*/
if (implicit) {

/*--- Allocate arrays needed for implicit solver ---*/
su2double Velocity[MAXNDIM] = {0.0};

/*--- Get species molar mass ---*/
auto& Ms = FluidModel->GetSpeciesMolarMass();

/*--- Initialize Jacobian ---*/
for (iVar = 0; iVar < nVar; iVar++)
for (jVar = 0; jVar < nVar; jVar++)
Jacobian_i[iVar][jVar] = 0.0;

/*--- Calculate state i ---*/
su2double rho = nodes->GetDensity(iPoint);
su2double rhoE = nodes->GetSolution(iPoint,nSpecies+nDim);
su2double rhoEve = nodes->GetSolution(iPoint,nSpecies+nDim+1);
auto dPdU = nodes->GetdPdU(iPoint);
for (iDim = 0; iDim < nDim; iDim++)
Velocity[iDim] = nodes->GetVelocity(iPoint,iDim);

su2double conc = 0.0;
for (iSpecies = 0; iSpecies < nSpecies; iSpecies++) {
su2double cs = nodes->GetMassFraction(iPoint,iSpecies);
conc += cs * rho/Ms[iSpecies];

for (iDim = 0; iDim < nDim; iDim++) {
Jacobian_i[nSpecies+iDim][iSpecies] = dPdU[iSpecies] * UnitNormal[iDim];
Jacobian_i[iSpecies][nSpecies+iDim] = cs * UnitNormal[iDim];
}
}

for (iDim = 0; iDim < nDim; iDim++) {
for (jDim = 0; jDim < nDim; jDim++) {
Jacobian_i[nSpecies+iDim][nSpecies+jDim] = Velocity[iDim]*UnitNormal[jDim]
+ dPdU[nSpecies+jDim]*UnitNormal[iDim];
}
Jacobian_i[nSpecies+iDim][nSpecies+nDim] = dPdU[nSpecies+nDim] *UnitNormal[iDim];
Jacobian_i[nSpecies+iDim][nSpecies+nDim+1] = dPdU[nSpecies+nDim+1]*UnitNormal[iDim];

Jacobian_i[nSpecies+nDim][nSpecies+iDim] = (rhoE+P)/rho * UnitNormal[iDim];
Jacobian_i[nSpecies+nDim+1][nSpecies+iDim] = rhoEve/rho * UnitNormal[iDim];
}

/*--- Integrate over the dual-grid area ---*/
for (iVar = 0; iVar < nVar; iVar++)
for (jVar = 0; jVar < nVar; jVar++)
Jacobian_i[iVar][jVar] = Jacobian_i[iVar][jVar] * Area;

/*--- Apply the contribution to the system ---*/
Jacobian.AddBlock2Diag(iPoint, Jacobian_i);

}
}
}
}

void CNEMOEulerSolver::BC_Far_Field(CGeometry *geometry, CSolver **solver_container,
CNumerics *conv_numerics, CNumerics *visc_numerics,
CConfig *config, unsigned short val_marker) {
Expand Down
3 changes: 3 additions & 0 deletions SU2_CFD/src/variables/CNEMOEulerVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ CNEMOEulerVariable::CNEMOEulerVariable(su2double val_pressure,
eves.resize(nPoint, nSpecies) = su2double(0.0);
Gamma.resize(nPoint) = su2double(0.0);

/* Vector to count number of symmetry planes at each node. */
symmetry.resize(nPoint) = su2double(0.0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be needed for the base and Inc solvers too, correct?


/*--- Set mixture state ---*/
fluidmodel->SetTDStatePTTv(val_pressure, val_massfrac, val_temperature, val_temperature_ve);

Expand Down
2 changes: 1 addition & 1 deletion SU2_IDE/Xcode/SU2_CFD.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2790,4 +2790,4 @@
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}
}
Loading