1 #include "tvb_limiter.h" 10 template <
int dim,
int nstate,
typename real>
15 template <
int dim,
int nstate,
typename real>
20 const double diff_next_state,
21 const double diff_prev_state,
22 const double cell_avg_state,
25 real limited_value = 0.0;
27 if (abs(a_state) <= M_state * pow(h, 2.0) && left_face) {
28 limited_value = cell_avg_state - a_state;
29 }
else if (abs(a_state) <= M_state * pow(h, 2.0) && !left_face) {
30 limited_value = cell_avg_state + a_state;
31 }
else if (left_face) {
32 if (signbit(a_state) == signbit(diff_next_state) && signbit(a_state) == signbit(diff_prev_state)) {
33 minmod = std::min({ abs(a_state), abs(diff_next_state), abs(diff_prev_state) });
36 limited_value = cell_avg_state + std::max(abs(minmod), M_state * pow(h, 2.0));
38 limited_value = cell_avg_state - std::max(abs(minmod), M_state * pow(h, 2.0));
41 limited_value = cell_avg_state - M_state * pow(h, 2.0);
42 }
else if (!left_face) {
43 if (signbit(a_state) == signbit(diff_next_state) && signbit(a_state) == signbit(diff_prev_state)) {
44 minmod = std::min({ abs(a_state), abs(diff_next_state), abs(diff_prev_state) });
47 limited_value = cell_avg_state - std::max(abs(minmod), M_state * pow(h, 2.0));
49 limited_value = cell_avg_state + std::max(abs(minmod), M_state * pow(h, 2.0));
52 limited_value = cell_avg_state - M_state * pow(h, 2.0);
58 template <
int dim,
int nstate,
typename real>
60 std::array<std::vector<real>,
nstate> soln_at_q,
61 const unsigned int n_quad_pts,
62 const std::array<real, nstate> prev_cell_avg,
63 const std::array<real, nstate> soln_cell_avg,
64 const std::array<real, nstate> next_cell_avg,
65 const std::array<real, nstate> M,
68 std::array<real, nstate> soln_cell_0;
69 std::array<real, nstate> soln_cell_k;
70 std::array<real, nstate> diff_next;
71 std::array<real, nstate> diff_prev;
72 std::array<real, nstate> soln_0_lim;
73 std::array<real, nstate> soln_k_lim;
74 std::array<real, nstate> theta;
78 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
79 soln_cell_0[istate] = soln_at_q[istate][0];
80 soln_cell_k[istate] = soln_at_q[istate][n_quad_pts - 1];
82 diff_next[istate] = next_cell_avg[istate] - soln_cell_avg[istate];
83 diff_prev[istate] = soln_cell_avg[istate] - prev_cell_avg[istate];
88 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
89 a = soln_cell_avg[istate] - soln_cell_0[istate];
90 soln_0_lim[istate] =
apply_modified_minmod(a, M[istate], h, diff_next[istate], diff_prev[istate], soln_cell_avg[istate],
true);
92 a = soln_cell_k[istate] - soln_cell_avg[istate];
93 soln_k_lim[istate] =
apply_modified_minmod(a, M[istate], h, diff_next[istate], diff_prev[istate], soln_cell_avg[istate],
false);
95 real scale = ((soln_cell_0[istate] - soln_cell_avg[istate]) + (soln_cell_k[istate] - soln_cell_avg[istate]));
97 theta[istate] = ((soln_0_lim[istate] - soln_cell_avg[istate]) + (soln_k_lim[istate] - soln_cell_avg[istate])) / scale;
103 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
104 for (
unsigned int iquad = 0; iquad < n_quad_pts; ++iquad) {
106 soln_at_q[istate][iquad] = soln_0_lim[istate];
108 else if (iquad == n_quad_pts - 1) {
109 soln_at_q[istate][iquad] = soln_k_lim[istate];
112 soln_at_q[istate][iquad] = theta[istate] * (soln_at_q[istate][iquad] - soln_cell_avg[istate])
113 + soln_cell_avg[istate];
121 template <
int dim,
int nstate,
typename real>
123 const dealii::LinearAlgebra::distributed::Vector<double>& solution,
124 const dealii::hp::FECollection<dim>& fe_collection,
125 const dealii::hp::QCollection<dim>& volume_quadrature_collection,
127 const int poly_degree,
128 const std::vector<dealii::types::global_dof_index>& neigh_dofs_indices,
129 const unsigned int n_dofs_neigh_cell)
132 std::array<std::vector<real>,
nstate> soln_coeff;
133 const unsigned int n_shape_fns = n_dofs_neigh_cell /
nstate;
135 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
136 soln_coeff[istate].resize(n_shape_fns);
140 for (
unsigned int idof = 0; idof < n_dofs_neigh_cell; ++idof) {
141 const unsigned int istate = fe_collection[poly_degree].system_to_component_index(idof).first;
142 const unsigned int ishape = fe_collection[poly_degree].system_to_component_index(idof).second;
143 soln_coeff[istate][ishape] = solution[neigh_dofs_indices[idof]];
145 const unsigned int n_quad_pts = volume_quadrature_collection[poly_degree].size();
146 const std::vector<real>& quad_weights = volume_quadrature_collection[poly_degree].get_weights();
148 std::array<real, nstate> cell_avg;
149 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
150 cell_avg[istate] = 0;
153 std::array<std::vector<real>, nstate> soln_at_q_neigh;
156 for (
int istate = 0; istate <
nstate; istate++) {
157 soln_at_q_neigh[istate].resize(n_quad_pts);
163 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
164 for (
unsigned int iquad = 0; iquad < n_quad_pts; ++iquad) {
165 cell_avg[istate] += quad_weights[iquad]
166 * soln_at_q_neigh[istate][iquad];
173 template <
int dim,
int nstate,
typename real>
175 dealii::LinearAlgebra::distributed::Vector<double>& solution,
176 const dealii::DoFHandler<dim>& dof_handler,
177 const dealii::hp::FECollection<dim>& fe_collection,
178 const dealii::hp::QCollection<dim>& volume_quadrature_collection,
179 const unsigned int grid_degree,
180 const unsigned int max_degree,
181 const dealii::hp::FECollection<1> oneD_fe_collection_1state,
182 dealii::hp::QCollection<1> oneD_quadrature_collection)
186 std::array<real, nstate> M;
187 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
194 const unsigned int init_grid_degree = grid_degree;
202 soln_basis_projection_oper.
build_1D_volume_operator(oneD_fe_collection_1state[max_degree], oneD_quadrature_collection[max_degree]);
204 for (
auto soln_cell : dof_handler.active_cell_iterators()) {
205 if (!soln_cell->is_locally_owned())
continue;
207 std::array<real, nstate> prev_cell_avg;
208 std::array<real, nstate> next_cell_avg;
211 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
212 prev_cell_avg[istate] = 0;
213 next_cell_avg[istate] = 0;
216 for (
const auto face_no : soln_cell->face_indices()) {
217 if (soln_cell->neighbor(face_no).state() != dealii::IteratorState::valid)
continue;
219 std::vector<dealii::types::global_dof_index> neigh_dofs_indices;
221 auto neigh = soln_cell->neighbor(face_no);
222 const int i_fele = soln_cell->active_fe_index();
223 const dealii::FESystem<dim, dim>& neigh_fe_ref = fe_collection[i_fele];
224 const int poly_degree = neigh_fe_ref.tensor_degree();
226 const unsigned int n_dofs_neigh_cell = neigh_fe_ref.n_dofs_per_cell();
228 neigh_dofs_indices.resize(n_dofs_neigh_cell);
229 neigh->get_dof_indices(neigh_dofs_indices);
231 std::array<real, nstate> neigh_cell_avg =
get_neighbour_cell_avg(solution, fe_collection, volume_quadrature_collection, soln_basis,
232 poly_degree, neigh_dofs_indices, n_dofs_neigh_cell);
235 prev_cell_avg = neigh_cell_avg;
237 else if (face_no == 1) {
238 next_cell_avg = neigh_cell_avg;
242 std::vector<dealii::types::global_dof_index> current_dofs_indices;
244 const int i_fele = soln_cell->active_fe_index();
245 const dealii::FESystem<dim, dim>& current_fe_ref = fe_collection[i_fele];
246 const int poly_degree = current_fe_ref.tensor_degree();
248 const unsigned int n_dofs_curr_cell = current_fe_ref.n_dofs_per_cell();
250 current_dofs_indices.resize(n_dofs_curr_cell);
251 soln_cell->get_dof_indices(current_dofs_indices);
254 std::array<std::vector<real>, nstate> soln_coeff;
255 const unsigned int n_shape_fns = n_dofs_curr_cell /
nstate;
257 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
258 soln_coeff[istate].resize(n_shape_fns);
262 for (
unsigned int idof = 0; idof < n_dofs_curr_cell; ++idof) {
263 const unsigned int istate = fe_collection[poly_degree].system_to_component_index(idof).first;
264 const unsigned int ishape = fe_collection[poly_degree].system_to_component_index(idof).second;
265 soln_coeff[istate][ishape] = solution[current_dofs_indices[idof]];
269 const unsigned int n_quad_pts = volume_quadrature_collection[poly_degree].size();
270 const std::vector<real>& quad_weights = volume_quadrature_collection[poly_degree].get_weights();
272 std::array<std::vector<real>, nstate> soln_at_q;
275 for (
int istate = 0; istate <
nstate; istate++) {
276 soln_at_q[istate].resize(n_quad_pts);
281 std::array<real, nstate> soln_cell_avg =
get_soln_cell_avg(soln_at_q, n_quad_pts, quad_weights);
283 std::array<std::vector<real>, nstate> soln_at_q_lim =
limit_cell(soln_at_q, n_quad_pts, prev_cell_avg, soln_cell_avg, next_cell_avg, M, h);
286 for (
int istate = 0; istate <
nstate; istate++) {
292 for (
int istate = 0; istate <
nstate; istate++) {
293 for (
unsigned int ishape = 0; ishape < n_shape_fns; ++ishape) {
294 const unsigned int idof = istate * n_shape_fns + ishape;
295 solution[current_dofs_indices[idof]] = soln_coeff[istate][ishape];
309 } // PHiLiP namespace void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
LimiterParam limiter_param
Contains parameters for limiter.
Base Class for bound preserving limiters templated on state.
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
double max_delta_x
Maximum delta_x for TVB Limiter.
TVBLimiter(const Parameters::AllParameters *const parameters_input)
Constructor.
void limit(dealii::LinearAlgebra::distributed::Vector< double > &solution, const dealii::DoFHandler< dim > &dof_handler, const dealii::hp::FECollection< dim > &fe_collection, const dealii::hp::QCollection< dim > &volume_quadrature_collection, const unsigned int grid_degree, const unsigned int max_degree, const dealii::hp::FECollection< 1 > oneD_fe_collection_1state, const dealii::hp::QCollection< 1 > oneD_quadrature_collection)
real apply_modified_minmod(const double a_state, const double M_state, const double h, const double diff_next_state, const double diff_prev_state, const double cell_avg_state, const bool left_face)
Function to apply modified_minmod using Thm3.7 in Chen, Shu 2017.
const int nstate
Number of states.
Files for the baseline physics.
std::array< std::vector< real >, nstate > limit_cell(std::array< std::vector< real >, nstate > soln_at_q, const unsigned int n_quad_pts, const std::array< real, nstate > prev_cell_avg, const std::array< real, nstate > soln_cell_avg, const std::array< real, nstate > next_cell_avg, const std::array< real, nstate > M, const double h)
Function to limit cell - apply minmod function, obtain theta (linear scaling value) and apply limiter...
Main parameter class that contains the various other sub-parameter classes.
std::array< real, nstate > get_soln_cell_avg(const std::array< std::vector< real >, nstate > &soln_at_q, const unsigned int n_quad_pts, const std::vector< real > &quad_weights)
Function to obtain the solution cell average.
Class for implementation of a TVD/TVB limiter derived from BoundPreservingLimiterState class...
std::array< real, nstate > get_neighbour_cell_avg(const dealii::LinearAlgebra::distributed::Vector< double > &solution, const dealii::hp::FECollection< dim > &fe_collection, const dealii::hp::QCollection< dim > &volume_quadrature_collection, OPERATOR::basis_functions< dim, 2 *dim, real > soln_basis, const int poly_degree, const std::vector< dealii::types::global_dof_index > &neigh_dofs_indices, const unsigned int n_dofs_neigh_cell)
Function to obtain the neighbour cell average.
dealii::FullMatrix< double > oneD_vol_operator
Stores the one dimensional volume operator.
dealii::Tensor< 1, 4, double > tuning_parameter_for_each_state
Tuning parameters for TVB Limiter.
void matrix_vector_mult_1D(const std::vector< real > &input_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const bool adding=false, const double factor=1.0)
Apply the matrix vector operation using the 1D operator in each direction.
const Parameters::AllParameters *const all_parameters
Pointer to parameters object.
Projection operator corresponding to basis functions onto M-norm (L2).