@@ -73,9 +73,11 @@ CTurbSASolver::CTurbSASolver(CGeometry *geometry, CConfig *config, unsigned shor
7373 LinSysRes.Initialize (nPoint, nPointDomain, nVar, 0.0 );
7474 System.SetxIsZero (true );
7575
76- if (ReducerStrategy)
76+ if (ReducerStrategy) {
7777 EdgeFluxes.Initialize (geometry->GetnEdge (), geometry->GetnEdge (), nVar, nullptr );
78-
78+ EdgeFluxes_Diff.Initialize (geometry->GetnEdge (), geometry->GetnEdge (), nVar, nullptr );
79+ }
80+
7981 if (config->GetExtraOutput ()) {
8082 if (nDim == 2 ) { nOutputVariables = 13 ; }
8183 else if (nDim == 3 ) { nOutputVariables = 19 ; }
@@ -301,8 +303,95 @@ void CTurbSASolver::Viscous_Residual(const unsigned long iEdge, const CGeometry*
301303 };
302304
303305 /* --- Now instantiate the generic implementation with the functor above. ---*/
306+ const bool implicit = (config->GetKind_TimeIntScheme () == EULER_IMPLICIT);
307+ CFlowVariable* flowNodes = solver_container[FLOW_SOL] ?
308+ su2staticcast_p<CFlowVariable*>(solver_container[FLOW_SOL]->GetNodes ()) : nullptr ;
309+
310+ /* --- Points in edge ---*/
311+ auto iPoint = geometry->edges ->GetNode (iEdge, 0 );
312+ auto jPoint = geometry->edges ->GetNode (iEdge, 1 );
313+
314+ /* --- Helper function to compute the flux ---*/
315+ auto ComputeFlux = [&](unsigned long point_i, unsigned long point_j, const su2double* normal) {
316+ numerics->SetCoord (geometry->nodes ->GetCoord (point_i),geometry->nodes ->GetCoord (point_j));
317+ numerics->SetNormal (normal);
318+
319+ if (flowNodes) {
320+ numerics->SetPrimitive (flowNodes->GetPrimitive (point_i), flowNodes->GetPrimitive (point_j));
321+ }
322+
323+ numerics->SetScalarVar (nodes->GetSolution (point_i), nodes->GetSolution (point_j));
324+ numerics->SetScalarVarGradient (nodes->GetGradient (point_i), nodes->GetGradient (point_j));
325+
326+ return numerics->ComputeResidual (config);
327+ };
328+
329+ SolverSpecificNumerics (iPoint, jPoint);
330+
331+ /* --- Compute fluxes and jacobians i->j ---*/
332+ const su2double* normal = geometry->edges ->GetNormal (iEdge);
333+ auto residual_ij = ComputeFlux (iPoint, jPoint, normal);
334+ if (ReducerStrategy) {
335+ EdgeFluxes.SubtractBlock (iEdge, residual_ij);
336+ EdgeFluxes_Diff.SetBlock (iEdge, residual_ij);
337+ if (implicit) {
338+ auto * Block_ij = Jacobian.GetBlock (iPoint, jPoint);
339+ auto * Block_ji = Jacobian.GetBlock (jPoint, iPoint);
340+
341+ for (int iVar=0 ; iVar<nVar; iVar++)
342+ for (int jVar=0 ; jVar<nVar; jVar++) {
343+ Block_ij[iVar*nVar + jVar] -= 0.5 *SU2_TYPE::GetValue (residual_ij.jacobian_j [iVar][jVar]);
344+ Block_ji[iVar*nVar + jVar] += 0.5 *SU2_TYPE::GetValue (residual_ij.jacobian_i [iVar][jVar]);
345+ }
346+ }
347+ }
348+ else {
349+ LinSysRes.SubtractBlock (iPoint, residual_ij);
350+ if (implicit) {
351+ auto * Block_ii = Jacobian.GetBlock (iPoint, iPoint);
352+ auto * Block_ij = Jacobian.GetBlock (iPoint, jPoint);
353+
354+ for (int iVar=0 ; iVar<nVar; iVar++)
355+ for (int jVar=0 ; jVar<nVar; jVar++) {
356+ Block_ii[iVar*nVar + jVar] -= SU2_TYPE::GetValue (residual_ij.jacobian_i [iVar][jVar]);
357+ Block_ij[iVar*nVar + jVar] -= SU2_TYPE::GetValue (residual_ij.jacobian_j [iVar][jVar]);
358+ }
359+ }
360+ }
304361
305- Viscous_Residual_impl (SolverSpecificNumerics, iEdge, geometry, solver_container, numerics, config);
362+ /* --- Compute fluxes and jacobians j->i ---*/
363+ su2double flipped_normal[MAXNDIM];
364+ for (int iDim=0 ; iDim<nDim; iDim++)
365+ flipped_normal[iDim] = -normal[iDim];
366+
367+ auto residual_ji = ComputeFlux (jPoint, iPoint, flipped_normal);
368+ if (ReducerStrategy) {
369+ EdgeFluxes_Diff.AddBlock (iEdge, residual_ji);
370+ if (implicit) {
371+ auto * Block_ij = Jacobian.GetBlock (iPoint, jPoint);
372+ auto * Block_ji = Jacobian.GetBlock (jPoint, iPoint);
373+
374+ for (int iVar=0 ; iVar<nVar; iVar++)
375+ for (int jVar=0 ; jVar<nVar; jVar++) {
376+ Block_ij[iVar*nVar + jVar] += 0.5 *SU2_TYPE::GetValue (residual_ji.jacobian_i [iVar][jVar]);
377+ Block_ji[iVar*nVar + jVar] -= 0.5 *SU2_TYPE::GetValue (residual_ji.jacobian_j [iVar][jVar]);
378+ }
379+ }
380+ }
381+ else {
382+ LinSysRes.SubtractBlock (jPoint, residual_ji);
383+ if (implicit) {
384+ auto * Block_ji = Jacobian.GetBlock (jPoint, iPoint);
385+ auto * Block_jj = Jacobian.GetBlock (jPoint, jPoint);
386+
387+ // the order of arguments were flipped in the evaluation of residual_ji, the jacobian associated with point i is stored in jacobian_j and point j in jacobian_i
388+ for (int iVar=0 ; iVar<nVar; iVar++)
389+ for (int jVar=0 ; jVar<nVar; jVar++) {
390+ Block_ji[iVar*nVar + jVar] -= SU2_TYPE::GetValue (residual_ji.jacobian_j [iVar][jVar]);
391+ Block_jj[iVar*nVar + jVar] -= SU2_TYPE::GetValue (residual_ji.jacobian_i [iVar][jVar]);
392+ }
393+ }
394+ }
306395}
307396
308397void CTurbSASolver::Source_Residual (CGeometry *geometry, CSolver **solver_container,
0 commit comments