@@ -146,6 +146,102 @@ class CScalarSolver : public CSolver {
146146 }
147147 }
148148
149+ /* !
150+ * \brief Compute the viscous flux for the turbulence equations at a particular edge for a non-conservative discretisation.
151+ * \tparam SolverSpecificNumericsTemp - lambda-function, to implement solver specific contributions to numerics.
152+ * \note The functor has to implement (iPoint, jPoint)
153+ * \param[in] iEdge - Edge for which we want to compute the flux
154+ * \param[in] geometry - Geometrical definition of the problem.
155+ * \param[in] solver_container - Container vector with all the solutions.
156+ * \param[in] numerics - Description of the numerical method.
157+ * \param[in] config - Definition of the particular problem.
158+ */
159+ template <typename SolverSpecificNumericsFunc>
160+ void Viscous_Residual_NonCons (const unsigned long iEdge, const CGeometry* geometry, CSolver** solver_container,
161+ CNumerics* numerics, const CConfig* config, SolverSpecificNumericsFunc&& SolverSpecificNumerics) {
162+ const bool implicit = (config->GetKind_TimeIntScheme () == EULER_IMPLICIT);
163+ CFlowVariable* flowNodes = solver_container[FLOW_SOL] ?
164+ su2staticcast_p<CFlowVariable*>(solver_container[FLOW_SOL]->GetNodes ()) : nullptr ;
165+
166+ const auto iPoint = geometry->edges ->GetNode (iEdge, 0 );
167+ const auto jPoint = geometry->edges ->GetNode (iEdge, 1 );
168+
169+ /* --- Lambda function to compute the flux ---*/
170+ auto ComputeFlux = [&](unsigned long iPoint, unsigned long jPoint, const su2double* normal) {
171+ numerics->SetCoord (geometry->nodes ->GetCoord (iPoint),geometry->nodes ->GetCoord (jPoint));
172+ numerics->SetNormal (normal);
173+
174+ if (flowNodes) {
175+ numerics->SetPrimitive (flowNodes->GetPrimitive (iPoint), flowNodes->GetPrimitive (jPoint));
176+ }
177+
178+ /* --- Solver specific numerics contribution. ---*/
179+ SolverSpecificNumerics (iPoint, jPoint);
180+
181+ numerics->SetScalarVar (nodes->GetSolution (iPoint), nodes->GetSolution (jPoint));
182+ numerics->SetScalarVarGradient (nodes->GetGradient (iPoint), nodes->GetGradient (jPoint));
183+
184+ return numerics->ComputeResidual (config);
185+ };
186+
187+ /* --- Compute fluxes and jacobians i->j ---*/
188+ const su2double* normal = geometry->edges ->GetNormal (iEdge);
189+ auto residual_ij = ComputeFlux (iPoint, jPoint, normal);
190+
191+ JacobianScalarType *Block_ii = nullptr , *Block_ij = nullptr , *Block_ji = nullptr , *Block_jj = nullptr ;
192+ if (implicit) {
193+ Jacobian.GetBlocks (iEdge, iPoint, jPoint, Block_ii, Block_ij, Block_ji, Block_jj);
194+ }
195+ if (ReducerStrategy) {
196+ EdgeFluxes.SubtractBlock (iEdge, residual_ij);
197+ EdgeFluxesDiff.SetBlock (iEdge, residual_ij);
198+ if (implicit) {
199+ /* --- For the reducer strategy the Jacobians are averaged for simplicity. ---*/
200+ for (int iVar=0 ; iVar<nVar; iVar++)
201+ for (int jVar=0 ; jVar<nVar; jVar++) {
202+ Block_ij[iVar*nVar + jVar] -= 0.5 * SU2_TYPE::GetValue (residual_ij.jacobian_j [iVar][jVar]);
203+ Block_ji[iVar*nVar + jVar] += 0.5 * SU2_TYPE::GetValue (residual_ij.jacobian_i [iVar][jVar]);
204+ }
205+ }
206+ } else {
207+ LinSysRes.SubtractBlock (iPoint, residual_ij);
208+ if (implicit) {
209+ for (int iVar=0 ; iVar<nVar; iVar++)
210+ for (int jVar=0 ; jVar<nVar; jVar++) {
211+ Block_ii[iVar*nVar + jVar] -= SU2_TYPE::GetValue (residual_ij.jacobian_i [iVar][jVar]);
212+ Block_ij[iVar*nVar + jVar] -= SU2_TYPE::GetValue (residual_ij.jacobian_j [iVar][jVar]);
213+ }
214+ }
215+ }
216+
217+ /* --- Compute fluxes and jacobians j->i ---*/
218+ su2double flipped_normal[MAXNDIM];
219+ for (auto iDim = 0u ; iDim < nDim; iDim++) flipped_normal[iDim] = -normal[iDim];
220+
221+ auto residual_ji = ComputeFlux (jPoint, iPoint, flipped_normal);
222+ if (ReducerStrategy) {
223+ EdgeFluxesDiff.AddBlock (iEdge, residual_ji);
224+ if (implicit) {
225+ for (int iVar=0 ; iVar<nVar; iVar++)
226+ for (int jVar=0 ; jVar<nVar; jVar++) {
227+ Block_ij[iVar*nVar + jVar] += 0.5 * SU2_TYPE::GetValue (residual_ji.jacobian_i [iVar][jVar]);
228+ Block_ji[iVar*nVar + jVar] -= 0.5 * SU2_TYPE::GetValue (residual_ji.jacobian_j [iVar][jVar]);
229+ }
230+ }
231+ } else {
232+ LinSysRes.SubtractBlock (jPoint, residual_ji);
233+ if (implicit) {
234+ /* --- The order of arguments were flipped in the evaluation of residual_ji, the Jacobian
235+ * associated with point i is stored in jacobian_j and point j in jacobian_i. ---*/
236+ for (int iVar=0 ; iVar<nVar; iVar++)
237+ for (int jVar=0 ; jVar<nVar; jVar++) {
238+ Block_ji[iVar*nVar + jVar] -= SU2_TYPE::GetValue (residual_ji.jacobian_j [iVar][jVar]);
239+ Block_jj[iVar*nVar + jVar] -= SU2_TYPE::GetValue (residual_ji.jacobian_i [iVar][jVar]);
240+ }
241+ }
242+ }
243+ }
244+
149245 /* !
150246 * \brief Generic implementation of the fluid interface boundary condition for scalar solvers.
151247 * \tparam SolverSpecificNumericsFunc - lambda that implements solver specific contributions to viscous numerics.
0 commit comments