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)
119 this->
tvbLimiter->limit(solution, dof_handler, fe_collection, volume_quadrature_collection, grid_degree, max_degree, oneD_fe_collection_1state, oneD_quadrature_collection);
124 const unsigned int init_grid_degree = grid_degree;
132 soln_basis_projection_oper.
build_1D_volume_operator(oneD_fe_collection_1state[max_degree], oneD_quadrature_collection[max_degree]);
138 for (
auto soln_cell : dof_handler.active_cell_iterators()) {
139 if (!soln_cell->is_locally_owned())
continue;
141 std::vector<dealii::types::global_dof_index> current_dofs_indices;
143 const int i_fele = soln_cell->active_fe_index();
144 const dealii::FESystem<dim, dim>& current_fe_ref = fe_collection[i_fele];
145 const int poly_degree = current_fe_ref.tensor_degree();
147 const unsigned int n_dofs_curr_cell = current_fe_ref.n_dofs_per_cell();
150 current_dofs_indices.resize(n_dofs_curr_cell);
151 soln_cell->get_dof_indices(current_dofs_indices);
154 std::array<std::vector<real>,
nstate> soln_coeff;
155 const unsigned int n_shape_fns = n_dofs_curr_cell /
nstate;
156 std::array<real, nstate> local_max;
157 std::array<real, nstate> local_min;
158 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
159 local_max[istate] = -1e9;
160 local_min[istate] = 1e9;
162 soln_coeff[istate].resize(n_shape_fns);
166 for (
unsigned int idof = 0; idof < n_dofs_curr_cell; ++idof) {
167 const unsigned int istate = fe_collection[poly_degree].system_to_component_index(idof).first;
168 const unsigned int ishape = fe_collection[poly_degree].system_to_component_index(idof).second;
169 soln_coeff[istate][ishape] = solution[current_dofs_indices[idof]];
171 if (soln_coeff[istate][ishape] > local_max[istate])
172 local_max[istate] = soln_coeff[istate][ishape];
174 if (soln_coeff[istate][ishape] < local_min[istate])
175 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::vector<real>, nstate> soln_at_q;
184 for (
int istate = 0; istate <
nstate; istate++) {
185 soln_at_q[istate].resize(n_quad_pts);
190 std::array<real, nstate> soln_cell_avg =
get_soln_cell_avg(soln_at_q, n_quad_pts, quad_weights);
193 std::array<real, nstate> theta;
194 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
198 if (local_max[istate] - soln_cell_avg[istate] != 0)
199 maxscale = local_max[istate] - soln_cell_avg[istate];
200 if (local_min[istate] - soln_cell_avg[istate] != 0)
201 minscale = local_min[istate] - soln_cell_avg[istate];
203 theta[istate] = std::min({ abs((
global_max[istate] - soln_cell_avg[istate]) / maxscale),
204 abs((
global_min[istate] - soln_cell_avg[istate]) / minscale), 1.0 });
208 for (
unsigned int istate = 0; istate <
nstate; ++istate) {
209 for (
unsigned int iquad = 0; iquad < n_quad_pts; ++iquad) {
210 soln_at_q[istate][iquad] = theta[istate] * (soln_at_q[istate][iquad] - soln_cell_avg[istate])
211 + soln_cell_avg[istate];
216 for (
int istate = 0; istate <
nstate; 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.
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.
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.
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)
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.
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)
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).
std::shared_ptr< BoundPreservingLimiter< dim, real > > tvbLimiter
Pointer to TVB limiter class (TVB limiter can be applied in conjunction with this limiter) ...