diff --git a/src/scheme/CellbyCellLimitation.hpp b/src/scheme/CellbyCellLimitation.hpp index 73a8ae06bec59c9b637c032bbb5f165c131fe15b..f9b8fc6028db2775fdaf09b74d1de9f5f04d5406 100644 --- a/src/scheme/CellbyCellLimitation.hpp +++ b/src/scheme/CellbyCellLimitation.hpp @@ -37,6 +37,168 @@ class CellByCellLimitation using Rd = TinyVector<Dimension>; public: + void + density_limiter(const MeshType& mesh, + const DiscreteFunctionP0<const double>& rho, + DiscreteFunctionDPk<Dimension, double>& rho_L) const + { + const auto& cell_to_face_matrix = mesh.connectivity().cellToFaceMatrix(); + const auto& face_to_node_matrix = mesh.connectivity().faceToNodeMatrix(); + + const auto& xr = mesh.xr(); + const auto& xl = mesh.xl(); + + MeshData<MeshType>& mesh_data = MeshDataManager::instance().getMeshData(mesh); + + auto stencil = StencilManager::instance().getStencil(mesh.connectivity(), 1); + + auto xj = mesh_data.xj(); + + const QuadratureFormula<1> qf = + QuadratureManager::instance().getLineFormula(GaussLegendreQuadratureDescriptor(m_quadrature_degree)); + + parallel_for( + mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double rhoj = rho[cell_id]; + + double rho_min = rhoj; + double rho_max = rhoj; + + const auto cell_stencil = stencil[cell_id]; + for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) { + rho_min = std::min(rho_min, rho[cell_stencil[i_cell]]); + rho_max = std::max(rho_max, rho[cell_stencil[i_cell]]); + } + + double rho_bar_min = rhoj; + double rho_bar_max = rhoj; + + for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) { + const CellId cell_k_id = cell_stencil[i_cell]; + const double rho_xk = rho_L[cell_id](xj[cell_k_id]); + + rho_bar_min = std::min(rho_bar_min, rho_xk); + rho_bar_max = std::max(rho_bar_max, rho_xk); + } + + auto face_list = cell_to_face_matrix[cell_id]; + for (size_t i_face = 0; i_face < face_list.size(); ++i_face) { + const FaceId face_id = face_list[i_face]; + + const Rd& x0 = xr[face_to_node_matrix[face_id][0]]; + const Rd& x1 = xl[face_id][0]; + const Rd& x2 = xr[face_to_node_matrix[face_id][1]]; + + const LineParabolicTransformation<Dimension> t(x0, x1, x2); + for (size_t iq = 0; iq < qf.numberOfPoints(); ++iq) { + const double rho_xk = rho_L[cell_id](t(qf.point(iq))); + + rho_bar_min = std::min(rho_bar_min, rho_xk); + rho_bar_max = std::max(rho_bar_max, rho_xk); + } + } + + const double eps = 1E-14; + double coef1 = 1; + if (std::abs(rho_bar_max - rhoj) > eps) { + coef1 = (rho_max - rhoj) / ((rho_bar_max - rhoj)); + } + + double coef2 = 1.; + if (std::abs(rho_bar_min - rhoj) > eps) { + coef2 = (rho_min - rhoj) / ((rho_bar_min - rhoj)); + } + + const double lambda = std::max(0., std::min(1., std::min(coef1, coef2))); + + auto coefficients = rho_L.coefficients(cell_id); + + coefficients[0] = (1 - lambda) * rho[cell_id] + lambda * coefficients[0]; + + for (size_t i = 1; i < coefficients.size(); ++i) { + coefficients[i] *= lambda; + } + }); + } + + void + specific_internal_nrj_limiter(const MeshType& mesh, + const DiscreteFunctionP0<const double>& rho, + const DiscreteFunctionDPk<Dimension, double>& rho_L + DiscreteFunctionP0<const double>& epsilon, + DiscreteFunctionDPk<Dimension, double>& epsilon_R) const + { + const auto& cell_to_face_matrix = mesh.connectivity().cellToFaceMatrix(); + const auto& face_to_node_matrix = mesh.connectivity().faceToNodeMatrix(); + + const auto& xr = mesh.xr(); + const auto& xl = mesh.xl(); + + MeshData<MeshType>& mesh_data = MeshDataManager::instance().getMeshData(mesh); + + auto stencil = StencilManager::instance().getStencil(mesh.connectivity(), 1); + + auto xj = mesh_data.xj(); + + const QuadratureFormula<1> qf = + QuadratureManager::instance().getLineFormula(GaussLegendreQuadratureDescriptor(m_quadrature_degree)); + + parallel_for( + mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id) { + const double epsilonj = epsilon[cell_id]; + + double epsilon_min = epsilonj; + double epsilon_max = epsilonj; + + const auto cell_stencil = stencil[cell_id]; + for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) { + epsilon_min = std::min(epsilon_min, epsilon[cell_stencil[i_cell]]); + epsilon_max = std::max(epsilon_max, epsilon[cell_stencil[i_cell]]); + } + + double epsilon_R_min = epsilonj; + double epsilon_R_max = epsilonj; + + for (size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell) { + const CellId cell_k_id = cell_stencil[i_cell]; + const double epsilon_xk = epsilon_R(cell_id, xj[cell_k_id]); + + epsilon_R_min = std::min(epsilon_R_min, epsilon_xk); + epsilon_R_max = std::max(epsilon_R_max, epsilon_xk); + } + + auto face_list = cell_to_face_matrix[cell_id]; + for (size_t i_face = 0; i_face < face_list.size(); ++i_face) { + const FaceId face_id = face_list[i_face]; + + const Rd& x0 = xr[face_to_node_matrix[face_id][0]]; + const Rd& x1 = xl[face_id][0]; + const Rd& x2 = xr[face_to_node_matrix[face_id][1]]; + + const LineParabolicTransformation<Dimension> t(x0, x1, x2); + for (size_t iq = 0; iq < qf.numberOfPoints(); ++iq) { + const double epsilon_xk = epsilon_R(cell_id, t(qf.point(iq))); + + epsilon_R_min = std::min(epsilon_R_min, epsilon_xk); + epsilon_R_max = std::max(epsilon_R_max, epsilon_xk); + } + } + + const double eps = 1E-14; + double coef1 = 1; + if (std::abs(epsilon_R_max - epsilonj) > eps) { + coef1 = (epsilon_max - epsilonj) / ((epsilon_R_max - epsilonj)); + } + + double coef2 = 1.; + if (std::abs(epsilon_R_min - epsilonj) > eps) { + coef2 = (epsilon_min - epsilonj) / ((epsilon_R_min - epsilonj)); + } + + lambda_epsilon[cell_id] = std::max(0., std::min(1., std::min(coef1, coef2))); + }); + } + void computeLimitorVolumicScalarQuantityMinModDukowiczGradient(const MeshType& mesh, const CellValue<double>& q,