1 #include "maximum_principle_limiter.h" 2 #include "tvb_limiter.h" 11 template <
int dim,
int nstate,
typename real>
19 tvbLimiter = std::make_shared < TVBLimiter<dim, nstate, real> >(parameters_input);
22 std::cout <<
"Error: Cannot create TVB limiter for dim > 1" << std::endl;
28 template <
int dim,
int nstate,
typename real>
30 const dealii::LinearAlgebra::distributed::Vector<double>& solution,
31 const dealii::DoFHandler<dim>& dof_handler,
32 const dealii::hp::FECollection<dim>& fe_collection)
34 for (
auto soln_cell : dof_handler.active_cell_iterators()) {
35 if (!soln_cell->is_locally_owned())
continue;
37 std::vector<dealii::types::global_dof_index> current_dofs_indices;
39 const int i_fele = soln_cell->active_fe_index();
40 const dealii::FESystem<dim, dim>& current_fe_ref = fe_collection[i_fele];
41 const int poly_degree = current_fe_ref.tensor_degree();
43 const unsigned int n_dofs_curr_cell = current_fe_ref.n_dofs_per_cell();
45 current_dofs_indices.resize(n_dofs_curr_cell);
46 soln_cell->get_dof_indices(current_dofs_indices);
50 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
57 std::array<std::vector<real>,
nstate> soln_coeff;
58 const unsigned int n_shape_fns = n_dofs_curr_cell /
nstate;
59 for (
unsigned int idof = 0; idof < n_dofs_curr_cell; ++idof) {
60 const unsigned int istate = fe_collection[poly_degree].system_to_component_index(idof).first;
61 const unsigned int ishape = fe_collection[poly_degree].system_to_component_index(idof).second;
63 soln_coeff[istate].resize(n_shape_fns);
65 soln_coeff[istate][ishape] = solution[current_dofs_indices[idof]];
66 if (soln_coeff[istate][ishape] >
global_max[istate])
67 global_max[istate] = soln_coeff[istate][ishape];
68 if (soln_coeff[istate][ishape] <
global_min[istate])
69 global_min[istate] = soln_coeff[istate][ishape];
74 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
75 std::cout << std::fixed;
76 std::cout << std::setprecision(14);
77 std::cout <<
"global_max: " <<
global_max[istate] <<
" global_min: " <<
global_min[istate] << std::endl;
81 template <
int dim,
int nstate,
typename real>
83 dealii::LinearAlgebra::distributed::Vector<double>& solution,
84 const std::array<std::vector<real>,
nstate>& soln_coeff,
85 const unsigned int n_shape_fns,
86 const std::vector<dealii::types::global_dof_index>& current_dofs_indices)
89 for (
int istate = 0; istate <
nstate; istate++) {
90 for (
unsigned int ishape = 0; ishape < n_shape_fns; ++ishape) {
91 const unsigned int idof = istate * n_shape_fns + ishape;
92 solution[current_dofs_indices[idof]] = soln_coeff[istate][ishape];
94 if (solution[current_dofs_indices[idof]] >
global_max[istate] + 1e-13) {
95 std::cout <<
"Error: Solution exceeds global maximum - Aborting... Value: " << solution[current_dofs_indices[idof]] << std::endl << std::flush;
98 if (solution[current_dofs_indices[idof]] <
global_min[istate] - 1e-13) {
99 std::cout <<
"Error: Solution exceeds global minimum - Aborting... Value: " << solution[current_dofs_indices[idof]] << std::endl << std::flush;
106 template <
int dim,
int nstate,
typename real>
108 dealii::LinearAlgebra::distributed::Vector<double>& solution,
109 const dealii::DoFHandler<dim>& dof_handler,
110 const dealii::hp::FECollection<dim>& fe_collection,
111 const dealii::hp::QCollection<dim>& volume_quadrature_collection,
112 const unsigned int grid_degree,
113 const unsigned int max_degree,
114 const dealii::hp::FECollection<1> oneD_fe_collection_1state,
115 const dealii::hp::QCollection<1> oneD_quadrature_collection,
120 this->
tvbLimiter->limit(solution, dof_handler, fe_collection, volume_quadrature_collection, grid_degree, max_degree, oneD_fe_collection_1state, oneD_quadrature_collection, dt);
123 const unsigned int init_grid_degree = grid_degree;
124 dealii::QGauss<1> oneD_quad_GL(max_degree + 1);
125 dealii::QGaussLobatto<1> oneD_quad_GLL(max_degree + 1);
137 for (
auto soln_cell : dof_handler.active_cell_iterators()) {
138 if (!soln_cell->is_locally_owned())
continue;
140 std::vector<dealii::types::global_dof_index> current_dofs_indices;
142 const int i_fele = soln_cell->active_fe_index();
143 const dealii::FESystem<dim, dim>& current_fe_ref = fe_collection[i_fele];
144 const int poly_degree = current_fe_ref.tensor_degree();
146 const unsigned int n_dofs_curr_cell = current_fe_ref.n_dofs_per_cell();
149 current_dofs_indices.resize(n_dofs_curr_cell);
150 soln_cell->get_dof_indices(current_dofs_indices);
153 std::array<std::vector<real>,
nstate> soln_coeff;
154 const unsigned int n_shape_fns = n_dofs_curr_cell /
nstate;
155 std::array<real, nstate> local_max;
156 std::array<real, nstate> local_min;
157 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
158 local_max[istate] = -1e9;
159 local_min[istate] = 1e9;
161 soln_coeff[istate].resize(n_shape_fns);
165 for (
unsigned int idof = 0; idof < n_dofs_curr_cell; ++idof) {
166 const unsigned int istate = fe_collection[poly_degree].system_to_component_index(idof).first;
167 const unsigned int ishape = fe_collection[poly_degree].system_to_component_index(idof).second;
168 soln_coeff[istate][ishape] = solution[current_dofs_indices[idof]];
170 if (soln_coeff[istate][ishape] > local_max[istate])
171 local_max[istate] = soln_coeff[istate][ishape];
173 if (soln_coeff[istate][ishape] < local_min[istate])
174 local_min[istate] = soln_coeff[istate][ishape];
178 const unsigned int n_quad_pts = volume_quadrature_collection[poly_degree].size();
179 const std::vector<real>& quad_weights = volume_quadrature_collection[poly_degree].get_weights();
181 std::array<std::array<std::vector<real>, nstate>, dim> soln_at_q;
182 std::array<std::vector<real>, nstate> soln_at_q_dim;
185 for(
unsigned int idim = 0; idim < dim; idim++) {
186 for (
int istate = 0; istate <
nstate; istate++) {
187 soln_at_q_dim[istate].resize(n_quad_pts);
204 soln_at_q[idim] = soln_at_q_dim;
207 for (
unsigned int idim = 0; idim < dim; ++idim) {
208 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
209 for (
unsigned int iquad = 0; iquad < n_quad_pts; ++iquad) {
210 if(soln_at_q[idim][istate][iquad] > local_max[istate]) {
211 local_max[istate] = soln_at_q[idim][istate][iquad];
213 if(soln_at_q[idim][istate][iquad] < local_min[istate]) {
214 local_min[istate] = soln_at_q[idim][istate][iquad];
221 std::array<real, nstate> soln_cell_avg =
get_soln_cell_avg(soln_coeff, n_quad_pts, quad_weights);
224 std::array<real, nstate> theta;
225 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
229 if (local_max[istate] - soln_cell_avg[istate] != 0)
230 maxscale = local_max[istate] - soln_cell_avg[istate];
231 if (local_min[istate] - soln_cell_avg[istate] != 0)
232 minscale = local_min[istate] - soln_cell_avg[istate];
234 theta[istate] = std::min({ abs((
global_max[istate] - soln_cell_avg[istate]) / maxscale),
235 abs((
global_min[istate] - soln_cell_avg[istate]) / minscale), 1.0 });
239 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
240 for (
unsigned int iquad = 0; iquad < n_quad_pts; ++iquad) {
241 soln_coeff[istate][iquad] = theta[istate] * (soln_coeff[istate][iquad] - soln_cell_avg[istate])
242 + soln_cell_avg[istate];
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.
std::vector< real > global_max
Maximum of initial solution for each state in domain.
void matrix_vector_mult(const std::vector< real > &input_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const dealii::FullMatrix< double > &basis_y, const dealii::FullMatrix< double > &basis_z, const bool adding=false, const double factor=1.0) override
Computes a matrix-vector product using sum-factorization. Pass the one-dimensional basis...
Base Class for bound preserving limiters templated on state.
Class for implementation of Maximum-Principle-Satisfying limiter derived from BoundPreservingLimiterS...
const int nstate
Number of states.
Files for the baseline physics.
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.
MaximumPrincipleLimiter(const Parameters::AllParameters *const parameters_input)
Constructor.
std::vector< real > global_min
Minimum of initial solution for each state in domain.
void get_global_max_and_min_of_solution(const dealii::LinearAlgebra::distributed::Vector< double > &solution, const dealii::DoFHandler< dim > &dof_handler, const dealii::hp::FECollection< dim > &fe_collection)
Function to obtain the maximum and minimum of the initial solution for each state.
dealii::FullMatrix< double > oneD_vol_operator
Stores the one dimensional volume operator.
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, double dt) override
bool use_tvb_limiter
Flag for applying TVB Limiter.
void write_limited_solution(dealii::LinearAlgebra::distributed::Vector< double > &solution, const std::array< std::vector< real >, nstate > &soln_coeff, const unsigned int n_shape_fns, const std::vector< dealii::types::global_dof_index > ¤t_dofs_indices)
const Parameters::AllParameters *const all_parameters
Pointer to parameters object.
std::shared_ptr< BoundPreservingLimiter< dim, real > > tvbLimiter
Pointer to TVB limiter class (TVB limiter can be applied in conjunction with this limiter) ...