[ConvectionDiffusionApplication] Adding crosswind stabilization to Eulerian Convection–Diffusion element#14272
[ConvectionDiffusionApplication] Adding crosswind stabilization to Eulerian Convection–Diffusion element#14272
Conversation
rubenzorrilla
left a comment
There was a problem hiding this comment.
I'm not fully convinced about the elemental cross wind factor calculation. Aside of this, the others are minors.
| const double res = -time_derivative -inner_prod(vel_gauss, grad_phi_halfstep); | ||
|
|
||
| const double disc_capturing_coeff = 0.5*C*h*fabs(res/norm_grad); | ||
| BoundedMatrix<double,TDim,TDim> D = disc_capturing_coeff*( IdentityMatrix(TDim)); |
There was a problem hiding this comment.
You are allocating this for each Gauss pt.
| //cross-wind term | ||
| if(norm_grad > 1e-3 && norm_vel > 1e-9) | ||
| { | ||
| const double C = rCurrentProcessInfo[CROSS_WIND_STABILIZATION_FACTOR]; |
There was a problem hiding this comment.
Access once outside the Gauss pt. loop. Besides avoiding accessing the ProcessInfo many times, you can use it to check if the cross wind stabilization is active and avoid all these operations.
| const double time_derivative = Variables.dt_inv*(inner_prod(N,Variables.phi)-inner_prod(N,Variables.phi_old)); | ||
| const double res = -time_derivative -inner_prod(vel_gauss, grad_phi_halfstep); | ||
|
|
||
| const double disc_capturing_coeff = 0.5*C*h*fabs(res/norm_grad); |
There was a problem hiding this comment.
| const double disc_capturing_coeff = 0.5*C*h*fabs(res/norm_grad); | |
| const double disc_capturing_coeff = 0.5*C*h*std::abs(res/norm_grad); |
| const double disc_capturing_coeff = 0.5*C*h*fabs(res/norm_grad); | ||
| BoundedMatrix<double,TDim,TDim> D = disc_capturing_coeff*( IdentityMatrix(TDim)); | ||
| const double norm_vel_squared = norm_vel*norm_vel; | ||
| D += (std::max( disc_capturing_coeff - tau*norm_vel_squared , 0.0) - disc_capturing_coeff)/(norm_vel_squared) * outer_prod(vel_gauss,vel_gauss); |
There was a problem hiding this comment.
Are you sure about this? Shouldn't it involve the viscosity besides the tau?
| KRATOS_EXPECT_VECTOR_NEAR(RHS, expected_RHS, 1.0e-4) | ||
| KRATOS_EXPECT_MATRIX_NEAR(LHS, expected_LHS, 1.0e-4) |
There was a problem hiding this comment.
Make it more strict. In order to output the values, you can use std::setprecision (you can find some examples in the FluidDynamicsApplication).
| "dynamic_tau": 1.0, | ||
| "theta" : 1.0 | ||
| "theta" : 1.0, | ||
| "cross_wind_stabilization_factor": 0.0 |
There was a problem hiding this comment.
Shouldn't it automatically add it when validating the defaults?
📝 Description
This pull request introduces a crosswind stabilization term in the
EulerianConvectionDiffusionElementof Kratos.The implementation follows the discontinuity-capturing approach proposed in A discontinuity‑capturing crosswind‑dissipation for the finite element solution of the convection‑diffusion equation by Ramon Codina. The method adds a nonlinear diffusion in the direction orthogonal to the flow in order to reduce the spurious oscillations that may still appear when using streamline-based stabilization techniques.
The stabilization term can be activated through the element settings.
By default
CROSS_WIND_STABILIZATION_FACTORis zero.Additionally, a unit test has been included to verify the correct behaviour of the implementation.
To illustrate the effect of the stabilization, two example simulations are shown below:
Without crosswind stabilization:

Spurious oscillations appear near steep gradients.
With crosswind stabilization:

The oscillations are significantly reduced.
🆕 Changelog