[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
periodic_turbulence.cpp
1 #include "periodic_turbulence.h"
2 #include "ode_solver/low_storage_runge_kutta_ode_solver.h"
3 #include <deal.II/base/function.h>
4 #include <stdlib.h>
5 #include <iostream>
6 #include <deal.II/dofs/dof_tools.h>
7 #include <deal.II/grid/grid_tools.h>
8 #include <deal.II/numerics/vector_tools.h>
9 #include <deal.II/fe/fe_values.h>
10 #include "physics/physics_factory.h"
11 #include <deal.II/base/table_handler.h>
12 #include <deal.II/base/tensor.h>
13 #include "math.h"
14 #include <string>
15 #include <deal.II/base/quadrature_lib.h>
16 
17 namespace PHiLiP {
18 
19 namespace FlowSolver {
20 
21 //=========================================================
22 // TURBULENCE IN PERIODIC CUBE DOMAIN
23 //=========================================================
24 template <int dim, int nstate>
26  : PeriodicCubeFlow<dim, nstate>(parameters_input)
27  , unsteady_data_table_filename_with_extension(this->all_param.flow_solver_param.unsteady_data_table_filename+".txt")
28  , number_of_times_to_output_velocity_field(this->all_param.flow_solver_param.number_of_times_to_output_velocity_field)
29  , output_velocity_field_at_fixed_times(this->all_param.flow_solver_param.output_velocity_field_at_fixed_times)
30  , output_vorticity_magnitude_field_in_addition_to_velocity(this->all_param.flow_solver_param.output_vorticity_magnitude_field_in_addition_to_velocity)
31  , output_flow_field_files_directory_name(this->all_param.flow_solver_param.output_flow_field_files_directory_name)
32  , output_solution_at_exact_fixed_times(this->all_param.ode_solver_param.output_solution_at_exact_fixed_times)
33 {
34  // Get the flow case type
35  using FlowCaseEnum = Parameters::FlowSolverParam::FlowCaseType;
36  const FlowCaseEnum flow_type = this->all_param.flow_solver_param.flow_case_type;
37 
38  // Flow case identifiers
39  this->is_taylor_green_vortex = (flow_type == FlowCaseEnum::taylor_green_vortex);
40  this->is_decaying_homogeneous_isotropic_turbulence = (flow_type == FlowCaseEnum::decaying_homogeneous_isotropic_turbulence);
41  this->is_viscous_flow = (this->all_param.pde_type != Parameters::AllParameters::PartialDifferentialEquation::euler);
43 
44  // Navier-Stokes object; create using dynamic_pointer_cast and the create_Physics factory
45  PHiLiP::Parameters::AllParameters parameters_navier_stokes = this->all_param;
46  parameters_navier_stokes.pde_type = Parameters::AllParameters::PartialDifferentialEquation::navier_stokes;
47  this->navier_stokes_physics = std::dynamic_pointer_cast<Physics::NavierStokes<dim,dim+2,double>>(
49 
50  /* Initialize integrated quantities as NAN;
51  done as a precaution in the case compute_integrated_quantities() is not called
52  before a member function of kind get_integrated_quantity() is called
53  */
54  std::fill(this->integrated_quantities.begin(), this->integrated_quantities.end(), NAN);
55 
58  exact_output_times_of_velocity_field_files_table = std::make_shared<dealii::TableHandler>();
60 
61  // Get output_velocity_field_times from string
62  const std::string output_velocity_field_times_string = this->all_param.flow_solver_param.output_velocity_field_times_string;
63  std::string line = output_velocity_field_times_string;
64  std::string::size_type sz1;
65  output_velocity_field_times[0] = std::stod(line,&sz1);
66  for(unsigned int i=1; i<number_of_times_to_output_velocity_field; ++i) {
67  line = line.substr(sz1);
68  sz1 = 0;
69  output_velocity_field_times[i] = std::stod(line,&sz1);
70  }
71 
72  // Get flow_field_quantity_filename_prefix
75  flow_field_quantity_filename_prefix += std::string("_vorticity");
76  }
77  }
78 
81  // If restarting, get the index of the current desired time to output velocity field based on the initial time
82  const double initial_simulation_time = this->all_param.ode_solver_param.initial_time;
83  for(unsigned int i=1; i<number_of_times_to_output_velocity_field; ++i) {
84  if((output_velocity_field_times[i-1] < initial_simulation_time) && (initial_simulation_time < output_velocity_field_times[i])) {
86  }
87  }
88  }
89 }
90 
91 template <int dim, int nstate>
93 {
94  this->pcout << "- - Courant-Friedrichs-Lewy number: " << this->all_param.flow_solver_param.courant_friedrichs_lewy_number << std::endl;
95  std::string flow_type_string;
97  this->pcout << "- - Freestream Reynolds number: " << this->all_param.navier_stokes_param.reynolds_number_inf << std::endl;
98  this->pcout << "- - Freestream Mach number: " << this->all_param.euler_param.mach_inf << std::endl;
99  }
100  this->display_grid_parameters();
101 }
102 
103 template <int dim, int nstate>
105 {
107  const double constant_time_step = this->all_param.flow_solver_param.constant_time_step;
108  this->pcout << "- - Using constant time step in FlowSolver parameters: " << constant_time_step << std::endl;
109  return constant_time_step;
110  } else {
111  const unsigned int number_of_degrees_of_freedom_per_state = dg->dof_handler.n_dofs()/nstate;
112  const double approximate_grid_spacing = (this->domain_right-this->domain_left)/pow(number_of_degrees_of_freedom_per_state,(1.0/dim));
113  const double constant_time_step = this->all_param.flow_solver_param.courant_friedrichs_lewy_number * approximate_grid_spacing;
114  return constant_time_step;
115  }
116 }
117 
118 std::string get_padded_mpi_rank_string(const int mpi_rank_input) {
119  // returns the mpi rank as a string with appropriate padding
120  std::string mpi_rank_string = std::to_string(mpi_rank_input);
121  const unsigned int length_of_mpi_rank_with_padding = 5;
122  const int number_of_zeros = length_of_mpi_rank_with_padding - mpi_rank_string.length();
123  mpi_rank_string.insert(0, number_of_zeros, '0');
124 
125  return mpi_rank_string;
126 }
127 
128 template<int dim, int nstate>
130  std::shared_ptr<DGBase<dim,double>> dg,
131  const unsigned int output_file_index,
132  const double current_time) const
133 {
134  this->pcout << " ... Writting velocity field ... " << std::flush;
135 
136  // NOTE: Same loop from read_values_from_file_and_project() in set_initial_condition.cpp
137 
138  // Get filename prefix based on output file index and the flow field quantity filename prefix
139  const std::string filename_prefix = flow_field_quantity_filename_prefix + std::string("-") + std::to_string(output_file_index);
140 
141  // (1) Get filename based on MPI rank
142  //-------------------------------------------------------------
143  // -- Get padded mpi rank string
144  const std::string mpi_rank_string = get_padded_mpi_rank_string(this->mpi_rank);
145  // -- Assemble filename string
146  const std::string filename_without_extension = filename_prefix + std::string("-") + mpi_rank_string;
147  const std::string filename = output_flow_field_files_directory_name + std::string("/") + filename_without_extension + std::string(".dat");
148  //-------------------------------------------------------------
149 
150  // (1.5) Write the exact output time for the file to the table
151  //-------------------------------------------------------------
152  if(this->mpi_rank==0) {
153  const std::string filename_for_time_table = output_flow_field_files_directory_name + std::string("/") + std::string("exact_output_times_of_velocity_field_files.txt");
154  // Add values to data table
155  this->add_value_to_data_table(output_file_index,"output_file_index",this->exact_output_times_of_velocity_field_files_table);
157  // Write to file
158  std::ofstream data_table_file(filename_for_time_table);
159  this->exact_output_times_of_velocity_field_files_table->write_text(data_table_file);
160  }
161  //-------------------------------------------------------------
162 
163  // (2) Write file
164  //-------------------------------------------------------------
165  std::ofstream FILE (filename);
166 
167  // check that the file is open and write DOFs
168  if (!FILE.is_open()) {
169  this->pcout << "ERROR: Cannot open file " << filename << std::endl;
170  std::abort();
171  } else if(this->mpi_rank==0) {
172  const unsigned int number_of_degrees_of_freedom_per_state = dg->dof_handler.n_dofs()/nstate;
173  FILE << number_of_degrees_of_freedom_per_state << std::string("\n");
174  }
175 
176  // build a basis oneD on equidistant nodes in 1D
177  dealii::Quadrature<1> vol_quad_equidistant_1D = dealii::QIterated<1>(dealii::QTrapez<1>(),dg->max_degree);
178  dealii::FE_DGQArbitraryNodes<1,1> equidistant_finite_element(vol_quad_equidistant_1D);
179 
180  const unsigned int init_grid_degree = dg->high_order_grid->fe_system.tensor_degree();
181  OPERATOR::basis_functions<dim,2*dim,double> soln_basis(1, dg->max_degree, init_grid_degree);
182  soln_basis.build_1D_volume_operator(dg->oneD_fe_collection_1state[dg->max_degree], vol_quad_equidistant_1D);
183  soln_basis.build_1D_gradient_operator(dg->oneD_fe_collection_1state[dg->max_degree], vol_quad_equidistant_1D);
184 
185  // mapping basis for the equidistant node set because we output the physical coordinates
186  OPERATOR::mapping_shape_functions<dim,2*dim,double> mapping_basis_at_equidistant(1, dg->max_degree, init_grid_degree);
187  mapping_basis_at_equidistant.build_1D_shape_functions_at_grid_nodes(dg->high_order_grid->oneD_fe_system, dg->high_order_grid->oneD_grid_nodes);
188  mapping_basis_at_equidistant.build_1D_shape_functions_at_flux_nodes(dg->high_order_grid->oneD_fe_system, vol_quad_equidistant_1D, dg->oneD_face_quadrature);
189 
190  const unsigned int max_dofs_per_cell = dg->dof_handler.get_fe_collection().max_dofs_per_cell();
191  std::vector<dealii::types::global_dof_index> current_dofs_indices(max_dofs_per_cell);
192  auto metric_cell = dg->high_order_grid->dof_handler_grid.begin_active();
193  for (auto current_cell = dg->dof_handler.begin_active(); current_cell!=dg->dof_handler.end(); ++current_cell, ++metric_cell) {
194  if (!current_cell->is_locally_owned()) continue;
195 
196  const int i_fele = current_cell->active_fe_index();
197  const unsigned int poly_degree = i_fele;
198  const unsigned int n_dofs_cell = dg->fe_collection[poly_degree].dofs_per_cell;
199  const unsigned int n_shape_fns = n_dofs_cell / nstate;
200  const unsigned int n_quad_pts = n_shape_fns;
201 
202  // We first need to extract the mapping support points (grid nodes) from high_order_grid.
203  const dealii::FESystem<dim> &fe_metric = dg->high_order_grid->fe_system;
204  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
205  const unsigned int n_grid_nodes = n_metric_dofs / dim;
206  std::vector<dealii::types::global_dof_index> metric_dof_indices(n_metric_dofs);
207  metric_cell->get_dof_indices (metric_dof_indices);
208  std::array<std::vector<double>,dim> mapping_support_points;
209  for(int idim=0; idim<dim; idim++){
210  mapping_support_points[idim].resize(n_grid_nodes);
211  }
212  // Get the mapping support points (physical grid nodes) from high_order_grid.
213  // Store it in such a way we can use sum-factorization on it with the mapping basis functions.
214  const std::vector<unsigned int > &index_renumbering = dealii::FETools::hierarchic_to_lexicographic_numbering<dim>(init_grid_degree);
215  for (unsigned int idof = 0; idof< n_metric_dofs; ++idof) {
216  const double val = (dg->high_order_grid->volume_nodes[metric_dof_indices[idof]]);
217  const unsigned int istate = fe_metric.system_to_component_index(idof).first;
218  const unsigned int ishape = fe_metric.system_to_component_index(idof).second;
219  const unsigned int igrid_node = index_renumbering[ishape];
220  mapping_support_points[istate][igrid_node] = val;
221  }
222  // Construct the metric operators
223  OPERATOR::metric_operators<double, dim, 2*dim> metric_oper_equid(nstate, poly_degree, init_grid_degree, true, false);
224  // Build the metric terms to compute the gradient and volume node positions.
225  // This functions will compute the determinant of the metric Jacobian and metric cofactor matrix.
226  // If flags store_vol_flux_nodes and store_surf_flux_nodes set as true it will also compute the physical quadrature positions.
227  metric_oper_equid.build_volume_metric_operators(
228  n_quad_pts, n_grid_nodes,
229  mapping_support_points,
230  mapping_basis_at_equidistant,
231  dg->all_parameters->use_invariant_curl_form);
232 
233 
234  current_dofs_indices.resize(n_dofs_cell);
235  current_cell->get_dof_indices (current_dofs_indices);
236 
237  std::array<std::vector<double>,nstate> soln_coeff;
238  for(unsigned int idof=0; idof<n_dofs_cell; idof++){
239  const unsigned int istate = dg->fe_collection[poly_degree].system_to_component_index(idof).first;
240  const unsigned int ishape = dg->fe_collection[poly_degree].system_to_component_index(idof).second;
241  if(ishape == 0) {
242  soln_coeff[istate].resize(n_shape_fns);
243  }
244  soln_coeff[istate][ishape] = dg->solution(current_dofs_indices[idof]);
245  }
246 
247  std::array<std::vector<double>,nstate> soln_at_q;
248  std::array<dealii::Tensor<1,dim,std::vector<double>>,nstate> soln_grad_at_q;
249  for(int istate=0; istate<nstate; istate++){
250  soln_at_q[istate].resize(n_quad_pts);
251  // Interpolate soln coeff to volume cubature nodes.
252  soln_basis.matrix_vector_mult_1D(soln_coeff[istate], soln_at_q[istate],
253  soln_basis.oneD_vol_operator);
254  // apply gradient of reference basis functions on the solution at volume cubature nodes
255  dealii::Tensor<1,dim,std::vector<double>> ref_gradient_basis_fns_times_soln;
256  for(int idim=0; idim<dim; idim++){
257  ref_gradient_basis_fns_times_soln[idim].resize(n_quad_pts);
258  }
259  soln_basis.gradient_matrix_vector_mult_1D(soln_coeff[istate], ref_gradient_basis_fns_times_soln,
260  soln_basis.oneD_vol_operator,
261  soln_basis.oneD_grad_operator);
262  // transform the gradient into a physical gradient operator scaled by determinant of metric Jacobian
263  // then apply the inner product in each direction
264  for(int idim=0; idim<dim; idim++){
265  soln_grad_at_q[istate][idim].resize(n_quad_pts);
266  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
267  for(int jdim=0; jdim<dim; jdim++){
268  //transform into the physical gradient
269  soln_grad_at_q[istate][idim][iquad] += metric_oper_equid.metric_cofactor_vol[idim][jdim][iquad]
270  * ref_gradient_basis_fns_times_soln[jdim][iquad]
271  / metric_oper_equid.det_Jac_vol[iquad];
272  }
273  }
274  }
275  }
276  // compute quantities at quad nodes (equisdistant)
277  dealii::Tensor<1,dim,std::vector<double>> velocity_at_q;
278  std::vector<double> vorticity_magnitude_at_q(n_quad_pts);
279  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
280  std::array<double,nstate> soln_state;
281  std::array<dealii::Tensor<1,dim,double>,nstate> soln_grad_state;
282  for(int istate=0; istate<nstate; istate++){
283  soln_state[istate] = soln_at_q[istate][iquad];
284  for(int idim=0; idim<dim; idim++){
285  soln_grad_state[istate][idim] = soln_grad_at_q[istate][idim][iquad];
286  }
287  }
288  const dealii::Tensor<1,dim,double> velocity = this->navier_stokes_physics->compute_velocities(soln_state);
289  for(int idim=0; idim<dim; idim++){
290  if(iquad==0)
291  velocity_at_q[idim].resize(n_quad_pts);
292  velocity_at_q[idim][iquad] = velocity[idim];
293  }
294 
295  // write vorticity magnitude field if desired
297  vorticity_magnitude_at_q[iquad] = this->navier_stokes_physics->compute_vorticity_magnitude(soln_state, soln_grad_state);
298  }
299  }
300  // write out all values at equidistant nodes
301  for(unsigned int ishape=0; ishape<n_shape_fns; ishape++){
302  dealii::Point<dim,double> vol_equid_node;
303  // write coordinates
304  for(int idim=0; idim<dim; idim++) {
305  vol_equid_node[idim] = metric_oper_equid.flux_nodes_vol[idim][ishape];
306  FILE << std::setprecision(17) << vol_equid_node[idim] << std::string(" ");
307  }
308  // write velocity field
309  for (int d=0; d<dim; ++d) {
310  FILE << std::setprecision(17) << velocity_at_q[d][ishape] << std::string(" ");
311  }
312  // write vorticity magnitude field if desired
314  FILE << std::setprecision(17) << vorticity_magnitude_at_q[ishape] << std::string(" ");
315  }
316  FILE << std::string("\n"); // next line
317  }
318  }
319  FILE.close();
320  this->pcout << "done." << std::endl;
321 }
322 
323 template<int dim, int nstate>
325 {
326  std::array<double,NUMBER_OF_INTEGRATED_QUANTITIES> integral_values;
327  std::fill(integral_values.begin(), integral_values.end(), 0.0);
328 
329  // Initialize the maximum local wave speed to zero; only used for adaptive time step
330  if(this->all_param.flow_solver_param.adaptive_time_step == true || this->all_param.flow_solver_param.error_adaptive_time_step == true) this->maximum_local_wave_speed = 0.0;
331 
332  // Overintegrate the error to make sure there is not integration error in the error estimate
333  int overintegrate = 10;
334 
335  // Set the quadrature of size dim and 1D for sum-factorization.
336  dealii::QGauss<dim> quad_extra(dg.max_degree+1+overintegrate);
337  dealii::QGauss<1> quad_extra_1D(dg.max_degree+1+overintegrate);
338 
339  const unsigned int n_quad_pts = quad_extra.size();
340  const unsigned int grid_degree = dg.high_order_grid->fe_system.tensor_degree();
341  const unsigned int poly_degree = dg.max_degree;
342  // Construct the basis functions and mapping shape functions.
343  OPERATOR::basis_functions<dim,2*dim,double> soln_basis(1, poly_degree, grid_degree);
344  OPERATOR::mapping_shape_functions<dim,2*dim,double> mapping_basis(1, poly_degree, grid_degree);
345  // Build basis function volume operator and gradient operator from 1D finite element for 1 state.
346  soln_basis.build_1D_volume_operator(dg.oneD_fe_collection_1state[poly_degree], quad_extra_1D);
347  soln_basis.build_1D_gradient_operator(dg.oneD_fe_collection_1state[poly_degree], quad_extra_1D);
348  // Build mapping shape functions operators using the oneD high_ordeR_grid finite element
349  mapping_basis.build_1D_shape_functions_at_grid_nodes(dg.high_order_grid->oneD_fe_system, dg.high_order_grid->oneD_grid_nodes);
350  mapping_basis.build_1D_shape_functions_at_flux_nodes(dg.high_order_grid->oneD_fe_system, quad_extra_1D, dg.oneD_face_quadrature);
351  const std::vector<double> &quad_weights = quad_extra.get_weights();
352  // If in the future we need the physical quadrature node location, turn these flags to true and the constructor will
353  // automatically compute it for you. Currently set to false as to not compute extra unused terms.
354  const bool store_vol_flux_nodes = false;//currently doesn't need the volume physical nodal position
355  const bool store_surf_flux_nodes = false;//currently doesn't need the surface physical nodal position
356 
357  const unsigned int n_dofs = dg.fe_collection[poly_degree].n_dofs_per_cell();
358  const unsigned int n_shape_fns = n_dofs / nstate;
359  std::vector<dealii::types::global_dof_index> dofs_indices (n_dofs);
360  auto metric_cell = dg.high_order_grid->dof_handler_grid.begin_active();
361  // Changed for loop to update metric_cell.
362  for (auto cell = dg.dof_handler.begin_active(); cell!= dg.dof_handler.end(); ++cell, ++metric_cell) {
363  if (!cell->is_locally_owned()) continue;
364  cell->get_dof_indices (dofs_indices);
365 
366  // We first need to extract the mapping support points (grid nodes) from high_order_grid.
367  const dealii::FESystem<dim> &fe_metric = dg.high_order_grid->fe_system;
368  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
369  const unsigned int n_grid_nodes = n_metric_dofs / dim;
370  std::vector<dealii::types::global_dof_index> metric_dof_indices(n_metric_dofs);
371  metric_cell->get_dof_indices (metric_dof_indices);
372  std::array<std::vector<double>,dim> mapping_support_points;
373  for(int idim=0; idim<dim; idim++){
374  mapping_support_points[idim].resize(n_grid_nodes);
375  }
376  // Get the mapping support points (physical grid nodes) from high_order_grid.
377  // Store it in such a way we can use sum-factorization on it with the mapping basis functions.
378  const std::vector<unsigned int > &index_renumbering = dealii::FETools::hierarchic_to_lexicographic_numbering<dim>(grid_degree);
379  for (unsigned int idof = 0; idof< n_metric_dofs; ++idof) {
380  const double val = (dg.high_order_grid->volume_nodes[metric_dof_indices[idof]]);
381  const unsigned int istate = fe_metric.system_to_component_index(idof).first;
382  const unsigned int ishape = fe_metric.system_to_component_index(idof).second;
383  const unsigned int igrid_node = index_renumbering[ishape];
384  mapping_support_points[istate][igrid_node] = val;
385  }
386  // Construct the metric operators.
387  OPERATOR::metric_operators<double, dim, 2*dim> metric_oper(nstate, poly_degree, grid_degree, store_vol_flux_nodes, store_surf_flux_nodes);
388  // Build the metric terms to compute the gradient and volume node positions.
389  // This functions will compute the determinant of the metric Jacobian and metric cofactor matrix.
390  // If flags store_vol_flux_nodes and store_surf_flux_nodes set as true it will also compute the physical quadrature positions.
391  metric_oper.build_volume_metric_operators(
392  n_quad_pts, n_grid_nodes,
393  mapping_support_points,
394  mapping_basis,
395  dg.all_parameters->use_invariant_curl_form);
396 
397  // Fetch the modal soln coefficients
398  // We immediately separate them by state as to be able to use sum-factorization
399  // in the interpolation operator. If we left it by n_dofs_cell, then the matrix-vector
400  // mult would sum the states at the quadrature point.
401  // That is why the basis functions are based off the 1state oneD fe_collection.
402  std::array<std::vector<double>,nstate> soln_coeff;
403  for (unsigned int idof = 0; idof < n_dofs; ++idof) {
404  const unsigned int istate = dg.fe_collection[poly_degree].system_to_component_index(idof).first;
405  const unsigned int ishape = dg.fe_collection[poly_degree].system_to_component_index(idof).second;
406  if(ishape == 0){
407  soln_coeff[istate].resize(n_shape_fns);
408  }
409 
410  soln_coeff[istate][ishape] = dg.solution(dofs_indices[idof]);
411  }
412  // Interpolate each state to the quadrature points using sum-factorization
413  // with the basis functions in each reference direction.
414  std::array<std::vector<double>,nstate> soln_at_q_vect;
415  std::array<dealii::Tensor<1,dim,std::vector<double>>,nstate> soln_grad_at_q_vect;
416  for(int istate=0; istate<nstate; istate++){
417  soln_at_q_vect[istate].resize(n_quad_pts);
418  // Interpolate soln coeff to volume cubature nodes.
419  soln_basis.matrix_vector_mult_1D(soln_coeff[istate], soln_at_q_vect[istate],
420  soln_basis.oneD_vol_operator);
421  // We need to first compute the reference gradient of the solution, then transform that to a physical gradient.
422  dealii::Tensor<1,dim,std::vector<double>> ref_gradient_basis_fns_times_soln;
423  for(int idim=0; idim<dim; idim++){
424  ref_gradient_basis_fns_times_soln[idim].resize(n_quad_pts);
425  soln_grad_at_q_vect[istate][idim].resize(n_quad_pts);
426  }
427  // Apply gradient of reference basis functions on the solution at volume cubature nodes.}
428  soln_basis.gradient_matrix_vector_mult_1D(soln_coeff[istate], ref_gradient_basis_fns_times_soln,
429  soln_basis.oneD_vol_operator,
430  soln_basis.oneD_grad_operator);
431  // Transform the reference gradient into a physical gradient operator.
432  for(int idim=0; idim<dim; idim++){
433  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
434  for(int jdim=0; jdim<dim; jdim++){
435  //transform into the physical gradient
436  soln_grad_at_q_vect[istate][idim][iquad] += metric_oper.metric_cofactor_vol[idim][jdim][iquad]
437  * ref_gradient_basis_fns_times_soln[jdim][iquad]
438  / metric_oper.det_Jac_vol[iquad];
439  }
440  }
441  }
442  }
443 
444  // Loop over quadrature nodes, compute quantities to be integrated, and integrate them.
445  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
446 
447  std::array<double,nstate> soln_at_q;
448  std::array<dealii::Tensor<1,dim,double>,nstate> soln_grad_at_q;
449  // Extract solution and gradient in a way that the physics ca n use them.
450  for(int istate=0; istate<nstate; istate++){
451  soln_at_q[istate] = soln_at_q_vect[istate][iquad];
452  for(int idim=0; idim<dim; idim++){
453  soln_grad_at_q[istate][idim] = soln_grad_at_q_vect[istate][idim][iquad];
454  }
455  }
456 
457  std::array<double,NUMBER_OF_INTEGRATED_QUANTITIES> integrand_values;
458  std::fill(integrand_values.begin(), integrand_values.end(), 0.0);
459  integrand_values[IntegratedQuantitiesEnum::kinetic_energy] = this->navier_stokes_physics->compute_kinetic_energy_from_conservative_solution(soln_at_q);
460  integrand_values[IntegratedQuantitiesEnum::enstrophy] = this->navier_stokes_physics->compute_enstrophy(soln_at_q,soln_grad_at_q);
461  integrand_values[IntegratedQuantitiesEnum::pressure_dilatation] = this->navier_stokes_physics->compute_pressure_dilatation(soln_at_q,soln_grad_at_q);
462  integrand_values[IntegratedQuantitiesEnum::deviatoric_strain_rate_tensor_magnitude_sqr] = this->navier_stokes_physics->compute_deviatoric_strain_rate_tensor_magnitude_sqr(soln_at_q,soln_grad_at_q);
463  integrand_values[IntegratedQuantitiesEnum::strain_rate_tensor_magnitude_sqr] = this->navier_stokes_physics->compute_strain_rate_tensor_magnitude_sqr(soln_at_q,soln_grad_at_q);
464 
465  for(int i_quantity=0; i_quantity<NUMBER_OF_INTEGRATED_QUANTITIES; ++i_quantity) {
466  integral_values[i_quantity] += integrand_values[i_quantity] * quad_weights[iquad] * metric_oper.det_Jac_vol[iquad];
467  }
468 
469  // Update the maximum local wave speed (i.e. convective eigenvalue) if using an adaptive time step
470  if(this->all_param.flow_solver_param.adaptive_time_step == true || this->all_param.flow_solver_param.error_adaptive_time_step == true) {
471  const double local_wave_speed = this->navier_stokes_physics->max_convective_eigenvalue(soln_at_q);
472  if(local_wave_speed > this->maximum_local_wave_speed) this->maximum_local_wave_speed = local_wave_speed;
473  }
474  }
475  }
476  this->maximum_local_wave_speed = dealii::Utilities::MPI::max(this->maximum_local_wave_speed, this->mpi_communicator);
477 
478  // update integrated quantities
479  for(int i_quantity=0; i_quantity<NUMBER_OF_INTEGRATED_QUANTITIES; ++i_quantity) {
480  this->integrated_quantities[i_quantity] = dealii::Utilities::MPI::sum(integral_values[i_quantity], this->mpi_communicator);
481  this->integrated_quantities[i_quantity] /= this->domain_size; // divide by total domain volume
482  }
483 }
484 
485 template<int dim, int nstate>
487 {
488  const double integrated_kinetic_energy = this->integrated_quantities[IntegratedQuantitiesEnum::kinetic_energy];
489  // // Abort if energy is nan
490  // if(std::isnan(integrated_kinetic_energy)) {
491  // this->pcout << " ERROR: Kinetic energy at time " << current_time << " is nan." << std::endl;
492  // this->pcout << " Consider decreasing the time step / CFL number." << std::endl;
493  // std::abort();
494  // }
495  return integrated_kinetic_energy;
496 }
497 
498 template<int dim, int nstate>
500 {
501  return this->integrated_quantities[IntegratedQuantitiesEnum::enstrophy];
502 }
503 
504 template<int dim, int nstate>
506 {
507  const double integrated_enstrophy = this->integrated_quantities[IntegratedQuantitiesEnum::enstrophy];
508  double vorticity_based_dissipation_rate = 0.0;
509  if (is_viscous_flow){
510  vorticity_based_dissipation_rate = this->navier_stokes_physics->compute_vorticity_based_dissipation_rate_from_integrated_enstrophy(integrated_enstrophy);
511  }
512  return vorticity_based_dissipation_rate;
513 }
514 
515 template<int dim, int nstate>
517 {
518  const double integrated_pressure_dilatation = this->integrated_quantities[IntegratedQuantitiesEnum::pressure_dilatation];
519  return (-1.0*integrated_pressure_dilatation); // See reference (listed in header file), equation (57b)
520 }
521 
522 template<int dim, int nstate>
524 {
525  const double integrated_deviatoric_strain_rate_tensor_magnitude_sqr = this->integrated_quantities[IntegratedQuantitiesEnum::deviatoric_strain_rate_tensor_magnitude_sqr];
526  double deviatoric_strain_rate_tensor_based_dissipation_rate = 0.0;
527  if (is_viscous_flow){
528  deviatoric_strain_rate_tensor_based_dissipation_rate =
529  this->navier_stokes_physics->compute_deviatoric_strain_rate_tensor_based_dissipation_rate_from_integrated_deviatoric_strain_rate_tensor_magnitude_sqr(integrated_deviatoric_strain_rate_tensor_magnitude_sqr);
530  }
531  return deviatoric_strain_rate_tensor_based_dissipation_rate;
532 }
533 
534 template<int dim, int nstate>
536 {
537  const double integrated_strain_rate_tensor_magnitude_sqr = this->integrated_quantities[IntegratedQuantitiesEnum::strain_rate_tensor_magnitude_sqr];
538  double strain_rate_tensor_based_dissipation_rate = 0.0;
539  if (is_viscous_flow){
540  strain_rate_tensor_based_dissipation_rate =
541  this->navier_stokes_physics->compute_strain_rate_tensor_based_dissipation_rate_from_integrated_strain_rate_tensor_magnitude_sqr(integrated_strain_rate_tensor_magnitude_sqr);
542  }
543  return strain_rate_tensor_based_dissipation_rate;
544 }
545 
546 template<int dim, int nstate>
548 {
550 }
551 
552 template<int dim, int nstate>
554  const std::shared_ptr <DGBase<dim, double>> dg
555  ) const
556 {
557  const double poly_degree = this->all_param.flow_solver_param.poly_degree;
558 
559  const unsigned int n_dofs_cell = dg->fe_collection[poly_degree].dofs_per_cell;
560  const unsigned int n_quad_pts = dg->volume_quadrature_collection[poly_degree].size();
561  const unsigned int n_shape_fns = n_dofs_cell / nstate;
562 
563  OPERATOR::vol_projection_operator<dim,2*dim,double> vol_projection(1, poly_degree, dg->max_grid_degree);
564  vol_projection.build_1D_volume_operator(dg->oneD_fe_collection_1state[poly_degree], dg->oneD_quadrature_collection[poly_degree]);
565 
566  // Construct the basis functions and mapping shape functions.
567  OPERATOR::basis_functions<dim,2*dim,double> soln_basis(1, poly_degree, dg->max_grid_degree);
568  soln_basis.build_1D_volume_operator(dg->oneD_fe_collection_1state[poly_degree], dg->oneD_quadrature_collection[poly_degree]);
569 
570  OPERATOR::mapping_shape_functions<dim,2*dim,double> mapping_basis(1, poly_degree, dg->max_grid_degree);
571  mapping_basis.build_1D_shape_functions_at_grid_nodes(dg->high_order_grid->oneD_fe_system, dg->high_order_grid->oneD_grid_nodes);
572  mapping_basis.build_1D_shape_functions_at_flux_nodes(dg->high_order_grid->oneD_fe_system, dg->oneD_quadrature_collection[poly_degree], dg->oneD_face_quadrature);
573 
574  std::vector<dealii::types::global_dof_index> dofs_indices (n_dofs_cell);
575 
576  double integrand_numerical_entropy_function=0;
577  double integral_numerical_entropy_function=0;
578  const std::vector<double> &quad_weights = dg->volume_quadrature_collection[poly_degree].get_weights();
579 
580  auto metric_cell = dg->high_order_grid->dof_handler_grid.begin_active();
581  // Changed for loop to update metric_cell.
582  for (auto cell = dg->dof_handler.begin_active(); cell!= dg->dof_handler.end(); ++cell, ++metric_cell) {
583  if (!cell->is_locally_owned()) continue;
584  cell->get_dof_indices (dofs_indices);
585 
586  // We first need to extract the mapping support points (grid nodes) from high_order_grid.
587  const dealii::FESystem<dim> &fe_metric = dg->high_order_grid->fe_system;
588  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
589  const unsigned int n_grid_nodes = n_metric_dofs / dim;
590  std::vector<dealii::types::global_dof_index> metric_dof_indices(n_metric_dofs);
591  metric_cell->get_dof_indices (metric_dof_indices);
592  std::array<std::vector<double>,dim> mapping_support_points;
593  for(int idim=0; idim<dim; idim++){
594  mapping_support_points[idim].resize(n_grid_nodes);
595  }
596  // Get the mapping support points (physical grid nodes) from high_order_grid.
597  // Store it in such a way we can use sum-factorization on it with the mapping basis functions.
598  const std::vector<unsigned int > &index_renumbering = dealii::FETools::hierarchic_to_lexicographic_numbering<dim>(dg->max_grid_degree);
599  for (unsigned int idof = 0; idof< n_metric_dofs; ++idof) {
600  const double val = (dg->high_order_grid->volume_nodes[metric_dof_indices[idof]]);
601  const unsigned int istate = fe_metric.system_to_component_index(idof).first;
602  const unsigned int ishape = fe_metric.system_to_component_index(idof).second;
603  const unsigned int igrid_node = index_renumbering[ishape];
604  mapping_support_points[istate][igrid_node] = val;
605  }
606  // Construct the metric operators.
607  OPERATOR::metric_operators<double, dim, 2*dim> metric_oper(nstate, poly_degree, dg->max_grid_degree, false, false);
608  // Build the metric terms to compute the gradient and volume node positions.
609  // This functions will compute the determinant of the metric Jacobian and metric cofactor matrix.
610  // If flags store_vol_flux_nodes and store_surf_flux_nodes set as true it will also compute the physical quadrature positions.
611  metric_oper.build_volume_metric_operators(
612  n_quad_pts, n_grid_nodes,
613  mapping_support_points,
614  mapping_basis,
615  dg->all_parameters->use_invariant_curl_form);
616 
617  // Fetch the modal soln coefficients
618  // We immediately separate them by state as to be able to use sum-factorization
619  // in the interpolation operator. If we left it by n_dofs_cell, then the matrix-vector
620  // mult would sum the states at the quadrature point.
621  // That is why the basis functions are based off the 1state oneD fe_collection.
622  std::array<std::vector<double>,nstate> soln_coeff;
623  for (unsigned int idof = 0; idof < n_dofs_cell; ++idof) {
624  const unsigned int istate = dg->fe_collection[poly_degree].system_to_component_index(idof).first;
625  const unsigned int ishape = dg->fe_collection[poly_degree].system_to_component_index(idof).second;
626  if(ishape == 0){
627  soln_coeff[istate].resize(n_shape_fns);
628  }
629  soln_coeff[istate][ishape] = dg->solution(dofs_indices[idof]);
630  }
631  // Interpolate each state to the quadrature points using sum-factorization
632  // with the basis functions in each reference direction.
633  std::array<std::vector<double>,nstate> soln_at_q;
634  for(int istate=0; istate<nstate; istate++){
635  soln_at_q[istate].resize(n_quad_pts);
636  // Interpolate soln coeff to volume cubature nodes.
637  soln_basis.matrix_vector_mult_1D(soln_coeff[istate], soln_at_q[istate],
638  soln_basis.oneD_vol_operator);
639  }
640 
641  // Loop over quadrature nodes, compute quantities to be integrated, and integrate them.
642  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
643 
644  std::array<double,nstate> soln_state;
645  // Extract solution in a way that the physics ca n use them.
646  for(int istate=0; istate<nstate; istate++){
647  soln_state[istate] = soln_at_q[istate][iquad];
648  }
649  integrand_numerical_entropy_function = this->navier_stokes_physics->compute_numerical_entropy_function(soln_state);
650  integral_numerical_entropy_function += integrand_numerical_entropy_function * quad_weights[iquad] * metric_oper.det_Jac_vol[iquad];
651  }
652  }
653  // update integrated quantities and return
654  const double mpi_integrated_numerical_entropy = dealii::Utilities::MPI::sum(integral_numerical_entropy_function, this->mpi_communicator);
655 
656  return mpi_integrated_numerical_entropy;
657 }
658 
659 
660 template <int dim, int nstate>
662  const double FR_entropy_contribution_RRK_solver,
663  const unsigned int current_iteration,
664  const std::shared_ptr <DGBase<dim, double>> dg)
665 {
666 
667  const double current_numerical_entropy = this->compute_current_integrated_numerical_entropy(dg);
668 
669  if (current_iteration==0) {
670  this->previous_numerical_entropy = current_numerical_entropy;
671  this->initial_numerical_entropy_abs = abs(current_numerical_entropy);
672  }
673 
674  const double current_numerical_entropy_change_FRcorrected = (current_numerical_entropy - this->previous_numerical_entropy + FR_entropy_contribution_RRK_solver)/this->initial_numerical_entropy_abs;
675  this->previous_numerical_entropy = current_numerical_entropy;
676  this->cumulative_numerical_entropy_change_FRcorrected+=current_numerical_entropy_change_FRcorrected;
677 
678 }
679 
680 template <int dim, int nstate>
682  const std::shared_ptr<ODE::ODESolverBase<dim, double>> ode_solver,
683  const std::shared_ptr <DGBase<dim, double>> dg,
684  const std::shared_ptr <dealii::TableHandler> unsteady_data_table)
685 {
686  //unpack current iteration and current time from ode solver
687  const unsigned int current_iteration = ode_solver->current_iteration;
688  const double current_time = ode_solver->current_time;
689  // Compute and update integrated quantities
691  // Get computed quantities
692  const double integrated_kinetic_energy = this->get_integrated_kinetic_energy();
693  const double integrated_enstrophy = this->get_integrated_enstrophy();
694  const double vorticity_based_dissipation_rate = this->get_vorticity_based_dissipation_rate();
695  const double pressure_dilatation_based_dissipation_rate = this->get_pressure_dilatation_based_dissipation_rate();
696  const double deviatoric_strain_rate_tensor_based_dissipation_rate = this->get_deviatoric_strain_rate_tensor_based_dissipation_rate();
697  const double strain_rate_tensor_based_dissipation_rate = this->get_strain_rate_tensor_based_dissipation_rate();
698 
700  const bool is_rrk = (this->all_param.ode_solver_param.ode_solver_type == ODEEnum::rrk_explicit_solver);
701  const double relaxation_parameter = ode_solver->relaxation_parameter_RRK_solver;
702 
704  this->update_numerical_entropy(ode_solver->FR_entropy_contribution_RRK_solver,current_iteration, dg);
705  }
706 
707  if(this->mpi_rank==0) {
708  // Add values to data table
709  this->add_value_to_data_table(current_time,"time",unsteady_data_table);
710  if(do_calculate_numerical_entropy) this->add_value_to_data_table(this->cumulative_numerical_entropy_change_FRcorrected,"numerical_entropy_scaled_cumulative",unsteady_data_table);
711  if(is_rrk) this->add_value_to_data_table(relaxation_parameter, "relaxation_parameter",unsteady_data_table);
712  this->add_value_to_data_table(integrated_kinetic_energy,"kinetic_energy",unsteady_data_table);
713  this->add_value_to_data_table(integrated_enstrophy,"enstrophy",unsteady_data_table);
714  if(is_viscous_flow) this->add_value_to_data_table(vorticity_based_dissipation_rate,"eps_vorticity",unsteady_data_table);
715  this->add_value_to_data_table(pressure_dilatation_based_dissipation_rate,"eps_pressure",unsteady_data_table);
716  if(is_viscous_flow) this->add_value_to_data_table(strain_rate_tensor_based_dissipation_rate,"eps_strain",unsteady_data_table);
717  if(is_viscous_flow) this->add_value_to_data_table(deviatoric_strain_rate_tensor_based_dissipation_rate,"eps_dev_strain",unsteady_data_table);
718  // Write to file
719  std::ofstream unsteady_data_table_file(this->unsteady_data_table_filename_with_extension);
720  unsteady_data_table->write_text(unsteady_data_table_file);
721  }
722  // Print to console
723  this->pcout << " Iter: " << current_iteration
724  << " Time: " << current_time
725  << " Energy: " << integrated_kinetic_energy
726  << " Enstrophy: " << integrated_enstrophy;
727  if(is_viscous_flow) {
728  this->pcout << " eps_vorticity: " << vorticity_based_dissipation_rate
729  << " eps_p+eps_strain: " << (pressure_dilatation_based_dissipation_rate + strain_rate_tensor_based_dissipation_rate);
730  }
732  this->pcout << " Num. Entropy cumulative, FR corrected: " << std::setprecision(16) << this->cumulative_numerical_entropy_change_FRcorrected;
733  }
734  if(is_rrk){
735  this->pcout << " Relaxation Parameter: " << std::setprecision(16) << relaxation_parameter;
736  }
737  this->pcout << std::endl;
738 
739  // Abort if energy is nan
740  if(std::isnan(integrated_kinetic_energy)) {
741  this->pcout << " ERROR: Kinetic energy at time " << current_time << " is nan." << std::endl;
742  this->pcout << " Consider decreasing the time step / CFL number." << std::endl;
743  std::abort();
744  }
745 
746  // Output velocity field for spectra obtaining kinetic energy spectra
748  const double time_step = this->get_time_step();
749  const double next_time = current_time + time_step;
751  // Check if current time is an output time
752  bool is_output_time = false; // default initialization
754  is_output_time = current_time == desired_time;
755  } else {
756  is_output_time = ((current_time<=desired_time) && (next_time>desired_time));
757  }
758  if(is_output_time) {
759  // Output velocity field for current index
761 
762  // Update index s.t. it never goes out of bounds
766  }
767  }
768  }
769 }
770 
771 #if PHILIP_DIM==3
773 #endif
774 
775 } // FlowSolver namespace
776 } // PHiLiP namespace
777 
const Parameters::AllParameters all_param
All parameters.
const MPI_Comm mpi_communicator
MPI communicator.
FlowCaseType
Selects the flow case to be simulated.
dealii::Tensor< 2, dim, std::vector< real > > metric_cofactor_vol
The volume metric cofactor matrix.
Definition: operators.h:1165
PartialDifferentialEquation pde_type
Store the PDE type to be solved.
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1082
double initial_time
Initial time at which we initialize the ODE solver with.
FlowCaseType flow_case_type
Selected FlowCaseType from the input file.
double courant_friedrichs_lewy_number
Courant-Friedrich-Lewy (CFL) number for constant time step.
bool adaptive_time_step
Flag for computing the time step on the fly.
const bool output_vorticity_magnitude_field_in_addition_to_velocity
Flag for outputting vorticity magnitude field in addition to velocity field at fixed times...
const bool output_solution_at_exact_fixed_times
Flag for outputting the solution at exact fixed times by decreasing the time step on the fly...
FlowSolverParam flow_solver_param
Contains the parameters for simulation cases (flow solver test)
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
Definition: dg_base.hpp:91
double constant_time_step
Constant time step.
dealii::FullMatrix< double > oneD_grad_operator
Stores the one dimensional gradient operator.
Definition: operators.h:363
double mach_inf
Mach number at infinity.
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1732
bool restart_computation_from_file
Restart computation from restart file.
double get_time_step() const
Getter for time step.
double get_deviatoric_strain_rate_tensor_based_dissipation_rate() const
dealii::QGauss< 0 > oneD_face_quadrature
1D surface quadrature is always one single point for all poly degrees.
Definition: dg_base.hpp:634
unsigned int index_of_current_desired_time_to_output_velocity_field
Index of current desired time to output velocity field.
Files for the baseline physics.
Definition: ADTypes.hpp:10
void output_velocity_field(std::shared_ptr< DGBase< dim, double >> dg, const unsigned int output_file_index, const double current_time) const
Output the velocity field to file.
const std::string output_flow_field_files_directory_name
Directory for writting flow field files.
Base class ODE solver.
const std::string unsteady_data_table_filename_with_extension
Filename (with extension) for the unsteady data table.
const double domain_left
Domain left-boundary value for generating the grid.
double initial_numerical_entropy_abs
Numerical entropy at initial time.
double reynolds_number_inf
Farfield Reynolds number.
double get_numerical_entropy(const std::shared_ptr< DGBase< dim, double >>) const
Retrieves cumulative_numerical_entropy_change_FRcorrected.
std::shared_ptr< dealii::TableHandler > exact_output_times_of_velocity_field_files_table
Data table storing the exact output times for the velocity field files.
EulerParam euler_param
Contains parameters for the Euler equations non-dimensionalization.
double previous_numerical_entropy
Numerical entropy at previous timestep.
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.
Definition: operators.cpp:2155
unsigned int poly_degree
Polynomial order (P) of the basis functions for DG.
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...
Definition: dg_base.hpp:627
bool do_calculate_numerical_entropy
For TGV, flag to calculate and write numerical entropy.
const bool output_velocity_field_at_fixed_times
Flag for outputting velocity field at fixed times.
bool do_calculate_numerical_entropy
Identifies if numerical entropy should be calculated; initialized as false.
std::string output_velocity_field_times_string
String of velocity field output times.
dealii::LinearAlgebra::distributed::Vector< double > solution
Current modal coefficients of the solution.
Definition: dg_base.hpp:409
std::vector< real > det_Jac_vol
The determinant of the metric Jacobian at volume cubature nodes.
Definition: operators.h:1171
void display_additional_flow_case_specific_parameters() const override
Display additional more specific flow case parameters.
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.
PeriodicTurbulence(const Parameters::AllParameters *const parameters_input)
Constructor.
dealii::Table< 1, double > output_velocity_field_times
Times at which to output the velocity field.
NavierStokesParam navier_stokes_param
Contains parameters for the Navier-Stokes equations non-dimensionalization.
void build_1D_gradient_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1102
bool is_viscous_flow
Identifies if viscous flow; initialized as true.
const unsigned int max_degree
Maximum degree used for p-refi1nement.
Definition: dg_base.hpp:104
Base metric operators class that stores functions used in both the volume and on surface.
Definition: operators.h:1086
void compute_and_update_integrated_quantities(DGBase< dim, double > &dg)
double get_constant_time_step(std::shared_ptr< DGBase< dim, double >> dg) const override
Function to compute the constant time step.
The mapping shape functions evaluated at the desired nodes (facet set included in volume grid nodes f...
Definition: operators.h:1026
const unsigned int number_of_times_to_output_velocity_field
Number of times to output the velocity field.
bool is_decaying_homogeneous_isotropic_turbulence
Identified if DHIT case; initialized as false.
std::shared_ptr< HighOrderGrid< dim, real, MeshType > > high_order_grid
High order grid that will provide the MappingFEField.
Definition: dg_base.hpp:655
void gradient_matrix_vector_mult_1D(const std::vector< real > &input_vect, dealii::Tensor< 1, dim, std::vector< real >> &output_vect, const dealii::FullMatrix< double > &basis, const dealii::FullMatrix< double > &gradient_basis)
Computes the gradient of a scalar using sum-factorization where the basis are the same in each direct...
Definition: operators.cpp:414
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.
bool is_taylor_green_vortex
Identifies if taylor green vortex case; initialized as false.
dealii::FullMatrix< double > oneD_vol_operator
Stores the one dimensional volume operator.
Definition: operators.h:355
double cumulative_numerical_entropy_change_FRcorrected
Cumulative change in numerical entropy.
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.
double compute_current_integrated_numerical_entropy(const std::shared_ptr< DGBase< dim, double >> dg) const
Calculate numerical entropy by matrix-vector product.
ODESolverEnum ode_solver_type
ODE solver type.
dealii::DoFHandler< dim > dof_handler
Finite Element Collection to represent the high-order grid.
Definition: dg_base.hpp:652
std::shared_ptr< Physics::NavierStokes< dim, dim+2, double > > navier_stokes_physics
Pointer to Navier-Stokes physics object for computing things on the fly.
const double domain_size
Domain size (length in 1D, area in 2D, and volume in 3D)
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.
Definition: operators.cpp:2294
const double domain_right
Domain right-boundary value for generating the grid.
double maximum_local_wave_speed
Maximum local wave speed (i.e. convective eigenvalue)
std::array< double, NUMBER_OF_INTEGRATED_QUANTITIES > integrated_quantities
Array for storing the integrated quantities; done for computational efficiency.
std::string flow_field_quantity_filename_prefix
Flow field quantity filename prefix.
DGBase is independent of the number of state variables.
Definition: dg_base.hpp:82
dealii::ConditionalOStream pcout
ConditionalOStream.
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.
Definition: operators.cpp:2164
void update_numerical_entropy(const double FR_entropy_contribution_RRK_solver, const unsigned int current_iteration, const std::shared_ptr< DGBase< dim, double >> dg)
Update numerical entropy variables.
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.
Definition: operators.cpp:308
const dealii::hp::FECollection< dim > fe_collection
Finite Element Collection for p-finite-element to represent the solution.
Definition: dg_base.hpp:597
dealii::Tensor< 1, dim, std::vector< real > > flux_nodes_vol
Stores the physical volume flux nodes.
Definition: operators.h:1180
Navier-Stokes equations. Derived from Euler for the convective terms, which is derived from PhysicsBa...
Definition: navier_stokes.h:12
Projection operator corresponding to basis functions onto M-norm (L2).
Definition: operators.h:694
void display_grid_parameters() const
Display grid parameters.