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) ...