1 #include "positivity_preserving_tests.h" 2 #include "mesh/grids/positivity_preserving_tests_grid.h" 3 #include "mesh/grids/straight_periodic_cube.hpp" 4 #include <deal.II/grid/grid_generator.h> 5 #include "physics/physics_factory.h" 10 template <
int dim,
int nstate>
13 , unsteady_data_table_filename_with_extension(this->all_param.flow_solver_param.unsteady_data_table_filename+
".txt")
19 template <
int dim,
int nstate>
22 std::shared_ptr<Triangulation> grid = std::make_shared<Triangulation> (
30 std::cout <<
"Error: xmax and xmin need to be provided as parameters - Aborting... " << std::endl << std::flush;
37 std::cout <<
"Error: ymax and ymin need to be provided as parameters - Aborting... " << std::endl << std::flush;
44 std::cout <<
"Error: zmax and zmin need to be provided as parameters - Aborting... " << std::endl << std::flush;
51 if (dim==1 && (flow_case_type == flow_case_enum::sod_shock_tube
52 || flow_case_type == flow_case_enum::leblanc_shock_tube
53 || flow_case_type == flow_case_enum::shu_osher_problem)) {
56 else if (dim==2 && flow_case_type == flow_case_enum::shock_diffraction) {
59 else if (dim==2 && flow_case_type == flow_case_enum::astrophysical_jet) {
62 else if (dim==2 && flow_case_type == flow_case_enum::double_mach_reflection) {
65 else if (dim==2 && flow_case_type == flow_case_enum::strong_vortex_shock_wave) {
71 template <
int dim,
int nstate>
77 template<
int dim,
int nstate>
95 if (!soln_cell->is_locally_owned())
continue;
98 std::vector<dealii::types::global_dof_index> current_dofs_indices;
100 const int i_fele = soln_cell->active_fe_index();
101 const dealii::FESystem<dim, dim>& current_fe_ref = dg.
fe_collection[i_fele];
102 const int poly_degree = current_fe_ref.tensor_degree();
104 const unsigned int n_dofs_curr_cell = current_fe_ref.n_dofs_per_cell();
107 current_dofs_indices.resize(n_dofs_curr_cell);
108 soln_cell->get_dof_indices(current_dofs_indices);
111 std::array<std::vector<double>, nstate> soln_coeff;
112 const unsigned int n_shape_fns = n_dofs_curr_cell / nstate;
114 for (
unsigned int istate = 0; istate < nstate; ++istate) {
115 soln_coeff[istate].resize(n_shape_fns);
119 for (
unsigned int idof = 0; idof < n_dofs_curr_cell; ++idof) {
120 const unsigned int istate = dg.
fe_collection[poly_degree].system_to_component_index(idof).first;
121 const unsigned int ishape = dg.
fe_collection[poly_degree].system_to_component_index(idof).second;
122 soln_coeff[istate][ishape] = dg.
solution[current_dofs_indices[idof]];
127 std::array<std::vector<double>, nstate> soln_at_q;
130 for (
int istate = 0; istate < nstate; istate++) {
131 soln_at_q[istate].resize(n_quad_pts);
135 for (
unsigned int iquad = 0; iquad < n_quad_pts; ++iquad) {
137 if (soln_at_q[0][iquad] < 0) {
138 std::cout <<
"Flow Solver Error: Density is negative - Aborting... " << std::endl << std::flush;
142 if (soln_at_q[nstate - 1][iquad] < 0) {
143 std::cout <<
"Flow Solver Error: Total Energy is negative - Aborting... " << std::endl << std::flush;
147 if ((isnan(soln_at_q[0][iquad]))) {
148 std::cout <<
"Flow Solver Error: Density is NaN - Aborting... " << std::endl << std::flush;
155 template<
int dim,
int nstate>
161 this->
pcout <<
"ERROR: compute_integrated_quantities() is untested for nonuniform p. Aborting..." << std::endl;
165 double integrated_quantity = 0.0;
167 const unsigned int grid_degree = dg.
high_order_grid->fe_system.tensor_degree();
168 const unsigned int poly_degree = dg.
max_degree;
185 const bool store_vol_flux_nodes =
false;
186 const bool store_surf_flux_nodes =
false;
188 const unsigned int n_dofs = dg.
fe_collection[poly_degree].n_dofs_per_cell();
189 const unsigned int n_shape_fns = n_dofs / nstate;
190 std::vector<dealii::types::global_dof_index> dofs_indices (n_dofs);
191 auto metric_cell = dg.
high_order_grid->dof_handler_grid.begin_active();
194 if (!cell->is_locally_owned())
continue;
195 cell->get_dof_indices (dofs_indices);
198 const dealii::FESystem<dim> &fe_metric = dg.
high_order_grid->fe_system;
199 const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
200 const unsigned int n_grid_nodes = n_metric_dofs / dim;
201 std::vector<dealii::types::global_dof_index> metric_dof_indices(n_metric_dofs);
202 metric_cell->get_dof_indices (metric_dof_indices);
203 std::array<std::vector<double>,dim> mapping_support_points;
204 for(
int idim=0; idim<dim; idim++){
205 mapping_support_points[idim].resize(n_grid_nodes);
209 const std::vector<unsigned int > &index_renumbering = dealii::FETools::hierarchic_to_lexicographic_numbering<dim>(grid_degree);
210 for (
unsigned int idof = 0; idof< n_metric_dofs; ++idof) {
211 const double val = (dg.
high_order_grid->volume_nodes[metric_dof_indices[idof]]);
212 const unsigned int istate = fe_metric.system_to_component_index(idof).first;
213 const unsigned int ishape = fe_metric.system_to_component_index(idof).second;
214 const unsigned int igrid_node = index_renumbering[ishape];
215 mapping_support_points[istate][igrid_node] = val;
223 n_quad_pts, n_grid_nodes,
224 mapping_support_points,
233 std::array<std::vector<double>,nstate> soln_coeff;
234 for (
unsigned int idof = 0; idof < n_dofs; ++idof) {
235 const unsigned int istate = dg.
fe_collection[poly_degree].system_to_component_index(idof).first;
236 const unsigned int ishape = dg.
fe_collection[poly_degree].system_to_component_index(idof).second;
238 soln_coeff[istate].resize(n_shape_fns);
241 soln_coeff[istate][ishape] = dg.
solution(dofs_indices[idof]);
245 std::array<std::vector<double>,nstate> soln_at_q_vect;
246 for(
int istate=0; istate<nstate; istate++){
247 soln_at_q_vect[istate].resize(n_quad_pts);
254 for (
unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
256 std::array<double,nstate> soln_at_q;
258 for(
int istate=0; istate<nstate; istate++){
259 soln_at_q[istate] = soln_at_q_vect[istate][iquad];
265 const double quadrature_entropy = this->euler_physics->compute_numerical_entropy_function(soln_at_q);
267 if (isnan(quadrature_entropy)) std::cout <<
"WARNING: NaN entropy detected at a node!" << std::endl;
268 integrated_quantity += quadrature_entropy * quad_weights[iquad] * metric_oper.
det_Jac_vol[iquad];
274 integrated_quantity = dealii::Utilities::MPI::sum(integrated_quantity, this->
mpi_communicator);
276 return integrated_quantity;
279 template <
int dim,
int nstate>
283 const std::shared_ptr <dealii::TableHandler> unsteady_data_table)
286 const unsigned int current_iteration = ode_solver->current_iteration;
287 const double current_time = ode_solver->current_time;
293 const double entropy = current_numerical_entropy -
previous_numerical_entropy + ode_solver->FR_entropy_contribution_RRK_solver;
296 if (std::isnan(entropy)){
297 this->
pcout <<
"Entropy is nan. Aborting flow simulation..." << std::endl << std::flush;
300 if (current_iteration == 0)
initial_entropy = current_numerical_entropy;
302 if(nstate == dim + 2)
307 unsteady_data_table->add_value(
"iteration", current_iteration);
311 unsteady_data_table->set_scientific(
"entropy",
false);
313 unsteady_data_table->set_scientific(
"current_numerical_entropy",
false);
315 unsteady_data_table->set_scientific(
"U/Uo",
false);
320 unsteady_data_table->write_text(unsteady_data_table_file);
325 this->
pcout <<
" Iter: " << current_iteration
326 <<
" Time: " << std::setprecision(16) << current_time
327 <<
" Current Numerical Entropy: " << current_numerical_entropy
328 <<
" Entropy: " << entropy
331 this->
pcout << std::endl;
const Parameters::AllParameters all_param
All parameters.
const MPI_Comm mpi_communicator
MPI communicator.
void check_positivity_density(DGBase< dim, double > &dg)
Check positivity of density and total energy + verify that density is not NaN.
FlowCaseType
Selects the flow case to be simulated.
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
void compute_unsteady_data_and_write_to_table(const std::shared_ptr< ODE::ODESolverBase< dim, double >> ode_solver, const std::shared_ptr< DGBase< dim, double >> dg, const std::shared_ptr< dealii::TableHandler > unsteady_data_table) override
Compute the desired unsteady data and write it to a table.
FlowCaseType flow_case_type
Selected FlowCaseType from the input file.
double courant_friedrichs_lewy_number
Courant-Friedrich-Lewy (CFL) number for constant time step.
FlowSolverParam flow_solver_param
Contains the parameters for simulation cases (flow solver test)
double initial_entropy
Storing entropy at first step.
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
dealii::QGauss< 0 > oneD_face_quadrature
1D surface quadrature is always one single point for all poly degrees.
Files for the baseline physics.
unsigned int print_iteration_modulo
If ode_output==verbose, print every print_iteration_modulo iterations.
double compute_integrated_entropy(DGBase< dim, double > &dg) const
Updates the maximum local wave speed.
void build_1D_shape_functions_at_grid_nodes(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Constructs the volume operator and gradient operator.
unsigned int poly_degree
Polynomial order (P) of the basis functions for DG.
double previous_numerical_entropy
Store previous entropy.
Main parameter class that contains the various other sub-parameter classes.
const dealii::hp::FECollection< 1 > oneD_fe_collection_1state
1D Finite Element Collection for p-finite-element to represent the solution for a single state...
double grid_z_upper_bound
Maximum z bound of domain for a rectangle grid.
dealii::LinearAlgebra::distributed::Vector< double > solution
Current modal coefficients of the solution.
std::vector< real > det_Jac_vol
The determinant of the metric Jacobian at volume cubature nodes.
void add_value_to_data_table(const double value, const std::string value_string, const std::shared_ptr< dealii::TableHandler > data_table) const
Add a value to a given data table with scientific format.
ODESolverParam ode_solver_param
Contains parameters for ODE solver.
PositivityPreservingTests(const Parameters::AllParameters *const parameters_input)
Constructor.
const unsigned int max_degree
Maximum degree used for p-refi1nement.
Base metric operators class that stores functions used in both the volume and on surface.
double grid_top_bound
Maximum y bound of domain for a rectangle grid.
unsigned int get_max_fe_degree()
Gets the maximum value of currently active FE degree.
The mapping shape functions evaluated at the desired nodes (facet set included in volume grid nodes f...
Euler equations. Derived from PhysicsBase.
std::shared_ptr< HighOrderGrid< dim, real, MeshType > > high_order_grid
High order grid that will provide the MappingFEField.
const unsigned int max_grid_degree
Maximum grid degree used for hp-refi1nement.
dealii::FullMatrix< double > oneD_vol_operator
Stores the one dimensional volume operator.
static std::shared_ptr< PhysicsBase< dim, nstate, real > > create_Physics(const Parameters::AllParameters *const parameters_input, std::shared_ptr< ModelBase< dim, nstate, real > > model_input=nullptr)
Factory to return the correct physics given input file.
unsigned int get_min_fe_degree()
Gets the minimum value of currently active FE degree.
dealii::DoFHandler< dim > dof_handler
Finite Element Collection to represent the high-order grid.
const std::string unsteady_data_table_filename_with_extension
Filename (with extension) for the unsteady data table.
void build_volume_metric_operators(const unsigned int n_quad_pts, const unsigned int n_metric_dofs, const std::array< std::vector< real >, dim > &mapping_support_points, mapping_shape_functions< dim, n_faces, real > &mapping_basis, const bool use_invariant_curl_form=false)
Builds the volume metric operators.
double grid_right_bound
Right bound of domain for hyper_cube mesh based cases.
const int mpi_rank
MPI rank.
dealii::hp::QCollection< 1 > oneD_quadrature_collection
1D quadrature to generate Lagrange polynomials for the sake of flux interpolation.
DGBase is independent of the number of state variables.
dealii::ConditionalOStream pcout
ConditionalOStream.
dealii::hp::QCollection< dim > volume_quadrature_collection
Finite Element Collection to represent the high-order grid.
void build_1D_shape_functions_at_flux_nodes(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature, const dealii::Quadrature< 0 > &face_quadrature)
Constructs the volume, gradient, surface, and surface gradient operator.
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.
void display_additional_flow_case_specific_parameters() const override
Display additional more specific flow case parameters.
const dealii::hp::FECollection< dim > fe_collection
Finite Element Collection for p-finite-element to represent the solution.
Projection operator corresponding to basis functions onto M-norm (L2).
std::shared_ptr< Triangulation > generate_grid() const override
Function to generate the grid.