[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
dg_base.cpp
1 #include<limits>
2 #include<fstream>
3 #include <deal.II/base/parameter_handler.h>
4 #include <deal.II/base/tensor.h>
5 
6 #include <deal.II/base/qprojector.h>
7 
8 #include <deal.II/grid/tria.h>
9 #include <deal.II/distributed/shared_tria.h>
10 #include <deal.II/distributed/tria.h>
11 
12 #include <deal.II/grid/grid_generator.h>
13 #include <deal.II/grid/grid_refinement.h>
14 
15 #include <deal.II/dofs/dof_handler.h>
16 #include <deal.II/dofs/dof_tools.h>
17 #include <deal.II/dofs/dof_renumbering.h>
18 
19 #include <deal.II/dofs/dof_accessor.h>
20 
21 #include <deal.II/lac/vector.h>
22 #include <deal.II/lac/dynamic_sparsity_pattern.h>
23 #include <deal.II/lac/sparse_matrix.h>
24 
25 #include <deal.II/fe/fe_dgq.h>
26 
27 //#include <deal.II/fe/mapping_q1.h> // Might need mapping_q
28 #include <deal.II/fe/mapping_q.h> // Might need mapping_q
29 #include <deal.II/fe/mapping_q_generic.h>
30 #include <deal.II/fe/mapping_manifold.h>
31 #include <deal.II/fe/mapping_fe_field.h>
32 
33 // Finally, we take our exact solution from the library as well as volume_quadrature
34 // and additional tools.
35 #include <EpetraExt_Transpose_RowMatrix.h>
36 #include <deal.II/distributed/grid_refinement.h>
37 #include <deal.II/dofs/dof_renumbering.h>
38 #include <deal.II/grid/grid_refinement.h>
39 #include <deal.II/numerics/data_out.h>
40 #include <deal.II/numerics/data_out_dof_data.h>
41 #include <deal.II/numerics/data_out_faces.h>
42 #include <deal.II/numerics/derivative_approximation.h>
43 #include <deal.II/numerics/vector_tools.h>
44 #include <deal.II/numerics/vector_tools.templates.h>
45 
46 #include "dg_base.hpp"
47 #include "global_counter.hpp"
48 #include "post_processor/physics_post_processor.h"
49 
50 unsigned int n_vmult;
51 unsigned int dRdW_form;
52 unsigned int dRdW_mult;
53 unsigned int dRdX_mult;
54 unsigned int d2R_mult;
55 
56 
57 namespace PHiLiP {
58 
59 template <int dim, int nspecies, typename real, typename MeshType>
61  const int nstate_input,
62  const Parameters::AllParameters *const parameters_input,
63  const unsigned int degree,
64  const unsigned int max_degree_input,
65  const unsigned int grid_degree_input,
66  const std::shared_ptr<Triangulation> triangulation_input)
67  : DGBase<dim,nspecies,real,MeshType>(nstate_input, parameters_input, degree, max_degree_input, grid_degree_input, triangulation_input, this->create_collection_tuple(max_degree_input, nstate_input, parameters_input))
68 { }
69 
70 template <int dim, int nspecies, typename real, typename MeshType>
72  const int nstate_input,
73  const Parameters::AllParameters *const parameters_input,
74  const unsigned int degree,
75  const unsigned int max_degree_input,
76  const unsigned int grid_degree_input,
77  const std::shared_ptr<Triangulation> triangulation_input,
78  const MassiveCollectionTuple collection_tuple)
79  : all_parameters(parameters_input)
80  , nstate(nstate_input)
81  , initial_degree(degree)
82  , max_degree(max_degree_input)
83  , max_grid_degree(grid_degree_input)
84  , triangulation(triangulation_input)
85  , fe_collection(std::get<0>(collection_tuple))
86  , volume_quadrature_collection(std::get<1>(collection_tuple))
87  , face_quadrature_collection(std::get<2>(collection_tuple))
88  , fe_collection_lagrange(std::get<3>(collection_tuple))
89  , oneD_fe_collection(std::get<4>(collection_tuple))
90  , oneD_fe_collection_1state(std::get<5>(collection_tuple))
91  , oneD_fe_collection_flux(std::get<6>(collection_tuple))
92  , oneD_quadrature_collection(std::get<7>(collection_tuple))
94  , dof_handler(*triangulation, true)
95  , high_order_grid(std::make_shared<HighOrderGrid<dim,real,MeshType>>(grid_degree_input, triangulation, all_parameters->check_valid_metric_Jacobian, all_parameters->do_renumber_dofs, all_parameters->output_high_order_grid))
98  , mpi_communicator(MPI_COMM_WORLD)
99  , pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(mpi_communicator)==0)
102 {
103 
106 
107  set_all_cells_fe_degree(degree);
108 
109 }
110 
111 template <int dim, int nspecies, typename real, typename MeshType>
113 {
114  high_order_grid->reinit();
115 
118 }
119 
120 template <int dim, int nspecies, typename real, typename MeshType>
122 {
123  high_order_grid = new_high_order_grid;
124  triangulation = high_order_grid->triangulation;
128 }
129 
130 
131 template <int dim, int nspecies, typename real, typename MeshType>
132 std::tuple<
133  //dealii::hp::MappingCollection<dim>, // Mapping
134  dealii::hp::FECollection<dim>, // Solution FE
135  dealii::hp::QCollection<dim>, // Volume quadrature
136  dealii::hp::QCollection<dim-1>, // Face quadrature
137  dealii::hp::FECollection<dim>, // Lagrange polynomials for strong form
138  dealii::hp::FECollection<1>, // Solution FE 1D
139  dealii::hp::FECollection<1>, // Solution FE 1D for a single state
140  dealii::hp::FECollection<1>, // Collocated flux basis 1D for Strong
141  dealii::hp::QCollection<1> >// 1D quadrature for strong form
143  const unsigned int max_degree,
144  const int nstate,
145  const Parameters::AllParameters *const parameters_input) const
146 {
147  dealii::hp::FECollection<dim> fe_coll;
148  dealii::hp::FECollection<1> fe_coll_1D;
149  dealii::hp::FECollection<1> fe_coll_1D_1state;
150  dealii::hp::QCollection<dim> volume_quad_coll;
151  dealii::hp::QCollection<dim-1> face_quad_coll;
152  dealii::hp::QCollection<1> oneD_quad_coll;
153 
154  dealii::hp::FECollection<dim> fe_coll_lagr;
155  dealii::hp::FECollection<1> fe_coll_lagr_1D;
156 
157  const unsigned int overintegration = parameters_input->overintegration;
158  using FluxNodes = Parameters::AllParameters::FluxNodes;
159  const FluxNodes flux_nodes_type = parameters_input->flux_nodes_type;
160 
161  // for p=0, we use a p=1 FE for collocation, since there's no p=0 quadrature for Gauss Lobatto (GLL)
162  if (flux_nodes_type==FluxNodes::GLL)
163  {
164  int degree = 1;
165  const unsigned int integration_strength = degree+1+overintegration;
166 
167  const dealii::FE_DGQ<dim> fe_dg(degree);
168  const dealii::FESystem<dim,dim> fe_system(fe_dg, nstate);
169  fe_coll.push_back (fe_system);
170 
171  const dealii::FE_DGQ<1> fe_dg_1D(degree);
172  const dealii::FESystem<1,1> fe_system_1D(fe_dg_1D, nstate);
173  fe_coll_1D.push_back (fe_system_1D);
174  const dealii::FESystem<1,1> fe_system_1D_1state(fe_dg_1D, 1);
175  fe_coll_1D_1state.push_back (fe_system_1D_1state);
176 
177  dealii::Quadrature<1> oneD_quad(integration_strength);
178  dealii::Quadrature<dim> volume_quad(integration_strength);
179  dealii::Quadrature<dim-1> face_quad(integration_strength); //removed const
180 
181  dealii::QGaussLobatto<1> oneD_quad_Gauss_Lobatto (integration_strength);
182  dealii::QGaussLobatto<dim> vol_quad_Gauss_Lobatto (integration_strength);
183  oneD_quad = oneD_quad_Gauss_Lobatto;
184  volume_quad = vol_quad_Gauss_Lobatto;
185 
186  if(dim == 1) {
187  dealii::QGauss<dim-1> face_quad_Gauss_Legendre (integration_strength);
188  face_quad = face_quad_Gauss_Legendre;
189  } else {
190  dealii::QGaussLobatto<dim-1> face_quad_Gauss_Lobatto (integration_strength);
191  face_quad = face_quad_Gauss_Lobatto;
192  }
193 
194  volume_quad_coll.push_back (volume_quad);
195  face_quad_coll.push_back (face_quad);
196  oneD_quad_coll.push_back (oneD_quad);
197 
198  dealii::FE_DGQArbitraryNodes<dim,dim> lagrange_poly(oneD_quad);
199  fe_coll_lagr.push_back (lagrange_poly);
200 
201  dealii::FE_DGQArbitraryNodes<1,1> lagrange_poly_1D(oneD_quad);
202  fe_coll_lagr_1D.push_back (lagrange_poly_1D);
203  }
204 
205  int minimum_degree = (flux_nodes_type==FluxNodes::GLL) ? 1 : 0;
206  for (unsigned int degree=minimum_degree; degree<=max_degree; ++degree) {
207 
208  // Solution FECollection
209  const dealii::FE_DGQ<dim> fe_dg(degree);
210  const dealii::FESystem<dim,dim> fe_system(fe_dg, nstate);
211  fe_coll.push_back (fe_system);
212 
213  const dealii::FE_DGQ<1> fe_dg_1D(degree);
214  const dealii::FESystem<1,1> fe_system_1D(fe_dg_1D, nstate);
215  fe_coll_1D.push_back (fe_system_1D);
216  const dealii::FESystem<1,1> fe_system_1D_1state(fe_dg_1D, 1);
217  fe_coll_1D_1state.push_back (fe_system_1D_1state);
218 
219  const unsigned int integration_strength = degree+1+overintegration;
220 
221  dealii::Quadrature<1> oneD_quad(integration_strength);
222  dealii::Quadrature<dim> volume_quad(integration_strength);
223  dealii::Quadrature<dim-1> face_quad(integration_strength); //removed const
224 
225  if (flux_nodes_type==FluxNodes::GLL) {
226  dealii::QGaussLobatto<1> oneD_quad_Gauss_Lobatto (integration_strength);
227  dealii::QGaussLobatto<dim> vol_quad_Gauss_Lobatto (integration_strength);
228  oneD_quad = oneD_quad_Gauss_Lobatto;
229  volume_quad = vol_quad_Gauss_Lobatto;
230 
231  if(dim == 1)
232  {
233  dealii::QGauss<dim-1> face_quad_Gauss_Legendre (integration_strength);
234  face_quad = face_quad_Gauss_Legendre;
235  }
236  else
237  {
238  dealii::QGaussLobatto<dim-1> face_quad_Gauss_Lobatto (integration_strength);
239  face_quad = face_quad_Gauss_Lobatto;
240  }
241  } else if(flux_nodes_type==FluxNodes::GL) {
242  dealii::QGauss<1> oneD_quad_Gauss_Legendre (integration_strength);
243  dealii::QGauss<dim> vol_quad_Gauss_Legendre (integration_strength);
244  dealii::QGauss<dim-1> face_quad_Gauss_Legendre (integration_strength);
245  oneD_quad = oneD_quad_Gauss_Legendre;
246  volume_quad = vol_quad_Gauss_Legendre;
247  face_quad = face_quad_Gauss_Legendre;
248  }
249 
250  volume_quad_coll.push_back (volume_quad);
251  face_quad_coll.push_back (face_quad);
252  oneD_quad_coll.push_back (oneD_quad);
253 
254  dealii::FE_DGQArbitraryNodes<dim,dim> lagrange_poly(oneD_quad);
255  fe_coll_lagr.push_back (lagrange_poly);
256 
257  dealii::FE_DGQArbitraryNodes<1,1> lagrange_poly_1d(oneD_quad);
258  fe_coll_lagr_1D.push_back (lagrange_poly_1d);
259  }
260  return std::make_tuple(fe_coll, volume_quad_coll, face_quad_coll, fe_coll_lagr, fe_coll_1D, fe_coll_1D_1state, fe_coll_lagr_1D, oneD_quad_coll);
261 }
262 
263 template <int dim, int nspecies, typename real, typename MeshType>
264 void DGBase<dim,nspecies,real,MeshType>::time_scale_solution_update ( dealii::LinearAlgebra::distributed::Vector<double> &solution_update, const real CFL ) const
265 {
266  std::vector<dealii::types::global_dof_index> dofs_indices;
267 
268  for (auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell) {
269 
270  if (!cell->is_locally_owned()) continue;
271 
272 
273  const int i_fele = cell->active_fe_index();
274  const dealii::FESystem<dim,dim> &fe_ref = fe_collection[i_fele];
275  const unsigned int n_dofs_cell = fe_ref.n_dofs_per_cell();
276 
277  dofs_indices.resize(n_dofs_cell);
278  cell->get_dof_indices (dofs_indices);
279 
280  const dealii::types::global_dof_index cell_index = cell->active_cell_index();
281 
282  const real dt = CFL * max_dt_cell[cell_index];
283  for (unsigned int idof = 0; idof < n_dofs_cell; ++idof) {
284  const dealii::types::global_dof_index dof_index = dofs_indices[idof];
285  solution_update[dof_index] *= dt;
286  }
287  }
288 }
289 
290 
291 template <int dim, int nspecies, typename real, typename MeshType>
293 {
294  triangulation->prepare_coarsening_and_refinement();
295  for (auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
296  {
297  if (cell->is_locally_owned()) cell->set_future_fe_index (degree);
298  }
299 
300  triangulation->execute_coarsening_and_refinement();
301 }
302 
303 template <int dim, int nspecies, typename real, typename MeshType>
305 {
306  unsigned int max_fe_degree = 0;
307 
308  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
309  if(cell->is_locally_owned() && cell->active_fe_index() > max_fe_degree)
310  max_fe_degree = cell->active_fe_index();
311 
312  return dealii::Utilities::MPI::max(max_fe_degree, MPI_COMM_WORLD);
313 }
314 
315 template <int dim, int nspecies, typename real, typename MeshType>
317 {
318  unsigned int min_fe_degree = max_degree;
319 
320  for(auto cell = dof_handler.begin_active(); cell != dof_handler.end(); ++cell)
321  if(cell->is_locally_owned() && cell->active_fe_index() < min_fe_degree)
322  min_fe_degree = cell->active_fe_index();
323 
324  return dealii::Utilities::MPI::min(min_fe_degree, MPI_COMM_WORLD);
325 }
326 
327 template <int dim, int nspecies, typename real, typename MeshType>
328 dealii::Point<dim> DGBase<dim,nspecies,real,MeshType>::coordinates_of_highest_refined_cell(bool check_for_p_refined_cell)
329 {
330  const int iproc = dealii::Utilities::MPI::this_mpi_process(mpi_communicator);
331  const dealii::Point<dim> unit_vertex = dealii::GeometryInfo<dim>::unit_cell_vertex(0);
332  double current_cell_diameter;
333  double min_diameter_local = high_order_grid->dof_handler_grid.begin_active()->diameter();
334  int max_cell_polynomial_order = 0;
335  int current_cell_polynomial_order = 0;
336  dealii::Point<dim> refined_cell_coord;
337 
338  if(check_for_p_refined_cell)
339  {
340  for (const auto &cell : dof_handler.active_cell_iterators())
341  {
342  if(!cell->is_locally_owned()) continue;
343  current_cell_polynomial_order = cell->active_fe_index();
344  if ((current_cell_polynomial_order > max_cell_polynomial_order) && (cell->is_locally_owned()))
345  {
346  max_cell_polynomial_order = current_cell_polynomial_order;
347  refined_cell_coord = cell->center();
348  }
349  }
350  }
351  else
352  {
353  for (const auto &cell : high_order_grid->dof_handler_grid.active_cell_iterators())
354  {
355  if(!cell->is_locally_owned()) continue;
356  current_cell_diameter = cell->diameter(); // For future dealii version: current_cell_diameter = cell->diameter(*(mapping_fe_field));
357  if ((min_diameter_local > current_cell_diameter) && (cell->is_locally_owned()))
358  {
359  min_diameter_local = current_cell_diameter;
360  refined_cell_coord = high_order_grid->mapping_fe_field->transform_unit_to_real_cell(cell, unit_vertex);
361  }
362  }
363  }
364 
365  dealii::Utilities::MPI::MinMaxAvg indexstore;
366  int processor_containing_refined_cell;
367 
368  if(check_for_p_refined_cell)
369  {
370  indexstore = dealii::Utilities::MPI::min_max_avg(max_cell_polynomial_order, mpi_communicator);
371  processor_containing_refined_cell = indexstore.max_index;
372  }
373  else
374  {
375  indexstore = dealii::Utilities::MPI::min_max_avg(min_diameter_local, mpi_communicator);
376  processor_containing_refined_cell = indexstore.min_index;
377  }
378 
379  double global_point[dim];
380 
381  if (iproc == processor_containing_refined_cell)
382  {
383  for (int i=0; i<dim; i++)
384  global_point[i] = refined_cell_coord[i];
385  }
386 
387  MPI_Bcast(global_point, dim, MPI_DOUBLE, processor_containing_refined_cell, mpi_communicator); // Update values in all processors
388 
389  for (int i=0; i<dim; i++)
390  refined_cell_coord[i] = global_point[i];
391 
392  return refined_cell_coord;
393  }
394 
395 template <int dim, int nspecies, typename real, typename MeshType>
396 template<typename DoFCellAccessorType>
398  const DoFCellAccessorType &cell,
399  const int iface,
400  const dealii::hp::FECollection<dim> fe_collection) const
401 {
402 
403  const unsigned int fe_index = cell->active_fe_index();
404  const unsigned int degree = fe_collection[fe_index].tensor_degree();
405  const unsigned int degsq = (degree == 0) ? 1 : degree * (degree+1);
406 
407  const unsigned int normal_direction = dealii::GeometryInfo<dim>::unit_normal_direction[iface];
408  const real vol_div_facearea = cell->extent_in_direction(normal_direction);
409 
410  const real penalty = degsq / vol_div_facearea * this->all_parameters->sipg_penalty_factor;// * 20;
411 
412  return penalty;
413 }
414 
415 template <int dim, int nspecies, typename real, typename MeshType>
416 template<typename DoFCellAccessorType1, typename DoFCellAccessorType2>
418  const DoFCellAccessorType1 &current_cell,
419  const DoFCellAccessorType2 &neighbor_cell) const
420 {
421  if (neighbor_cell->has_children()) {
422  // Only happens in 1D where neither faces have children, but neighbor has some children
423  // Can't do the computation now since we need to query the children's DoF
424  AssertDimension(dim,1);
425  return false;
426  } else if (neighbor_cell->is_ghost()) {
427  // In the case the neighbor is a ghost cell, we let the processor with the lower rank do the work on that face
428  // We cannot use the cell->index() because the index is relative to the distributed triangulation
429  // Therefore, the cell index of a ghost cell might be different to the physical cell index even if they refer to the same cell
430  return (current_cell->subdomain_id() < neighbor_cell->subdomain_id());
431  //return true;
432  } else {
433  // Locally owned neighbor cell
434  Assert(neighbor_cell->is_locally_owned(), dealii::ExcMessage("If not ghost, neighbor should be locally owned."));
435 
436  if (current_cell->index() < neighbor_cell->index()) {
437  // Cell with lower index does work
438  return true;
439  } else if (neighbor_cell->index() == current_cell->index()) {
440  // If both cells have same index
441  // See https://www.dealii.org/developer/doxygen/deal.II/classTriaAccessorBase.html#a695efcbe84fefef3e4c93ee7bdb446ad
442  // then cell at the lower level does the work
443  return (current_cell->level() < neighbor_cell->level());
444  }
445  return false;
446  }
447  Assert(0==1, dealii::ExcMessage("Should not have reached here. Somehow another possible case has not been considered when two cells have the same coarseness."));
448  return false;
449 }
450 
451 template <int dim, int nspecies, typename real, typename MeshType>
452 template<typename adtype>
454  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<dim, dim, false>> &current_cell,
455  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<dim, dim, false>> &current_metric_cell,
456  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
457  dealii::hp::FEValues<dim,dim> &fe_values_collection_volume,
458  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_int,
459  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_ext,
460  dealii::hp::FESubfaceValues<dim,dim> &fe_values_collection_subface,
461  dealii::hp::FEValues<dim,dim> &fe_values_collection_volume_lagrange,
462  OPERATOR::basis_functions<dim,2*dim> &soln_basis_int,
463  OPERATOR::basis_functions<dim,2*dim> &soln_basis_ext,
464  OPERATOR::basis_functions<dim,2*dim> &flux_basis_int,
465  OPERATOR::basis_functions<dim,2*dim> &flux_basis_ext,
466  OPERATOR::local_basis_stiffness<dim,2*dim> &flux_basis_stiffness,
467  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_int,
468  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_ext,
470  const bool compute_auxiliary_right_hand_side,//flag on whether computing the auxiliary variable's equations' residuals
471  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
472  std::array<dealii::LinearAlgebra::distributed::Vector<double>,dim> &rhs_aux)
473 {
474  std::vector<dealii::types::global_dof_index> current_dofs_indices;
475  std::vector<dealii::types::global_dof_index> neighbor_dofs_indices;
476 
477  // Current reference element related to this physical cell
478  const int i_fele = current_cell->active_fe_index();
479 
480  const dealii::FESystem<dim,dim> &current_fe_ref = fe_collection[i_fele];
481  const unsigned int n_dofs_curr_cell = current_fe_ref.n_dofs_per_cell();
482 
483  // Local vector contribution from each cell
484  std::vector<real> current_cell_rhs (n_dofs_curr_cell); // Defaults to 0.0 initialization
485  // Local vector contribution from each cell for Auxiliary equations
486  dealii::Tensor<1,dim,std::vector<real>> current_cell_rhs_aux;
487  if(compute_auxiliary_right_hand_side){
488  for(int idim=0; idim<dim; idim++){
489  current_cell_rhs_aux[idim].resize(n_dofs_curr_cell);// Defaults to 0.0 initialization
490  }
491  }
492 
493  // Obtain the mapping from local dof indices to global dof indices
494  current_dofs_indices.resize(n_dofs_curr_cell);
495  current_cell->get_dof_indices (current_dofs_indices);
496 
497  const unsigned int grid_degree = this->high_order_grid->fe_system.tensor_degree();
498  const unsigned int poly_degree = i_fele;
499 
500  const unsigned int n_metric_dofs_cell = high_order_grid->fe_system.dofs_per_cell;
501  std::vector<dealii::types::global_dof_index> current_metric_dofs_indices(n_metric_dofs_cell);
502  std::vector<dealii::types::global_dof_index> neighbor_metric_dofs_indices(n_metric_dofs_cell);
503  current_metric_cell->get_dof_indices (current_metric_dofs_indices);
504 
505  const dealii::types::global_dof_index current_cell_index = current_cell->active_cell_index();
506 
507  OPERATOR::metric_operators<adtype,dim,2*dim> metric_oper_int(nstate, poly_degree, grid_degree,
510 
511  //flag to terminate if strong form and implicit
512  if((this->all_parameters->use_weak_form==false)
513  && (this->all_parameters->ode_solver_param.ode_solver_type
514  == Parameters::ODESolverParam::ODESolverEnum::implicit_solver)
515  && (this->use_auxiliary_eq || this->all_parameters->using_wall_model))
516  {
517  if(this->use_auxiliary_eq)
518  {
519  pcout<<"ERROR: Implicit does not currently work for strong form with Auxiliary Equation. The added terms dR/dq * dq/du needs to be added. Aborting..."<<std::endl;
520  }
521  else
522  {
523  pcout<<"ERROR: Implicit does not currently work for strong form with wall model. The Jacobian dR/du does not account for the neighboring solution at the wall. Aborting..."<<std::endl;
524  }
525  std::abort();
526  }
527 
528  std::array<std::vector<adtype>,dim> mapping_support_points;
529 
531  current_cell,
532  current_cell_index,
533  current_dofs_indices,
534  current_metric_dofs_indices,
535  poly_degree,
536  grid_degree,
537  soln_basis_int,
538  flux_basis_int,
539  flux_basis_stiffness,
540  soln_basis_projection_oper_int,
541  soln_basis_projection_oper_ext,
542  metric_oper_int,
543  mapping_basis,
544  mapping_support_points,
545  fe_values_collection_volume,
546  fe_values_collection_volume_lagrange,
547  current_fe_ref,
548  current_cell_rhs,
549  current_cell_rhs_aux,
550  compute_auxiliary_right_hand_side,
551  compute_dRdW, compute_dRdX, compute_d2R);
552 
553  (void) fe_values_collection_face_int;
554  (void) fe_values_collection_face_ext;
555  (void) fe_values_collection_subface;
556  for (unsigned int iface=0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface) {
557 
558  auto current_face = current_cell->face(iface);
559 
560  // CASE 1: FACE AT BOUNDARY
561  if ((current_face->at_boundary() && !current_cell->has_periodic_neighbor(iface)))
562  {
563  const real penalty = evaluate_penalty_scaling (current_cell, iface, fe_collection);
564 
565  const unsigned int boundary_id = current_face->boundary_id();
566 
568  current_cell,
569  current_cell_index,
570  iface,
571  boundary_id,
572  penalty,
573  current_dofs_indices,
574  current_metric_dofs_indices,
575  poly_degree,
576  grid_degree,
577  soln_basis_int,
578  flux_basis_int,
579  soln_basis_projection_oper_int,
580  metric_oper_int,
581  mapping_basis,
582  mapping_support_points,
583  fe_values_collection_face_int,
584  current_fe_ref,
585  current_cell_rhs,
586  current_cell_rhs_aux,
587  compute_auxiliary_right_hand_side,
588  compute_dRdW, compute_dRdX, compute_d2R);
589 
590  }
591  // CASE 2: PERIODIC BOUNDARY CONDITIONS
592  // NOTE: Periodicity is not adapted for hp adaptivity yet. this needs to be figured out in the future
593  else if (current_face->at_boundary() && current_cell->has_periodic_neighbor(iface))
594  {
595 
596  const auto neighbor_cell = current_cell->periodic_neighbor(iface);
597 
598  if (!current_cell->periodic_neighbor_is_coarser(iface) && current_cell_should_do_the_work(current_cell, neighbor_cell))
599  {
600  Assert (current_cell->periodic_neighbor(iface).state() == dealii::IteratorState::valid, dealii::ExcInternalError());
601 
602  const unsigned int n_dofs_neigh_cell = fe_collection[neighbor_cell->active_fe_index()].n_dofs_per_cell();
603  std::vector<real> neighbor_cell_rhs (n_dofs_neigh_cell); // Defaults to 0.0 initialization
604 
605  // Obtain the mapping from local dof indices to global dof indices for neighbor cell
606  neighbor_dofs_indices.resize(n_dofs_neigh_cell);
607  neighbor_cell->get_dof_indices (neighbor_dofs_indices);
608 
609  // Corresponding face of the neighbor.
610  const unsigned int neighbor_iface = current_cell->periodic_neighbor_of_periodic_neighbor(iface);
611 
612  const int i_fele_n = neighbor_cell->active_fe_index();
613 
614  // Compute penalty.
615  const real penalty1 = evaluate_penalty_scaling (current_cell, iface, fe_collection);
616  const real penalty2 = evaluate_penalty_scaling (neighbor_cell, neighbor_iface, fe_collection);
617  const real penalty = 0.5 * (penalty1 + penalty2);
618 
619  const dealii::types::global_dof_index neighbor_cell_index = neighbor_cell->active_cell_index();
620  const auto metric_neighbor_cell = current_metric_cell->periodic_neighbor(iface);
621  metric_neighbor_cell->get_dof_indices(neighbor_metric_dofs_indices);
622 
623  const unsigned int poly_degree_ext = i_fele_n;
624  const unsigned int grid_degree_ext = this->high_order_grid->fe_system.tensor_degree();
625  //constructor doesn't build anything
626  OPERATOR::metric_operators<adtype,dim,2*dim> metric_oper_ext(nstate, poly_degree_ext, grid_degree_ext,
629 
630  const dealii::FESystem<dim,dim> &neighbor_fe_ref = fe_collection[i_fele_n];
632  current_cell,
633  neighbor_cell,
634  current_cell_index,
635  neighbor_cell_index,
636  iface,
637  neighbor_iface,
638  penalty,
639  fe_values_collection_face_int,
640  fe_values_collection_face_ext,
641  fe_values_collection_subface,
642  current_fe_ref,
643  neighbor_fe_ref,
644  current_dofs_indices,
645  neighbor_dofs_indices,
646  current_metric_dofs_indices,
647  neighbor_metric_dofs_indices,
648  poly_degree,
649  poly_degree_ext,
650  grid_degree,
651  grid_degree_ext,
652  soln_basis_int,
653  soln_basis_ext,
654  flux_basis_int,
655  flux_basis_ext,
656  flux_basis_stiffness,
657  soln_basis_projection_oper_int,
658  soln_basis_projection_oper_ext,
659  metric_oper_int,
660  metric_oper_ext,
661  mapping_basis,
662  mapping_support_points,
663  current_cell_rhs,
664  neighbor_cell_rhs,
665  current_cell_rhs_aux,
666  rhs,
667  rhs_aux,
668  compute_auxiliary_right_hand_side,
669  compute_dRdW, compute_dRdX, compute_d2R);
670  }
671  }
672  // CASE 3: NEIGHBOUR IS FINER
673  // Occurs if the face has children
674  else if (current_cell->face(iface)->has_children())
675  {
676  // Do nothing.
677  // The face contribution from the current cell will appear then the finer neighbor cell is assembled.
678  }
679  // CASE 4: NEIGHBOR IS COARSER
680  // Assemble face residual.
681  else if (current_cell->neighbor(iface)->face(current_cell->neighbor_face_no(iface))->has_children())
682  {
683  Assert (current_cell->neighbor(iface).state() == dealii::IteratorState::valid, dealii::ExcInternalError());
684  Assert (!(current_cell->neighbor(iface)->has_children()), dealii::ExcInternalError());
685 
686  // Obtain cell neighbour
687  const auto neighbor_cell = current_cell->neighbor(iface);
688  const unsigned int neighbor_iface = current_cell->neighbor_face_no(iface);
689 
690  // Find corresponding subface
691  unsigned int neighbor_i_subface = 0;
692  unsigned int n_subface = dealii::GeometryInfo<dim>::n_subfaces(neighbor_cell->subface_case(neighbor_iface));
693 
694  for (; neighbor_i_subface < n_subface; ++neighbor_i_subface) {
695  if (neighbor_cell->neighbor_child_on_subface (neighbor_iface, neighbor_i_subface) == current_cell) {
696  break;
697  }
698  }
699  Assert(neighbor_i_subface != n_subface, dealii::ExcInternalError());
700 
701  const int i_fele_n = neighbor_cell->active_fe_index();//, i_quad_n = i_fele_n, i_mapp_n = 0;
702 
703  const unsigned int n_dofs_neigh_cell = fe_collection[i_fele_n].n_dofs_per_cell();
704  std::vector<real> neighbor_cell_rhs (n_dofs_neigh_cell); // Defaults to 0.0 initialization
705 
706  // Obtain the mapping from local dof indices to global dof indices for neighbor cell
707  neighbor_dofs_indices.resize(n_dofs_neigh_cell);
708  neighbor_cell->get_dof_indices (neighbor_dofs_indices);
709 
710  const real penalty1 = evaluate_penalty_scaling (current_cell, iface, fe_collection);
711  const real penalty2 = evaluate_penalty_scaling (neighbor_cell, neighbor_iface, fe_collection);
712  const real penalty = 0.5 * (penalty1 + penalty2);
713 
714  const dealii::types::global_dof_index neighbor_cell_index = neighbor_cell->active_cell_index();
715  const auto metric_neighbor_cell = current_metric_cell->neighbor(iface);
716  metric_neighbor_cell->get_dof_indices(neighbor_metric_dofs_indices);
717 
718  const unsigned int poly_degree_ext = i_fele_n;
719  const unsigned int grid_degree_ext = this->high_order_grid->fe_system.tensor_degree();
720  //Check if the poly degree or mapping changed order, in which case, then we re-compute the corresponding basis
721  OPERATOR::metric_operators<adtype,dim,2*dim> metric_oper_ext(nstate, poly_degree_ext, grid_degree_ext,
724 
725  const dealii::FESystem<dim,dim> &neighbor_fe_ref = fe_collection[i_fele_n];
727  current_cell,
728  neighbor_cell,
729  current_cell_index,
730  neighbor_cell_index,
731  iface,
732  neighbor_iface,
733  penalty,
734  fe_values_collection_face_int,
735  fe_values_collection_face_ext,
736  fe_values_collection_subface,
737  current_fe_ref,
738  neighbor_fe_ref,
739  current_dofs_indices,
740  neighbor_dofs_indices,
741  current_metric_dofs_indices,
742  neighbor_metric_dofs_indices,
743  poly_degree,
744  poly_degree_ext,
745  grid_degree,
746  grid_degree_ext,
747  soln_basis_int,
748  soln_basis_ext,
749  flux_basis_int,
750  flux_basis_ext,
751  flux_basis_stiffness,
752  soln_basis_projection_oper_int,
753  soln_basis_projection_oper_ext,
754  metric_oper_int,
755  metric_oper_ext,
756  mapping_basis,
757  mapping_support_points,
758  current_cell_rhs,
759  neighbor_cell_rhs,
760  current_cell_rhs_aux,
761  rhs,
762  rhs_aux,
763  compute_auxiliary_right_hand_side,
764  compute_dRdW, compute_dRdX, compute_d2R,
765  true,
766  neighbor_i_subface);
767  }
768  // CASE 5: NEIGHBOR CELL HAS SAME COARSENESS
769  // Therefore, we need to choose one of them to do the work
770  else if (current_cell_should_do_the_work(current_cell, current_cell->neighbor(iface)))
771  {
772  Assert (current_cell->neighbor(iface).state() == dealii::IteratorState::valid, dealii::ExcInternalError());
773 
774  const auto neighbor_cell = current_cell->neighbor_or_periodic_neighbor(iface);
775  // Corresponding face of the neighbor.
776  // e.g. The 4th face of the current cell might correspond to the 3rd face of the neighbor
777  const unsigned int neighbor_iface = current_cell->neighbor_of_neighbor(iface);
778 
779  // Get information about neighbor cell
780  const unsigned int n_dofs_neigh_cell = fe_collection[neighbor_cell->active_fe_index()].n_dofs_per_cell();
781 
782  // Local rhs contribution from neighbor
783  std::vector<real> neighbor_cell_rhs (n_dofs_neigh_cell); // Defaults to 0.0 initialization
784 
785  // Obtain the mapping from local dof indices to global dof indices for neighbor cell
786  neighbor_dofs_indices.resize(n_dofs_neigh_cell);
787  neighbor_cell->get_dof_indices (neighbor_dofs_indices);
788 
789  const int i_fele_n = neighbor_cell->active_fe_index();
790 
791  // Compute penalty.
792  const real penalty1 = evaluate_penalty_scaling (current_cell, iface, fe_collection);
793  const real penalty2 = evaluate_penalty_scaling (neighbor_cell, neighbor_iface, fe_collection);
794  const real penalty = 0.5 * (penalty1 + penalty2);
795 
796  const dealii::types::global_dof_index neighbor_cell_index = neighbor_cell->active_cell_index();
797  const auto metric_neighbor_cell = current_metric_cell->neighbor_or_periodic_neighbor(iface);
798  metric_neighbor_cell->get_dof_indices(neighbor_metric_dofs_indices);
799 
800  const unsigned int poly_degree_ext = i_fele_n;
801  // In future high_order_grids dof object/metric_cell should store the cell's fe degree.
802  // For now high_order_grid only handles all cells of same grid degree.
803  const unsigned int grid_degree_ext = this->high_order_grid->fe_system.tensor_degree();
804  //Check if the poly degree or mapping changed order, in which case, then we re-compute the corresponding basis
805  OPERATOR::metric_operators<adtype,dim,2*dim> metric_oper_ext(nstate, poly_degree_ext, grid_degree_ext,
808 
809  const dealii::FESystem<dim,dim> &neighbor_fe_ref = fe_collection[i_fele_n];
811  current_cell,
812  neighbor_cell,
813  current_cell_index,
814  neighbor_cell_index,
815  iface,
816  neighbor_iface,
817  penalty,
818  fe_values_collection_face_int,
819  fe_values_collection_face_ext,
820  fe_values_collection_subface,
821  current_fe_ref,
822  neighbor_fe_ref,
823  current_dofs_indices,
824  neighbor_dofs_indices,
825  current_metric_dofs_indices,
826  neighbor_metric_dofs_indices,
827  poly_degree,
828  poly_degree_ext,
829  grid_degree,
830  grid_degree_ext,
831  soln_basis_int,
832  soln_basis_ext,
833  flux_basis_int,
834  flux_basis_ext,
835  flux_basis_stiffness,
836  soln_basis_projection_oper_int,
837  soln_basis_projection_oper_ext,
838  metric_oper_int,
839  metric_oper_ext,
840  mapping_basis,
841  mapping_support_points,
842  current_cell_rhs,
843  neighbor_cell_rhs,
844  current_cell_rhs_aux,
845  rhs,
846  rhs_aux,
847  compute_auxiliary_right_hand_side,
848  compute_dRdW, compute_dRdX, compute_d2R);
849  }
850  else {
851  // Should be faces where the neighbor cell has the same coarseness
852  // but will be evaluated when we visit the other cell.
853  }
854  } // end of face loop
855 
856  if(compute_auxiliary_right_hand_side) {
857  // Add local contribution from current cell to global vector
858  for(int idim=0; idim<dim; idim++){
859  for (unsigned int idof=0; idof<n_dofs_curr_cell; ++idof) {
860  rhs_aux[idim][current_dofs_indices[idof]] += current_cell_rhs_aux[idim][idof];
861  }
862  }
863  }
864  else {
865  // Add local contribution from current cell to global vector
866  for (unsigned int idof=0; idof<n_dofs_curr_cell; ++idof) {
867  rhs[current_dofs_indices[idof]] += current_cell_rhs[idof];
868  }
869  }
870 }
871 
872 // Double version
873 template <int dim, int nspecies, typename real, typename MeshType>
875  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
876  const dealii::types::global_dof_index current_cell_index,
877  const std::vector<dealii::types::global_dof_index> &soln_dofs_indices,
878  const std::vector<dealii::types::global_dof_index> &metric_dofs_indices,
879  const unsigned int poly_degree,
880  const unsigned int grid_degree,
883  OPERATOR::local_basis_stiffness<dim,2*dim> &flux_basis_stiffness,
884  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_int,
885  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_ext,
888  std::array<std::vector<double>,dim> &mapping_support_points,
889  dealii::hp::FEValues<dim,dim> &fe_values_collection_volume,
890  dealii::hp::FEValues<dim,dim> &fe_values_collection_volume_lagrange,
891  const dealii::FESystem<dim,dim> &fe_soln,
892  std::vector<real> &local_rhs_cell,
893  dealii::Tensor<1,dim,std::vector<real>> &local_auxiliary_RHS,
894  const bool compute_auxiliary_right_hand_side,
895  const bool /*compute_dRdW*/, const bool /*compute_dRdX*/, const bool /*compute_d2R*/)
896 {
897  const unsigned int n_soln_dofs = fe_soln.dofs_per_cell;
898 
899  AssertDimension (n_soln_dofs, soln_dofs_indices.size());
900 
901  const unsigned int n_metric_dofs = this->high_order_grid->fe_system.dofs_per_cell;
902 
903  std::vector<real> local_dual(n_soln_dofs);
904  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
905  local_dual[itest] = 0.0;
906  }
907 
908  std::vector<double> local_solution(n_soln_dofs);
909  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
910  local_solution[idof] = this->solution(soln_dofs_indices[idof]);
911  }
912 
913  std::vector<double> local_metric_coeff_int(n_metric_dofs);
914  for(unsigned int idof=0; idof<n_metric_dofs; ++idof)
915  {
916  local_metric_coeff_int[idof] = this->high_order_grid->volume_nodes[metric_dofs_indices[idof]];
917  }
918 
919  build_volume_metric_operators(poly_degree, grid_degree, local_metric_coeff_int, metric_oper, mapping_basis, mapping_support_points);
920 
921  dealii::Tensor<1,dim,std::vector<double>> local_aux_solution;
922  for(unsigned int idim=0; idim<dim; idim++){
923  local_aux_solution[idim].resize(n_soln_dofs);
924  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
925  if(this->use_auxiliary_eq){//only if use auxiliary equation has the auxiliary solution initialized
926  local_aux_solution[idim][idof] = this->auxiliary_solution[idim](soln_dofs_indices[idof]);
927  }
928  }
929  }
930 
931  double dual_dot_residual = 0.0;
932  std::vector<double> rhs(n_soln_dofs); //set to zero by default
933  dealii::Tensor<1,dim,std::vector<double>> rhs_aux;
934  if(compute_auxiliary_right_hand_side){
935  for(int idim=0; idim<dim; idim++){
936  rhs_aux[idim].resize(n_soln_dofs);
937  }
938  }
940  cell,
941  current_cell_index,
942  local_solution,
943  local_aux_solution,
944  local_metric_coeff_int,
945  local_dual,
946  soln_dofs_indices,
947  metric_dofs_indices,
948  poly_degree,
949  grid_degree,
950  soln_basis,
951  flux_basis,
952  flux_basis_stiffness,
953  soln_basis_projection_oper_int,
954  soln_basis_projection_oper_ext,
955  metric_oper,
956  mapping_basis,
957  mapping_support_points,
958  fe_values_collection_volume,
959  fe_values_collection_volume_lagrange,
960  fe_soln,
961  rhs,
962  rhs_aux,
963  compute_auxiliary_right_hand_side,
964  dual_dot_residual);
965 
966 
967  if(compute_auxiliary_right_hand_side){
968  for(int idim=0; idim<dim; idim++){
969  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
970  local_auxiliary_RHS[idim][itest] += rhs_aux[idim][itest];
971  }
972  }
973  }
974  else{
975  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
976  local_rhs_cell[itest] += rhs[itest];
977  }
978  }
979 }
980 
981 // AD version
982 template <int dim, int nspecies, typename real, typename MeshType>
983 template <typename adtype>
984 typename std::enable_if<!std::is_same<adtype, double>::value,void>::type
986  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
987  const dealii::types::global_dof_index current_cell_index,
988  const std::vector<dealii::types::global_dof_index> &soln_dofs_indices,
989  const std::vector<dealii::types::global_dof_index> &metric_dofs_indices,
990  const unsigned int poly_degree,
991  const unsigned int grid_degree,
994  OPERATOR::local_basis_stiffness<dim,2*dim> &flux_basis_stiffness,
995  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_int,
996  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_ext,
999  std::array<std::vector<adtype>,dim> &mapping_support_points,
1000  dealii::hp::FEValues<dim,dim> &fe_values_collection_volume,
1001  dealii::hp::FEValues<dim,dim> &fe_values_collection_volume_lagrange,
1002  const dealii::FESystem<dim,dim> &fe_soln,
1003  std::vector<real> &local_rhs_cell,
1004  dealii::Tensor<1,dim,std::vector<real>> &local_auxiliary_RHS,
1005  const bool compute_auxiliary_right_hand_side,
1006  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
1007 {
1008  const unsigned int n_soln_dofs = fe_soln.dofs_per_cell;
1009 
1010  AssertDimension (n_soln_dofs, soln_dofs_indices.size());
1011 
1012  const unsigned int n_metric_dofs = this->high_order_grid->fe_system.dofs_per_cell;
1013 
1014  std::vector<real> local_dual(n_soln_dofs);
1015  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1016  const unsigned int global_residual_row = soln_dofs_indices[itest];
1017  if(compute_d2R)//only if compute_d2R do we have the dual allocated
1018  local_dual[itest] = this->dual[global_residual_row];
1019  }
1020 
1021 
1022  unsigned int w_start=0, w_end=0, x_start=0, x_end=0;
1023  if(compute_dRdW || compute_dRdX || compute_d2R)
1024  {
1025  automatic_differentiation_indexing_1( compute_dRdW, compute_dRdX, compute_d2R,
1026  n_soln_dofs, n_metric_dofs,
1027  w_start, w_end, x_start, x_end );
1028  }
1029 
1030  using TH = codi::TapeHelper<adtype>;
1031  TH th;
1032  typename adtype::TapeType &tape = adtype::getGlobalTape();
1033  if (compute_dRdW || compute_dRdX || compute_d2R) {
1034  th.startRecording();
1035  }
1036 
1037  std::vector<adtype> local_solution(n_soln_dofs);
1038  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1039  const real val = this->solution(soln_dofs_indices[idof]);
1040  local_solution[idof] = val;
1041 
1042  if (compute_dRdW || compute_d2R) {
1043  th.registerInput(local_solution[idof]);
1044  } else {
1045  tape.deactivateValue(local_solution[idof]);
1046  }
1047  }
1048 
1049  std::vector<adtype> local_metric_coeff_int(n_metric_dofs);
1050  for(unsigned int idof=0; idof<n_metric_dofs; ++idof)
1051  {
1052  const real val = this->high_order_grid->volume_nodes[metric_dofs_indices[idof]];
1053  local_metric_coeff_int[idof] = val;
1054  if (compute_dRdX || compute_d2R) {
1055  th.registerInput(local_metric_coeff_int[idof]);
1056  } else {
1057  tape.deactivateValue(local_metric_coeff_int[idof]);
1058  }
1059  }
1060 
1061  build_volume_metric_operators(poly_degree, grid_degree, local_metric_coeff_int, metric_oper, mapping_basis, mapping_support_points);
1062 
1063  dealii::Tensor<1,dim,std::vector<adtype>> local_aux_solution;
1064  for(unsigned int idim=0; idim<dim; idim++){
1065  local_aux_solution[idim].resize(n_soln_dofs);
1066  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1067  if(this->use_auxiliary_eq){//only if use auxiliary equation has the auxiliary solution initialized
1068  const real val = this->auxiliary_solution[idim](soln_dofs_indices[idof]);
1069  local_aux_solution[idim][idof] = val;
1070  }
1071  tape.deactivateValue(local_aux_solution[idim][idof]);
1072  /*
1073  if ((compute_dRdW || compute_d2R) && this->use_auxiliary_eq) {
1074  th.registerInput(local_aux_solution[idim][idof]);
1075  } else {
1076  tape.deactivateValue(local_aux_solution[idim][idof]);
1077  }
1078  */
1079  }
1080  }
1081 
1082  adtype dual_dot_residual = 0.0;
1083  std::vector<adtype> rhs(n_soln_dofs); //set to zero by default
1084  dealii::Tensor<1,dim,std::vector<adtype>> rhs_aux;
1085  if(compute_auxiliary_right_hand_side){
1086  for(int idim=0; idim<dim; idim++){
1087  rhs_aux[idim].resize(n_soln_dofs);
1088  }
1089  }
1091  cell,
1092  current_cell_index,
1093  local_solution,
1094  local_aux_solution,
1095  local_metric_coeff_int,
1096  local_dual,
1097  soln_dofs_indices,
1098  metric_dofs_indices,
1099  poly_degree,
1100  grid_degree,
1101  soln_basis,
1102  flux_basis,
1103  flux_basis_stiffness,
1104  soln_basis_projection_oper_int,
1105  soln_basis_projection_oper_ext,
1106  metric_oper,
1107  mapping_basis,
1108  mapping_support_points,
1109  fe_values_collection_volume,
1110  fe_values_collection_volume_lagrange,
1111  fe_soln,
1112  rhs,
1113  rhs_aux,
1114  compute_auxiliary_right_hand_side,
1115  dual_dot_residual);
1116 
1117  if (compute_dRdW || compute_dRdX) {
1118  /*
1119  if(compute_auxiliary_right_hand_side){
1120  for(int idim=0; idim<dim; idim++){
1121  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1122  th.registerOutput(rhs_aux[idim][itest]);
1123  }
1124  }
1125  }
1126  */
1127  //else{
1128  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1129  th.registerOutput(rhs[itest]);
1130  }
1131  //}
1132  } else if (compute_d2R) {
1133  th.registerOutput(dual_dot_residual);
1134  }
1135 
1136  if (compute_dRdW || compute_dRdX || compute_d2R) {
1137  th.stopRecording();
1138  }
1139 
1140  if(compute_auxiliary_right_hand_side){
1141  for(int idim=0; idim<dim; idim++){
1142  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1143  local_auxiliary_RHS[idim][itest] += getValue<adtype>(rhs_aux[idim][itest]);
1144  AssertIsFinite(local_auxiliary_RHS[idim][itest]);
1145  }
1146  }
1147  }
1148  else{
1149  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1150  local_rhs_cell[itest] += getValue<adtype>(rhs[itest]);
1151  AssertIsFinite(local_rhs_cell[itest]);
1152  }
1153  }
1154 
1155  if (compute_dRdW) {
1156  typename TH::JacobianType& jac = th.createJacobian();
1157  th.evalJacobian(jac);
1158  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1159 
1160  std::vector<real> residual_derivatives(n_soln_dofs);
1161  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1162  const unsigned int i_dx = idof+w_start;
1163  residual_derivatives[idof] = jac(itest,i_dx);
1164  AssertIsFinite(residual_derivatives[idof]);
1165  }
1166  const bool elide_zero_values = false;
1167  this->system_matrix.add(soln_dofs_indices[itest], soln_dofs_indices, residual_derivatives, elide_zero_values);
1168  }
1169  th.deleteJacobian(jac);
1170  }
1171 
1172  if (compute_dRdX) {
1173  typename TH::JacobianType& jac = th.createJacobian();
1174  th.evalJacobian(jac);
1175  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1176  std::vector<real> residual_derivatives(n_metric_dofs);
1177  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1178  const unsigned int i_dx = idof+x_start;
1179  residual_derivatives[idof] = jac(itest,i_dx);
1180  }
1181  this->dRdXv.add(soln_dofs_indices[itest], metric_dofs_indices, residual_derivatives);
1182  }
1183  th.deleteJacobian(jac);
1184  }
1185 
1186  if (compute_d2R) {
1187  typename TH::HessianType& hes = th.createHessian();
1188  th.evalHessian(hes);
1189 
1190  int i_dependent = (compute_dRdW || compute_dRdX) ? n_soln_dofs : 0;
1191 
1192  std::vector<real> dWidW(n_soln_dofs);
1193  std::vector<real> dWidX(n_metric_dofs);
1194  std::vector<real> dXidX(n_metric_dofs);
1195 
1196  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
1197 
1198  const unsigned int i_dx = idof+w_start;
1199 
1200  for (unsigned int jdof=0; jdof<n_soln_dofs; ++jdof) {
1201  const unsigned int j_dx = jdof+w_start;
1202  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
1203  }
1204  this->d2RdWdW.add(soln_dofs_indices[idof], soln_dofs_indices, dWidW);
1205 
1206  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
1207  const unsigned int j_dx = jdof+x_start;
1208  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
1209  }
1210  this->d2RdWdX.add(soln_dofs_indices[idof], metric_dofs_indices, dWidX);
1211  }
1212 
1213  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
1214 
1215  const unsigned int i_dx = idof+x_start;
1216 
1217  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
1218  const unsigned int j_dx = jdof+x_start;
1219  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
1220  }
1221  this->d2RdXdX.add(metric_dofs_indices[idof], metric_dofs_indices, dXidX);
1222  }
1223 
1224  th.deleteHessian(hes);
1225  }
1226 
1227  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1228  tape.deactivateValue(local_solution[idof]);
1229 
1230  for(int idim=0; idim<dim; idim++){
1231  tape.deactivateValue(local_aux_solution[idim][idof]);
1232  }
1233  }
1234 
1235  for(unsigned int idof=0; idof<n_metric_dofs; ++idof)
1236  {
1237  tape.deactivateValue(local_metric_coeff_int[idof]);
1238  }
1239 
1240 }
1241 
1243 template <int dim, int nspecies, typename real, typename MeshType>
1244 template <typename adtype>
1245 typename std::enable_if<!std::is_same<adtype, double>::value,void>::type
1247  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
1248  const dealii::types::global_dof_index current_cell_index,
1249  const unsigned int iface,
1250  const unsigned int boundary_id,
1251  const real penalty,
1252  const std::vector<dealii::types::global_dof_index> &soln_dofs_indices,
1253  const std::vector<dealii::types::global_dof_index> &metric_dofs_indices,
1254  const unsigned int poly_degree,
1255  const unsigned int grid_degree,
1258  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_int,
1261  std::array<std::vector<adtype>,dim> &mapping_support_points,
1262  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_int,
1263  const dealii::FESystem<dim,dim> &fe_soln,
1264  std::vector<real> &local_rhs_cell,
1265  dealii::Tensor<1,dim,std::vector<real>> &local_auxiliary_RHS,
1266  const bool compute_auxiliary_right_hand_side,
1267  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
1268 {
1269  const unsigned int n_soln_dofs = fe_soln.dofs_per_cell;
1270  const unsigned int n_metric_dofs = this->high_order_grid->fe_system.dofs_per_cell;
1271 
1272  AssertDimension (n_soln_dofs, soln_dofs_indices.size());
1273 
1274  unsigned int w_start=0, w_end=0, x_start=0, x_end=0;
1275  if(compute_dRdW || compute_dRdX || compute_d2R)
1276  {
1277  automatic_differentiation_indexing_1( compute_dRdW, compute_dRdX, compute_d2R,
1278  n_soln_dofs, n_metric_dofs,
1279  w_start, w_end, x_start, x_end );
1280  }
1281 
1282  using TH = codi::TapeHelper<adtype>;
1283  TH th;
1284  typename adtype::TapeType &tape = adtype::getGlobalTape();
1285  if (compute_dRdW || compute_dRdX || compute_d2R) {
1286  th.startRecording();
1287  }
1288 
1289  std::vector<adtype> local_solution(fe_soln.dofs_per_cell);
1290  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1291  const real val = this->solution(soln_dofs_indices[idof]);
1292  local_solution[idof] = val;
1293 
1294  if (compute_dRdW || compute_d2R) {
1295  th.registerInput(local_solution[idof]);
1296  } else {
1297  tape.deactivateValue(local_solution[idof]);
1298  }
1299  }
1300 
1301  std::vector<adtype> local_metric_coeff(n_metric_dofs);
1302  for(unsigned int idof=0; idof<n_metric_dofs; ++idof)
1303  {
1304  const real val = this->high_order_grid->volume_nodes[metric_dofs_indices[idof]];
1305  local_metric_coeff[idof] = val;
1306  if (compute_dRdX || compute_d2R) {
1307  th.registerInput(local_metric_coeff[idof]);
1308  } else {
1309  tape.deactivateValue(local_metric_coeff[idof]);
1310  }
1311  }
1312 
1313  if(compute_dRdX || compute_d2R)
1314  {
1315  build_volume_metric_operators(poly_degree, grid_degree, local_metric_coeff, metric_oper, mapping_basis, mapping_support_points);
1316  }
1317 
1318  dealii::Tensor<1,dim,std::vector<adtype>> local_aux_solution;
1319  for(int idim=0; idim<dim; idim++){
1320  local_aux_solution[idim].resize(n_soln_dofs);
1321  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1322  if(this->use_auxiliary_eq){
1323  const real val = this->auxiliary_solution[idim](soln_dofs_indices[idof]);
1324  local_aux_solution[idim][idof] = val;
1325  }
1326  tape.deactivateValue(local_aux_solution[idim][idof]);
1327  /*
1328  if ((compute_dRdW || compute_d2R) && this->use_auxiliary_eq) {
1329  th.registerInput(local_aux_solution[idim][idof]);
1330  } else {
1331  tape.deactivateValue(local_aux_solution[idim][idof]);
1332  }
1333  */
1334  }
1335  }
1336 
1337 
1338  std::vector<real> local_dual(n_soln_dofs);
1339  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1340  if(compute_d2R)//only if compute_d2R do we have the dual allocated
1341  local_dual[itest] = this->dual[soln_dofs_indices[itest]];
1342  }
1343 
1344  std::vector<adtype> rhs(n_soln_dofs);
1345  dealii::Tensor<1,dim,std::vector<adtype>> aux_rhs;
1346  if(compute_auxiliary_right_hand_side){
1347  for(int idim=0; idim<dim; idim++){
1348  aux_rhs[idim].resize(n_soln_dofs);
1349  }
1350  }
1351  adtype dual_dot_residual = 0.0;
1353  cell,
1354  current_cell_index,
1355  local_solution,
1356  local_aux_solution,
1357  local_metric_coeff,
1358  local_dual,
1359  iface,
1360  boundary_id,
1361  poly_degree,
1362  grid_degree,
1363  soln_basis,
1364  flux_basis,
1365  soln_basis_projection_oper_int,
1366  metric_oper,
1367  mapping_basis,
1368  mapping_support_points,
1369  fe_values_collection_face_int,
1370  fe_soln,
1371  penalty,
1372  rhs,
1373  aux_rhs,
1374  compute_auxiliary_right_hand_side,
1375  dual_dot_residual);
1376 
1377  if (compute_dRdW || compute_dRdX) {
1378  /*
1379  if(compute_auxiliary_right_hand_side){
1380  for(int idim=0; idim<dim; idim++){
1381  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1382  th.registerOutput(aux_rhs[idim][itest]);
1383  }
1384  }
1385  }
1386  */
1387  //else{
1388  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1389  th.registerOutput(rhs[itest]);
1390  }
1391  //}
1392  } else if (compute_d2R) {
1393  th.registerOutput(dual_dot_residual);
1394  }
1395 
1396  if (compute_dRdW || compute_dRdX || compute_d2R) {
1397  th.stopRecording();
1398  }
1399 
1400  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1401  local_rhs_cell[itest] += getValue<adtype>(rhs[itest]);
1402  AssertIsFinite(local_rhs_cell[itest]);
1403  }
1404 
1405  if(compute_auxiliary_right_hand_side){
1406  for(int idim=0; idim<dim; idim++){
1407  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1408  local_auxiliary_RHS[idim][itest] += getValue<adtype>(aux_rhs[idim][itest]);
1409  AssertIsFinite(local_auxiliary_RHS[idim][itest]);
1410  }
1411  }
1412  }
1413 
1414  if (compute_dRdW) {
1415  typename TH::JacobianType& jac = th.createJacobian();
1416  th.evalJacobian(jac);
1417  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1418 
1419  std::vector<real> residual_derivatives(n_soln_dofs);
1420  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1421  const unsigned int i_dx = idof+w_start;
1422  residual_derivatives[idof] = jac(itest,i_dx);
1423  AssertIsFinite(residual_derivatives[idof]);
1424  }
1425  const bool elide_zero_values = false;
1426  this->system_matrix.add(soln_dofs_indices[itest], soln_dofs_indices, residual_derivatives, elide_zero_values);
1427  }
1428  th.deleteJacobian(jac);
1429 
1430  }
1431 
1432  if (compute_dRdX) {
1433  typename TH::JacobianType& jac = th.createJacobian();
1434  th.evalJacobian(jac);
1435  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1436  std::vector<real> residual_derivatives(n_metric_dofs);
1437  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1438  const unsigned int i_dx = idof+x_start;
1439  residual_derivatives[idof] = jac(itest,i_dx);
1440  }
1441  this->dRdXv.add(soln_dofs_indices[itest], metric_dofs_indices, residual_derivatives);
1442  }
1443  th.deleteJacobian(jac);
1444  }
1445 
1446  if (compute_d2R) {
1447  typename TH::HessianType& hes = th.createHessian();
1448  th.evalHessian(hes);
1449 
1450  int i_dependent = (compute_dRdW || compute_dRdX) ? n_soln_dofs : 0;
1451 
1452  std::vector<real> dWidW(n_soln_dofs);
1453  std::vector<real> dWidX(n_metric_dofs);
1454  std::vector<real> dXidX(n_metric_dofs);
1455 
1456  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
1457 
1458  const unsigned int i_dx = idof+w_start;
1459 
1460  for (unsigned int jdof=0; jdof<n_soln_dofs; ++jdof) {
1461  const unsigned int j_dx = jdof+w_start;
1462  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
1463  }
1464  this->d2RdWdW.add(soln_dofs_indices[idof], soln_dofs_indices, dWidW);
1465 
1466  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
1467  const unsigned int j_dx = jdof+x_start;
1468  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
1469  }
1470  this->d2RdWdX.add(soln_dofs_indices[idof], metric_dofs_indices, dWidX);
1471  }
1472 
1473  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
1474 
1475  const unsigned int i_dx = idof+x_start;
1476 
1477  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
1478  const unsigned int j_dx = jdof+x_start;
1479  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
1480  }
1481  this->d2RdXdX.add(metric_dofs_indices[idof], metric_dofs_indices, dXidX);
1482  }
1483 
1484  th.deleteHessian(hes);
1485  }
1486 
1487  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1488  tape.deactivateValue(local_solution[idof]);
1489 
1490  for(int idim=0; idim<dim; idim++){
1491  tape.deactivateValue(local_aux_solution[idim][idof]);
1492  }
1493  }
1494  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1495  tape.deactivateValue(local_metric_coeff[idof]);
1496  }
1497 
1498 }
1499 
1500 // Double version
1501 template <int dim, int nspecies, typename real, typename MeshType>
1503  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
1504  const dealii::types::global_dof_index current_cell_index,
1505  const unsigned int iface,
1506  const unsigned int boundary_id,
1507  const real penalty,
1508  const std::vector<dealii::types::global_dof_index> &soln_dofs_indices,
1509  const std::vector<dealii::types::global_dof_index> &metric_dofs_indices,
1510  const unsigned int poly_degree,
1511  const unsigned int grid_degree,
1514  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_int,
1517  std::array<std::vector<double>,dim> &mapping_support_points,
1518  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_int,
1519  const dealii::FESystem<dim,dim> &fe_soln,
1520  std::vector<real> &local_rhs_cell,
1521  dealii::Tensor<1,dim,std::vector<real>> &local_auxiliary_RHS,
1522  const bool compute_auxiliary_right_hand_side,
1523  const bool /*compute_dRdW*/, const bool /*compute_dRdX*/, const bool /*compute_d2R*/)
1524 {
1525  const unsigned int n_soln_dofs = fe_soln.dofs_per_cell;
1526  const unsigned int n_metric_dofs = this->high_order_grid->fe_system.dofs_per_cell;
1527 
1528  AssertDimension (n_soln_dofs, soln_dofs_indices.size());
1529 
1530  std::vector<double> local_solution(fe_soln.dofs_per_cell);
1531  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1532  local_solution[idof] = this->solution(soln_dofs_indices[idof]);
1533  }
1534 
1535  std::vector<double> local_metric_coeff(n_metric_dofs);
1536  for(unsigned int idof=0; idof<n_metric_dofs; ++idof)
1537  {
1538  local_metric_coeff[idof] = this->high_order_grid->volume_nodes[metric_dofs_indices[idof]];
1539  }
1540 
1541  dealii::Tensor<1,dim,std::vector<double>> local_aux_solution;
1542  for(int idim=0; idim<dim; idim++){
1543  local_aux_solution[idim].resize(n_soln_dofs);
1544  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1545  if(this->use_auxiliary_eq){
1546  local_aux_solution[idim][idof] = this->auxiliary_solution[idim](soln_dofs_indices[idof]);
1547  }
1548  }
1549  }
1550 
1551  std::vector<real> local_dual(n_soln_dofs);
1552  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1553  local_dual[itest] = 0.0;
1554  }
1555 
1556  std::vector<double> rhs(n_soln_dofs);
1557  dealii::Tensor<1,dim,std::vector<double>> aux_rhs;
1558  if(compute_auxiliary_right_hand_side){
1559  for(int idim=0; idim<dim; idim++){
1560  aux_rhs[idim].resize(n_soln_dofs);
1561  }
1562  }
1563  double dual_dot_residual = 0.0;
1565  cell,
1566  current_cell_index,
1567  local_solution,
1568  local_aux_solution,
1569  local_metric_coeff,
1570  local_dual,
1571  iface,
1572  boundary_id,
1573  poly_degree,
1574  grid_degree,
1575  soln_basis,
1576  flux_basis,
1577  soln_basis_projection_oper_int,
1578  metric_oper,
1579  mapping_basis,
1580  mapping_support_points,
1581  fe_values_collection_face_int,
1582  fe_soln,
1583  penalty,
1584  rhs,
1585  aux_rhs,
1586  compute_auxiliary_right_hand_side,
1587  dual_dot_residual);
1588 
1589  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1590  local_rhs_cell[itest] += rhs[itest];
1591  }
1592 
1593  if(compute_auxiliary_right_hand_side){
1594  for(int idim=0; idim<dim; idim++){
1595  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1596  local_auxiliary_RHS[idim][itest] += aux_rhs[idim][itest];
1597  }
1598  }
1599  }
1600 
1601 }
1602 
1603 // AD version
1604 template <int dim, int nspecies, typename real, typename MeshType>
1605 template <typename adtype>
1606 typename std::enable_if<!std::is_same<adtype, double>::value,void>::type
1608  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
1609  typename dealii::DoFHandler<dim>::active_cell_iterator neighbor_cell,
1610  const dealii::types::global_dof_index current_cell_index,
1611  const dealii::types::global_dof_index neighbor_cell_index,
1612  const unsigned int iface,
1613  const unsigned int neighbor_iface,
1614  const real penalty,
1615  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_int,
1616  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_ext,
1617  dealii::hp::FESubfaceValues<dim,dim> &fe_values_collection_subface,
1618  const dealii::FESystem<dim,dim> &fe_int,
1619  const dealii::FESystem<dim,dim> &fe_ext,
1620  const std::vector<dealii::types::global_dof_index> &soln_dofs_indices_int,
1621  const std::vector<dealii::types::global_dof_index> &soln_dofs_indices_ext,
1622  const std::vector<dealii::types::global_dof_index> &metric_dofs_indices_int,
1623  const std::vector<dealii::types::global_dof_index> &metric_dofs_indices_ext,
1624  const unsigned int poly_degree_int,
1625  const unsigned int poly_degree_ext,
1626  const unsigned int grid_degree_int,
1627  const unsigned int grid_degree_ext,
1628  OPERATOR::basis_functions<dim,2*dim> &soln_basis_int,
1629  OPERATOR::basis_functions<dim,2*dim> &soln_basis_ext,
1630  OPERATOR::basis_functions<dim,2*dim> &flux_basis_int,
1631  OPERATOR::basis_functions<dim,2*dim> &flux_basis_ext,
1632  OPERATOR::local_basis_stiffness<dim,2*dim> &flux_basis_stiffness,
1633  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_int,
1634  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_ext,
1638  std::array<std::vector<adtype>,dim> &mapping_support_points,
1639  std::vector<real> &local_rhs_int_cell,
1640  std::vector<real> &local_rhs_ext_cell,
1641  dealii::Tensor<1,dim,std::vector<real>> &current_cell_rhs_aux,
1642  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
1643  std::array<dealii::LinearAlgebra::distributed::Vector<double>,dim> &rhs_aux,
1644  const bool compute_auxiliary_right_hand_side,
1645  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
1646  const bool is_a_subface,
1647  const unsigned int neighbor_i_subface)
1648 {
1649  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
1650  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
1651  const unsigned int n_soln_dofs_int = fe_int.dofs_per_cell;
1652  const unsigned int n_soln_dofs_ext = fe_ext.dofs_per_cell;
1653 
1654  AssertDimension (n_soln_dofs_int, soln_dofs_indices_int.size());
1655  AssertDimension (n_soln_dofs_ext, soln_dofs_indices_ext.size());
1656 
1657  // Current derivative ordering is: soln_int, soln_ext, metric_int, metric_ext
1658  unsigned int w_int_start=0, w_int_end=0, w_ext_start=0, w_ext_end=0,
1659  x_int_start=0, x_int_end=0, x_ext_start=0, x_ext_end=0;
1660  if(compute_dRdW || compute_dRdX || compute_d2R)
1661  {
1663  compute_dRdW, compute_dRdX, compute_d2R,
1664  n_soln_dofs_int, n_soln_dofs_ext, n_metric_dofs,
1665  w_int_start, w_int_end, w_ext_start, w_ext_end,
1666  x_int_start, x_int_end, x_ext_start, x_ext_end);
1667  }
1668 
1669  using TH = codi::TapeHelper<adtype>;
1670  TH th;
1671  typename adtype::TapeType &tape = adtype::getGlobalTape();
1672  if (compute_dRdW || compute_dRdX || compute_d2R) {
1673  th.startRecording();
1674  }
1675 
1676  std::vector<adtype> soln_coeff_int(fe_int.dofs_per_cell);
1677  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
1678  const real val = this->solution(soln_dofs_indices_int[idof]);
1679  soln_coeff_int[idof] = val;
1680  if (compute_dRdW || compute_d2R) {
1681  th.registerInput(soln_coeff_int[idof]);
1682  } else {
1683  tape.deactivateValue(soln_coeff_int[idof]);
1684  }
1685  }
1686 
1687  std::vector<adtype> soln_coeff_ext(fe_ext.dofs_per_cell);
1688  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
1689  const real val = this->solution(soln_dofs_indices_ext[idof]);
1690  soln_coeff_ext[idof] = val;
1691  if (compute_dRdW || compute_d2R) {
1692  th.registerInput(soln_coeff_ext[idof]);
1693  } else {
1694  tape.deactivateValue(soln_coeff_ext[idof]);
1695  }
1696  }
1697 
1698  std::vector<adtype> metric_coeff_int(fe_metric.dofs_per_cell);
1699  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1700  const real val = this->high_order_grid->volume_nodes[metric_dofs_indices_int[idof]];
1701  metric_coeff_int[idof] = val;
1702  if (compute_dRdX || compute_d2R) {
1703  th.registerInput(metric_coeff_int[idof]);
1704  } else {
1705  tape.deactivateValue(metric_coeff_int[idof]);
1706  }
1707  }
1708 
1709  if(compute_dRdX || compute_d2R)
1710  {
1711  // Rebuild metric Jacobian and cofactors of the interior cell again
1712  build_volume_metric_operators(poly_degree_int, grid_degree_int, metric_coeff_int, metric_oper_int, mapping_basis, mapping_support_points);
1713  }
1714 
1715  std::vector<adtype> metric_coeff_ext(fe_metric.dofs_per_cell);
1716  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1717  const real val = this->high_order_grid->volume_nodes[metric_dofs_indices_ext[idof]];
1718  metric_coeff_ext[idof] = val;
1719  if (compute_dRdX || compute_d2R) {
1720  th.registerInput(metric_coeff_ext[idof]);
1721  } else {
1722  tape.deactivateValue(metric_coeff_ext[idof]);
1723  }
1724  }
1725 
1726  dealii::Tensor<1,dim,std::vector<adtype>> aux_soln_coeff_int;
1727  dealii::Tensor<1,dim,std::vector<adtype>> aux_soln_coeff_ext;
1728  for(int idim=0; idim<dim; idim++){
1729  aux_soln_coeff_int[idim].resize(n_soln_dofs_int);
1730  aux_soln_coeff_ext[idim].resize(n_soln_dofs_ext);
1731  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
1732  if(this->use_auxiliary_eq){
1733  const real val = this->auxiliary_solution[idim](soln_dofs_indices_int[idof]);
1734  aux_soln_coeff_int[idim][idof] = val;
1735  }
1736  tape.deactivateValue(aux_soln_coeff_int[idim][idof]);
1737  /*
1738  if ((compute_dRdW || compute_d2R) && this->use_auxiliary_eq) {
1739  th.registerInput(aux_soln_coeff_int[idim][idof]);
1740  } else {
1741  tape.deactivateValue(aux_soln_coeff_int[idim][idof]);
1742  }
1743  */
1744  }
1745  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
1746  if(this->use_auxiliary_eq){
1747  const real val = this->auxiliary_solution[idim](soln_dofs_indices_ext[idof]);
1748  aux_soln_coeff_ext[idim][idof] = val;
1749  }
1750  tape.deactivateValue(aux_soln_coeff_ext[idim][idof]);
1751  /*
1752  if ((compute_dRdW || compute_d2R) && this->use_auxiliary_eq) {
1753  th.registerInput(aux_soln_coeff_ext[idim][idof]);
1754  } else {
1755  tape.deactivateValue(aux_soln_coeff_ext[idim][idof]);
1756  }
1757  */
1758  }
1759  }
1760 
1761  std::vector<double> dual_int(n_soln_dofs_int);
1762  std::vector<double> dual_ext(n_soln_dofs_ext);
1763 
1764  for (unsigned int itest=0; itest<n_soln_dofs_int; ++itest) {
1765  const unsigned int global_residual_row = soln_dofs_indices_int[itest];
1766  if(compute_d2R)//only if compute_d2R do we have the dual allocated
1767  dual_int[itest] = this->dual[global_residual_row];
1768  }
1769  for (unsigned int itest=0; itest<n_soln_dofs_ext; ++itest) {
1770  const unsigned int global_residual_row = soln_dofs_indices_ext[itest];
1771  if(compute_d2R)//only if compute_d2R do we have the dual allocated
1772  dual_ext[itest] = this->dual[global_residual_row];
1773  }
1774 
1775  std::vector<adtype> rhs_int(n_soln_dofs_int);
1776  std::vector<adtype> rhs_ext(n_soln_dofs_ext);
1777  dealii::Tensor<1,dim,std::vector<adtype>> aux_rhs_int;
1778  dealii::Tensor<1,dim,std::vector<adtype>> aux_rhs_ext;
1779  if(compute_auxiliary_right_hand_side){
1780  for(int idim=0; idim<dim; idim++){
1781  aux_rhs_int[idim].resize(n_soln_dofs_int);
1782  aux_rhs_ext[idim].resize(n_soln_dofs_ext);
1783  }
1784  }
1785  adtype dual_dot_residual = 0.0;
1786 
1788  cell,
1789  neighbor_cell,
1790  current_cell_index,
1791  neighbor_cell_index,
1792  iface,
1793  neighbor_iface,
1794  soln_coeff_int,
1795  soln_coeff_ext,
1796  aux_soln_coeff_int,
1797  aux_soln_coeff_ext,
1798  metric_coeff_int,
1799  metric_coeff_ext,
1800  dual_int,
1801  dual_ext,
1802  poly_degree_int,
1803  poly_degree_ext,
1804  grid_degree_int,
1805  grid_degree_ext,
1806  soln_basis_int,
1807  soln_basis_ext,
1808  flux_basis_int,
1809  flux_basis_ext,
1810  flux_basis_stiffness,
1811  soln_basis_projection_oper_int,
1812  soln_basis_projection_oper_ext,
1813  metric_oper_int,
1814  metric_oper_ext,
1815  mapping_basis,
1816  mapping_support_points,
1817  fe_values_collection_face_int,
1818  fe_values_collection_face_ext,
1819  fe_values_collection_subface,
1820  fe_int,
1821  fe_ext,
1822  penalty,
1823  rhs_int,
1824  rhs_ext,
1825  aux_rhs_int,
1826  aux_rhs_ext,
1827  compute_auxiliary_right_hand_side,
1828  dual_dot_residual,
1829  compute_dRdW, compute_dRdX, compute_d2R,
1830  is_a_subface,
1831  neighbor_i_subface);
1832 
1833  if (compute_dRdW || compute_dRdX) {
1834  for (unsigned int itest=0; itest<n_soln_dofs_int; ++itest) {
1835  th.registerOutput(rhs_int[itest]);
1836  }
1837  for (unsigned int itest=0; itest<n_soln_dofs_ext; ++itest) {
1838  th.registerOutput(rhs_ext[itest]);
1839  }
1840  } else if (compute_d2R) {
1841  th.registerOutput(dual_dot_residual);
1842  }
1843 
1844  if (compute_dRdW || compute_dRdX || compute_d2R) {
1845  th.stopRecording();
1846  //adtype::getGlobalTape().printStatistics();
1847  }
1848 
1849  if(compute_auxiliary_right_hand_side){
1850  for(int idim=0; idim<dim; idim++){
1851  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
1852  current_cell_rhs_aux[idim][itest_int] += getValue<adtype>(aux_rhs_int[idim][itest_int]);
1853  }
1854 
1855  // Add local contribution from neighbor cell to global vector
1856  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
1857  rhs_aux[idim][soln_dofs_indices_ext[itest_ext]] += getValue<adtype>(aux_rhs_ext[idim][itest_ext]);
1858  }
1859  }
1860  }
1861  else{
1862  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
1863  local_rhs_int_cell[itest_int] += getValue<adtype>(rhs_int[itest_int]);
1864  }
1865  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
1866  local_rhs_ext_cell[itest_ext] += getValue<adtype>(rhs_ext[itest_ext]);
1867  }
1868 
1869  // Add local contribution from neighbor cell to global vector
1870  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
1871  rhs[soln_dofs_indices_ext[itest_ext]] += local_rhs_ext_cell[itest_ext];
1872  }
1873  }
1874 
1875  if (compute_dRdW || compute_dRdX) {
1876  typename TH::JacobianType& jac = th.createJacobian();
1877  th.evalJacobian(jac);
1878 
1879  if (compute_dRdW) {
1880  std::vector<real> residual_derivatives(n_soln_dofs_int);
1881 
1882  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
1883  int i_dependent = itest_int;
1884 
1885  // dR_int_dW_int
1886  residual_derivatives.resize(n_soln_dofs_int);
1887  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
1888  const unsigned int i_dx = idof+w_int_start;
1889  residual_derivatives[idof] = jac(i_dependent,i_dx);
1890  }
1891  const bool elide_zero_values = false;
1892  this->system_matrix.add(soln_dofs_indices_int[itest_int], soln_dofs_indices_int, residual_derivatives, elide_zero_values);
1893 
1894  // dR_int_dW_ext
1895  residual_derivatives.resize(n_soln_dofs_ext);
1896  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
1897  const unsigned int i_dx = idof+w_ext_start;
1898  residual_derivatives[idof] = jac(i_dependent,i_dx);
1899  }
1900  this->system_matrix.add(soln_dofs_indices_int[itest_int], soln_dofs_indices_ext, residual_derivatives, elide_zero_values);
1901  }
1902 
1903  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
1904 
1905  int i_dependent = n_soln_dofs_int + itest_ext;
1906 
1907  // dR_ext_dW_int
1908  residual_derivatives.resize(n_soln_dofs_int);
1909  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
1910  const unsigned int i_dx = idof+w_int_start;
1911  residual_derivatives[idof] = jac(i_dependent,i_dx);
1912  }
1913  const bool elide_zero_values = false;
1914  this->system_matrix.add(soln_dofs_indices_ext[itest_ext], soln_dofs_indices_int, residual_derivatives, elide_zero_values);
1915 
1916  // dR_ext_dW_ext
1917  residual_derivatives.resize(n_soln_dofs_ext);
1918  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
1919  const unsigned int i_dx = idof+w_ext_start;
1920  residual_derivatives[idof] = jac(i_dependent,i_dx);
1921  }
1922  this->system_matrix.add(soln_dofs_indices_ext[itest_ext], soln_dofs_indices_ext, residual_derivatives, elide_zero_values);
1923  }
1924  }
1925 
1926  if (compute_dRdX) {
1927  std::vector<real> residual_derivatives(n_metric_dofs);
1928 
1929  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
1930 
1931  int i_dependent = itest_int;
1932 
1933  // dR_int_dX_int
1934  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1935  const unsigned int i_dx = idof+x_int_start;
1936  residual_derivatives[idof] = jac(i_dependent,i_dx);
1937  }
1938  this->dRdXv.add(soln_dofs_indices_int[itest_int], metric_dofs_indices_int, residual_derivatives);
1939 
1940  // dR_int_dX_ext
1941  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1942  const unsigned int i_dx = idof+x_ext_start;
1943  residual_derivatives[idof] = jac(i_dependent,i_dx);
1944  }
1945  this->dRdXv.add(soln_dofs_indices_int[itest_int], metric_dofs_indices_ext, residual_derivatives);
1946  }
1947 
1948  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
1949 
1950  int i_dependent = n_soln_dofs_int + itest_ext;
1951 
1952  // dR_ext_dX_int
1953  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1954  const unsigned int i_dx = idof+x_int_start;
1955  residual_derivatives[idof] = jac(i_dependent,i_dx);
1956  }
1957  this->dRdXv.add(soln_dofs_indices_ext[itest_ext], metric_dofs_indices_int, residual_derivatives);
1958 
1959  // dR_ext_dX_ext
1960  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1961  const unsigned int i_dx = idof+x_ext_start;
1962  residual_derivatives[idof] = jac(i_dependent,i_dx);
1963  }
1964  this->dRdXv.add(soln_dofs_indices_ext[itest_ext], metric_dofs_indices_ext, residual_derivatives);
1965  }
1966  }
1967 
1968  th.deleteJacobian(jac);
1969  }
1970 
1971  if (compute_d2R) {
1972  typename TH::HessianType& hes = th.createHessian();
1973  th.evalHessian(hes);
1974 
1975  std::vector<real> dWidW(n_soln_dofs_int);
1976  std::vector<real> dWidX(n_metric_dofs);
1977  std::vector<real> dXidX(n_metric_dofs);
1978 
1979  int i_dependent = (compute_dRdW || compute_dRdX) ? n_soln_dofs_int + n_soln_dofs_ext : 0;
1980 
1981  for (unsigned int idof=0; idof<n_soln_dofs_int; ++idof) {
1982 
1983  const unsigned int i_dx = idof+w_int_start;
1984 
1985  // dWint_dWint
1986  for (unsigned int jdof=0; jdof<n_soln_dofs_int; ++jdof) {
1987  const unsigned int j_dx = jdof+w_int_start;
1988  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
1989  }
1990  this->d2RdWdW.add(soln_dofs_indices_int[idof], soln_dofs_indices_int, dWidW);
1991 
1992  // dWint_dWext
1993  for (unsigned int jdof=0; jdof<n_soln_dofs_ext; ++jdof) {
1994  const unsigned int j_dx = jdof+w_ext_start;
1995  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
1996  }
1997  this->d2RdWdW.add(soln_dofs_indices_int[idof], soln_dofs_indices_ext, dWidW);
1998 
1999  // dWint_dXint
2000  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2001  const unsigned int j_dx = jdof+x_int_start;
2002  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
2003  }
2004  this->d2RdWdX.add(soln_dofs_indices_int[idof], metric_dofs_indices_int, dWidX);
2005 
2006  // dWint_dXext
2007  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2008  const unsigned int j_dx = jdof+x_ext_start;
2009  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
2010  }
2011  this->d2RdWdX.add(soln_dofs_indices_int[idof], metric_dofs_indices_ext, dWidX);
2012  }
2013 
2014  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
2015 
2016  const unsigned int i_dx = idof+x_int_start;
2017 
2018  // dXint_dXint
2019  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2020  const unsigned int j_dx = jdof+x_int_start;
2021  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
2022  }
2023  this->d2RdXdX.add(metric_dofs_indices_int[idof], metric_dofs_indices_int, dXidX);
2024 
2025  // dXint_dXext
2026  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2027  const unsigned int j_dx = jdof+x_ext_start;
2028  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
2029  }
2030  this->d2RdXdX.add(metric_dofs_indices_int[idof], metric_dofs_indices_ext, dXidX);
2031  }
2032 
2033  dWidW.resize(n_soln_dofs_ext);
2034 
2035  for (unsigned int idof=0; idof<n_soln_dofs_ext; ++idof) {
2036 
2037  const unsigned int i_dx = idof+w_ext_start;
2038 
2039  // dWext_dWint
2040  for (unsigned int jdof=0; jdof<n_soln_dofs_int; ++jdof) {
2041  const unsigned int j_dx = jdof+w_int_start;
2042  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
2043  }
2044  this->d2RdWdW.add(soln_dofs_indices_ext[idof], soln_dofs_indices_int, dWidW);
2045 
2046  // dWext_dWext
2047  for (unsigned int jdof=0; jdof<n_soln_dofs_ext; ++jdof) {
2048  const unsigned int j_dx = jdof+w_ext_start;
2049  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
2050  }
2051  this->d2RdWdW.add(soln_dofs_indices_ext[idof], soln_dofs_indices_ext, dWidW);
2052 
2053  // dWext_dXint
2054  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2055  const unsigned int j_dx = jdof+x_int_start;
2056  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
2057  }
2058  this->d2RdWdX.add(soln_dofs_indices_ext[idof], metric_dofs_indices_int, dWidX);
2059 
2060  // dWext_dXext
2061  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2062  const unsigned int j_dx = jdof+x_ext_start;
2063  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
2064  }
2065  this->d2RdWdX.add(soln_dofs_indices_ext[idof], metric_dofs_indices_ext, dWidX);
2066  }
2067 
2068  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
2069 
2070  const unsigned int i_dx = idof+x_ext_start;
2071 
2072  // dXext_dXint
2073  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2074  const unsigned int j_dx = jdof+x_int_start;
2075  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
2076  }
2077  this->d2RdXdX.add(metric_dofs_indices_ext[idof], metric_dofs_indices_int, dXidX);
2078 
2079  // dXext_dXext
2080  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2081  const unsigned int j_dx = jdof+x_ext_start;
2082  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
2083  }
2084  this->d2RdXdX.add(metric_dofs_indices_ext[idof], metric_dofs_indices_ext, dXidX);
2085  }
2086 
2087  th.deleteHessian(hes);
2088  }
2089 
2090  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2091  tape.deactivateValue(soln_coeff_int[idof]);
2092  }
2093  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2094  tape.deactivateValue(soln_coeff_ext[idof]);
2095  }
2096  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2097  tape.deactivateValue(metric_coeff_int[idof]);
2098  }
2099  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2100  tape.deactivateValue(metric_coeff_ext[idof]);
2101  }
2102 
2103  for(int idim=0; idim<dim; idim++){
2104  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2105  tape.deactivateValue(aux_soln_coeff_int[idim][idof]);
2106  }
2107  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2108  tape.deactivateValue(aux_soln_coeff_ext[idim][idof]);
2109  }
2110  }
2111 }
2112 
2113 // Double version
2114 template <int dim, int nspecies, typename real, typename MeshType>
2116  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
2117  typename dealii::DoFHandler<dim>::active_cell_iterator neighbor_cell,
2118  const dealii::types::global_dof_index current_cell_index,
2119  const dealii::types::global_dof_index neighbor_cell_index,
2120  const unsigned int iface,
2121  const unsigned int neighbor_iface,
2122  const real penalty,
2123  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_int,
2124  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_ext,
2125  dealii::hp::FESubfaceValues<dim,dim> &fe_values_collection_subface,
2126  const dealii::FESystem<dim,dim> &fe_int,
2127  const dealii::FESystem<dim,dim> &fe_ext,
2128  const std::vector<dealii::types::global_dof_index> &soln_dofs_indices_int,
2129  const std::vector<dealii::types::global_dof_index> &soln_dofs_indices_ext,
2130  const std::vector<dealii::types::global_dof_index> &metric_dofs_indices_int,
2131  const std::vector<dealii::types::global_dof_index> &metric_dofs_indices_ext,
2132  const unsigned int poly_degree_int,
2133  const unsigned int poly_degree_ext,
2134  const unsigned int grid_degree_int,
2135  const unsigned int grid_degree_ext,
2136  OPERATOR::basis_functions<dim,2*dim> &soln_basis_int,
2137  OPERATOR::basis_functions<dim,2*dim> &soln_basis_ext,
2138  OPERATOR::basis_functions<dim,2*dim> &flux_basis_int,
2139  OPERATOR::basis_functions<dim,2*dim> &flux_basis_ext,
2140  OPERATOR::local_basis_stiffness<dim,2*dim> &flux_basis_stiffness,
2141  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_int,
2142  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_ext,
2146  std::array<std::vector<double>,dim> &mapping_support_points,
2147  std::vector<real> &local_rhs_int_cell,
2148  std::vector<real> &local_rhs_ext_cell,
2149  dealii::Tensor<1,dim,std::vector<real>> &current_cell_rhs_aux,
2150  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
2151  std::array<dealii::LinearAlgebra::distributed::Vector<double>,dim> &rhs_aux,
2152  const bool compute_auxiliary_right_hand_side,
2153  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
2154  const bool is_a_subface,
2155  const unsigned int neighbor_i_subface)
2156 {
2157  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
2158  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
2159  const unsigned int n_soln_dofs_int = fe_int.dofs_per_cell;
2160  const unsigned int n_soln_dofs_ext = fe_ext.dofs_per_cell;
2161 
2162  AssertDimension (n_soln_dofs_int, soln_dofs_indices_int.size());
2163  AssertDimension (n_soln_dofs_ext, soln_dofs_indices_ext.size());
2164 
2165  std::vector<double> soln_coeff_int(fe_int.dofs_per_cell);
2166  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2167  soln_coeff_int[idof] = this->solution(soln_dofs_indices_int[idof]);
2168  }
2169 
2170  std::vector<double> soln_coeff_ext(fe_ext.dofs_per_cell);
2171  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2172  soln_coeff_ext[idof] = this->solution(soln_dofs_indices_ext[idof]);
2173  }
2174 
2175  std::vector<double> metric_coeff_int(fe_metric.dofs_per_cell);
2176  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2177  metric_coeff_int[idof] = this->high_order_grid->volume_nodes[metric_dofs_indices_int[idof]];
2178  }
2179 
2180  std::vector<double> metric_coeff_ext(fe_metric.dofs_per_cell);
2181  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2182  metric_coeff_ext[idof] = this->high_order_grid->volume_nodes[metric_dofs_indices_ext[idof]];
2183  }
2184 
2185  dealii::Tensor<1,dim,std::vector<double>> aux_soln_coeff_int;
2186  dealii::Tensor<1,dim,std::vector<double>> aux_soln_coeff_ext;
2187  for(int idim=0; idim<dim; idim++){
2188  aux_soln_coeff_int[idim].resize(n_soln_dofs_int);
2189  aux_soln_coeff_ext[idim].resize(n_soln_dofs_ext);
2190  if(this->use_auxiliary_eq){
2191  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2192  aux_soln_coeff_int[idim][idof] = this->auxiliary_solution[idim](soln_dofs_indices_int[idof]);
2193  }
2194  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2195  aux_soln_coeff_ext[idim][idof] = this->auxiliary_solution[idim](soln_dofs_indices_ext[idof]);
2196  }
2197  }
2198  }
2199 
2200  std::vector<double> dual_int(n_soln_dofs_int);
2201  std::vector<double> dual_ext(n_soln_dofs_ext);
2202 
2203  std::vector<double> rhs_int(n_soln_dofs_int);
2204  std::vector<double> rhs_ext(n_soln_dofs_ext);
2205  dealii::Tensor<1,dim,std::vector<double>> aux_rhs_int;
2206  dealii::Tensor<1,dim,std::vector<double>> aux_rhs_ext;
2207  if(compute_auxiliary_right_hand_side){
2208  for(int idim=0; idim<dim; idim++){
2209  aux_rhs_int[idim].resize(n_soln_dofs_int);
2210  aux_rhs_ext[idim].resize(n_soln_dofs_ext);
2211  }
2212  }
2213  double dual_dot_residual = 0.0;
2214 
2216  cell,
2217  neighbor_cell,
2218  current_cell_index,
2219  neighbor_cell_index,
2220  iface,
2221  neighbor_iface,
2222  soln_coeff_int,
2223  soln_coeff_ext,
2224  aux_soln_coeff_int,
2225  aux_soln_coeff_ext,
2226  metric_coeff_int,
2227  metric_coeff_ext,
2228  dual_int,
2229  dual_ext,
2230  poly_degree_int,
2231  poly_degree_ext,
2232  grid_degree_int,
2233  grid_degree_ext,
2234  soln_basis_int,
2235  soln_basis_ext,
2236  flux_basis_int,
2237  flux_basis_ext,
2238  flux_basis_stiffness,
2239  soln_basis_projection_oper_int,
2240  soln_basis_projection_oper_ext,
2241  metric_oper_int,
2242  metric_oper_ext,
2243  mapping_basis,
2244  mapping_support_points,
2245  fe_values_collection_face_int,
2246  fe_values_collection_face_ext,
2247  fe_values_collection_subface,
2248  fe_int,
2249  fe_ext,
2250  penalty,
2251  rhs_int,
2252  rhs_ext,
2253  aux_rhs_int,
2254  aux_rhs_ext,
2255  compute_auxiliary_right_hand_side,
2256  dual_dot_residual,
2257  compute_dRdW, compute_dRdX, compute_d2R,
2258  is_a_subface,
2259  neighbor_i_subface);
2260 
2261  if(compute_auxiliary_right_hand_side){
2262  for(int idim=0; idim<dim; idim++){
2263  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
2264  current_cell_rhs_aux[idim][itest_int] += aux_rhs_int[idim][itest_int];
2265  }
2266 
2267  // Add local contribution from neighbor cell to global vector
2268  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2269  rhs_aux[idim][soln_dofs_indices_ext[itest_ext]] += aux_rhs_ext[idim][itest_ext];
2270  }
2271  }
2272  }
2273  else{
2274  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
2275  local_rhs_int_cell[itest_int] += rhs_int[itest_int];
2276  }
2277  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2278  local_rhs_ext_cell[itest_ext] += rhs_ext[itest_ext];
2279  }
2280 
2281  // Add local contribution from neighbor cell to global vector
2282  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2283  rhs[soln_dofs_indices_ext[itest_ext]] += local_rhs_ext_cell[itest_ext];
2284  }
2285  }
2286 }
2287 
2288 template <int dim, int nspecies, typename real, typename MeshType>
2289 template <typename real2>
2291 {
2292  if constexpr (std::is_same<real2, double>::value) {
2293  return x;
2294  } else {
2295  return getValue(x.value());
2296  }
2297 }
2298 
2299 template <int dim, int nspecies, typename real, typename MeshType>
2301  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
2302  const unsigned int n_soln_dofs, const unsigned int n_metric_dofs,
2303  unsigned int &w_start, unsigned int &w_end,
2304  unsigned int &x_start, unsigned int &x_end)
2305 {
2306  w_start = 0;
2307  w_end = 0;
2308  x_start = 0;
2309  x_end = 0;
2310  if (compute_d2R || (compute_dRdW && compute_dRdX)) {
2311  w_start = 0;
2312  w_end = w_start + n_soln_dofs;
2313  x_start = w_end;
2314  x_end = x_start + n_metric_dofs;
2315  } else if (compute_dRdW) {
2316  w_start = 0;
2317  w_end = w_start + n_soln_dofs;
2318  } else if (compute_dRdX) {
2319  x_start = 0;
2320  x_end = x_start + n_metric_dofs;
2321  } else {
2322  std::cout << "Called the derivative version of the residual without requesting the derivative" << std::endl;
2323  }
2324 }
2325 
2326 template <int dim, int nspecies, typename real, typename MeshType>
2328  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
2329  const unsigned int n_soln_dofs_int, const unsigned int n_soln_dofs_ext, const unsigned int n_metric_dofs,
2330  unsigned int &w_int_start, unsigned int &w_int_end, unsigned int &w_ext_start, unsigned int &w_ext_end,
2331  unsigned int &x_int_start, unsigned int &x_int_end, unsigned int &x_ext_start, unsigned int &x_ext_end)
2332 {
2333  // Current derivative order is: soln_int, soln_ext, metric_int, metric_ext
2334  w_int_start = 0; w_int_end = 0; w_ext_start = 0; w_ext_end = 0;
2335  x_int_start = 0; x_int_end = 0; x_ext_start = 0; x_ext_end = 0;
2336  if (compute_d2R || (compute_dRdW && compute_dRdX)) {
2337  w_int_start = 0;
2338  w_int_end = w_int_start + n_soln_dofs_int;
2339  w_ext_start = w_int_end;
2340  w_ext_end = w_ext_start + n_soln_dofs_ext;
2341 
2342  x_int_start = w_ext_end;
2343  x_int_end = x_int_start + n_metric_dofs;
2344  x_ext_start = x_int_end;
2345  x_ext_end = x_ext_start + n_metric_dofs;
2346  } else if (compute_dRdW) {
2347  w_int_start = 0;
2348  w_int_end = w_int_start + n_soln_dofs_int;
2349  w_ext_start = w_int_end;
2350  w_ext_end = w_ext_start + n_soln_dofs_ext;
2351  } else if (compute_dRdX) {
2352  x_int_start = 0;
2353  x_int_end = x_int_start + n_metric_dofs;
2354  x_ext_start = x_int_end;
2355  x_ext_end = x_ext_start + n_metric_dofs;
2356  } else {
2357  std::cout << "Called the derivative version of the residual without requesting the derivative" << std::endl;
2358  }
2359 }
2360 
2361 
2362 template <int dim, int nspecies, typename real, typename MeshType>
2363 void DGBase<dim,nspecies,real,MeshType>::set_dual(const dealii::LinearAlgebra::distributed::Vector<real> &dual_input)
2364 {
2365  dual = dual_input;
2366 }
2367 
2368 template <int dim, int nspecies, typename real, typename MeshType>
2370 {
2371  const auto mapping = (*(high_order_grid->mapping_fe_field));
2372  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
2373  const dealii::UpdateFlags update_flags = dealii::update_values | dealii::update_JxW_values;
2374  dealii::hp::FEValues<dim,dim> fe_values_collection_volume (mapping_collection, fe_collection, volume_quadrature_collection, update_flags);
2375 
2376  std::vector< double > soln_coeff_high;
2377  std::vector<dealii::types::global_dof_index> dof_indices;
2378 
2379  const unsigned int n_dofs_arti_diss = fe_q_artificial_dissipation.dofs_per_cell;
2380  std::vector<dealii::types::global_dof_index> dof_indices_artificial_dissipation(n_dofs_arti_diss);
2381 
2382  if (freeze_artificial_dissipation) return;
2384  for (auto cell : dof_handler.active_cell_iterators()) {
2385  if (!(cell->is_locally_owned() || cell->is_ghost())) continue;
2386 
2387  dealii::types::global_dof_index cell_index = cell->active_cell_index();
2388  artificial_dissipation_coeffs[cell_index] = 0.0;
2389  artificial_dissipation_se[cell_index] = 0.0;
2390  //artificial_dissipation_coeffs[cell_index] = 1e-2;
2391  //artificial_dissipation_se[cell_index] = 0.0;
2392  //continue;
2393 
2394  const int i_fele = cell->active_fe_index();
2395  const int i_quad = i_fele;
2396  const int i_mapp = 0;
2397 
2398  const dealii::FESystem<dim,dim> &fe_high = fe_collection[i_fele];
2399  const unsigned int degree = fe_high.tensor_degree();
2400 
2401  if (degree == 0) continue;
2402 
2403  const unsigned int nstate = fe_high.components;
2404  const unsigned int n_dofs_high = fe_high.dofs_per_cell;
2405 
2406  fe_values_collection_volume.reinit (cell, i_quad, i_mapp, i_fele);
2407  const dealii::FEValues<dim,dim> &fe_values_volume = fe_values_collection_volume.get_present_fe_values();
2408 
2409  dof_indices.resize(n_dofs_high);
2410  cell->get_dof_indices (dof_indices);
2411 
2412  soln_coeff_high.resize(n_dofs_high);
2413  for (unsigned int idof=0; idof<n_dofs_high; ++idof) {
2414  soln_coeff_high[idof] = solution[dof_indices[idof]];
2415  }
2416 
2417  // Lower degree basis.
2418  const unsigned int lower_degree = degree-1;
2419  const dealii::FE_DGQLegendre<dim> fe_dgq_lower(lower_degree);
2420  const dealii::FESystem<dim,dim> fe_lower(fe_dgq_lower, nstate);
2421 
2422  // Projection quadrature.
2423  const dealii::QGauss<dim> projection_quadrature(degree+5);
2424  std::vector< double > soln_coeff_lower = project_function<dim,nspecies,double>( soln_coeff_high, fe_high, fe_lower, projection_quadrature);
2425 
2426  // Quadrature used for solution difference.
2427  const dealii::Quadrature<dim> &quadrature = fe_values_volume.get_quadrature();
2428  const std::vector<dealii::Point<dim,double>> &unit_quad_pts = quadrature.get_points();
2429 
2430  const unsigned int n_quad_pts = quadrature.size();
2431  const unsigned int n_dofs_lower = fe_lower.dofs_per_cell;
2432 
2433  double element_volume = 0.0;
2434  double error = 0.0;
2435  double soln_norm = 0.0;
2436  std::vector<double> soln_high(nstate);
2437  std::vector<double> soln_lower(nstate);
2438  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
2439  for (unsigned int s=0; s<nstate; ++s) {
2440  soln_high[s] = 0.0;
2441  soln_lower[s] = 0.0;
2442  }
2443  // Interpolate solution
2444  for (unsigned int idof=0; idof<n_dofs_high; ++idof) {
2445  const unsigned int istate = fe_high.system_to_component_index(idof).first;
2446  soln_high[istate] += soln_coeff_high[idof] * fe_high.shape_value_component(idof,unit_quad_pts[iquad],istate);
2447  }
2448  // Interpolate low order solution
2449  for (unsigned int idof=0; idof<n_dofs_lower; ++idof) {
2450  const unsigned int istate = fe_lower.system_to_component_index(idof).first;
2451  soln_lower[istate] += soln_coeff_lower[idof] * fe_lower.shape_value_component(idof,unit_quad_pts[iquad],istate);
2452  }
2453  // Quadrature
2454  element_volume += fe_values_volume.JxW(iquad);
2455  // Only integrate over the first state variable.
2456  for (unsigned int s=0; s<1/*nstate*/; ++s)
2457  {
2458  error += (soln_high[s] - soln_lower[s]) * (soln_high[s] - soln_lower[s]) * fe_values_volume.JxW(iquad);
2459  soln_norm += soln_high[s] * soln_high[s] * fe_values_volume.JxW(iquad);
2460  }
2461  }
2462 
2463  //std::cout << " error: " << error
2464  // << " soln_norm: " << soln_norm << std::endl;
2465  //if (error < 1e-12) continue;
2466  if (soln_norm < 1e-12)
2467  {
2468  continue;
2469  }
2470 
2471  double S_e, s_e;
2472  S_e = sqrt(error / soln_norm);
2473  s_e = log10(S_e);
2474 
2475  //const double mu_scale = 1.0;
2476  //const double s_0 = log10(0.1) - 4.25*log10(degree);
2477  //const double s_0 = -0.5 - 4.25*log10(degree);
2478  //const double kappa = 1.0;
2479 
2481  //const double s_0 = - 4.25*log10(degree);
2482  const double s_0 = -0.00 - 4.00*log10(degree);
2484  const double low = s_0 - kappa;
2485  const double upp = s_0 + kappa;
2486 
2487  const double diameter = std::pow(element_volume, 1.0/dim);
2488  const double eps_0 = mu_scale * diameter / (double)degree;
2489 
2490  //std::cout << " lower < s_e < upp " << low << " < " << s_e << " < " << upp << " ? " << std::endl;
2491 
2492  if ( s_e < low) continue;
2493 
2494  if ( s_e > upp) {
2495  artificial_dissipation_coeffs[cell_index] += eps_0;
2497  {
2499  }
2500  continue;
2501  }
2502 
2503  const double PI = 4*atan(1);
2504  double eps = 1.0 + sin(PI * (s_e - s_0) * 0.5 / kappa);
2505  eps *= eps_0 * 0.5;
2506 
2508  {
2510  }
2511 
2512 
2513  artificial_dissipation_coeffs[cell_index] += eps;
2514  artificial_dissipation_se[cell_index] = s_e;
2515 
2516  typename dealii::DoFHandler<dim>::active_cell_iterator artificial_dissipation_cell(
2517  triangulation.get(), cell->level(), cell->index(), &dof_handler_artificial_dissipation);
2518 
2519  dof_indices_artificial_dissipation.resize(n_dofs_arti_diss);
2520  artificial_dissipation_cell->get_dof_indices (dof_indices_artificial_dissipation);
2521  for (unsigned int idof=0; idof<n_dofs_arti_diss; ++idof) {
2522  const unsigned int index = dof_indices_artificial_dissipation[idof];
2523  artificial_dissipation_c0[index] = std::max(artificial_dissipation_c0[index], eps);
2524  }
2525 
2526  //const unsigned int dofs_per_face = fe_q_artificial_dissipation.n_dofs_per_face();
2527  //for (unsigned int iface=0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface) {
2528  // const auto face = cell->face(iface);
2529  // if (face->at_boundary()) {
2530  // for (unsigned int idof_face=0; idof_face<dofs_per_face; ++idof_face) {
2531  // unsigned int idof_cell = fe_q_artificial_dissipation.face_to_cell_index(idof_face, iface);
2532  // const dealii::types::global_dof_index index = dof_indices_artificial_dissipation[idof_cell];
2533  // artificial_dissipation_c0[index] = 0.0;
2534  // }
2535  // }
2536  //}
2537  }
2538  dealii::IndexSet boundary_dofs(dof_handler_artificial_dissipation.n_dofs());
2539  dealii::DoFTools::extract_boundary_dofs(dof_handler_artificial_dissipation,
2540  dealii::ComponentMask(),
2541  boundary_dofs);
2542  for (unsigned int i = 0; i < dof_handler_artificial_dissipation.n_dofs(); ++i) {
2543  if (boundary_dofs.is_element(i)) {
2544  artificial_dissipation_c0[i] = 0.0;
2545  }
2546  }
2547  // artificial_dissipation_c0 *= 0.0;
2548  // artificial_dissipation_c0.add(1e-1);
2549  artificial_dissipation_c0.update_ghost_values();
2550 }
2551 
2552 template <int dim, int nspecies, typename real, typename MeshType>
2554  const unsigned int poly_degree_int,
2555  const unsigned int poly_degree_ext,
2556  const unsigned int /*grid_degree*/,
2557  OPERATOR::basis_functions<dim,2*dim> &soln_basis_int,
2558  OPERATOR::basis_functions<dim,2*dim> &soln_basis_ext,
2559  OPERATOR::basis_functions<dim,2*dim> &flux_basis_int,
2560  OPERATOR::basis_functions<dim,2*dim> &flux_basis_ext,
2561  OPERATOR::local_basis_stiffness<dim,2*dim> &flux_basis_stiffness,
2562  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_int,
2563  OPERATOR::vol_projection_operator<dim,2*dim> &soln_basis_projection_oper_ext,
2565 {
2566  soln_basis_int.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree_int], oneD_quadrature_collection[poly_degree_int]);
2567  soln_basis_int.build_1D_gradient_operator(oneD_fe_collection_1state[poly_degree_int], oneD_quadrature_collection[poly_degree_int]);
2570 
2571  soln_basis_ext.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree_ext], oneD_quadrature_collection[poly_degree_ext]);
2572  soln_basis_ext.build_1D_gradient_operator(oneD_fe_collection_1state[poly_degree_ext], oneD_quadrature_collection[poly_degree_ext]);
2575 
2576  flux_basis_int.build_1D_volume_operator(oneD_fe_collection_flux[poly_degree_int], oneD_quadrature_collection[poly_degree_int]);
2577  flux_basis_int.build_1D_gradient_operator(oneD_fe_collection_flux[poly_degree_int], oneD_quadrature_collection[poly_degree_int]);
2580 
2581  flux_basis_ext.build_1D_volume_operator(oneD_fe_collection_flux[poly_degree_ext], oneD_quadrature_collection[poly_degree_ext]);
2582  flux_basis_ext.build_1D_gradient_operator(oneD_fe_collection_flux[poly_degree_ext], oneD_quadrature_collection[poly_degree_ext]);
2585 
2586  //flux basis stiffness operator for skew-symmetric form
2587  flux_basis_stiffness.build_1D_volume_operator(oneD_fe_collection_flux[poly_degree_int], oneD_quadrature_collection[poly_degree_int]);
2588 
2589  //basis functions projection operator
2590  soln_basis_projection_oper_int.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree_int], oneD_quadrature_collection[poly_degree_int]);
2591  soln_basis_projection_oper_ext.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree_ext], oneD_quadrature_collection[poly_degree_ext]);
2592 
2593  //We only need to compute the most recent mapping basis since we compute interior before looping faces
2594  mapping_basis.build_1D_shape_functions_at_grid_nodes(high_order_grid->oneD_fe_system, high_order_grid->oneD_grid_nodes);
2596 }
2597 
2598 template <int dim, int nspecies, typename real, typename MeshType>
2599 void DGBase<dim,nspecies,real,MeshType>::assemble_residual (const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R, const double CFL_mass)
2600 {
2601  dealii::deal_II_exceptions::disable_abort_on_exception(); // Allows us to catch negative Jacobians.
2602  Assert( !(compute_dRdW && compute_dRdX)
2603  && !(compute_dRdW && compute_d2R)
2604  && !(compute_dRdX && compute_d2R)
2605  , dealii::ExcMessage("Can only do one at a time compute_dRdW or compute_dRdX or compute_d2R"));
2606 
2608  //pcout << "Assembling DG residual...";
2609  if (compute_dRdW) {
2610  pcout << " with dRdW...";
2611 
2612  auto diff_sol = solution;
2613  diff_sol -= solution_dRdW;
2614  const double l2_norm_sol = diff_sol.l2_norm();
2615 
2616  if (l2_norm_sol == 0.0) {
2617 
2618  auto diff_node = high_order_grid->volume_nodes;
2619  diff_node -= volume_nodes_dRdW;
2620  const double l2_norm_node = diff_node.l2_norm();
2621 
2622  if (l2_norm_node == 0.0) {
2623  if (CFL_mass_dRdW == CFL_mass) {
2624  pcout << " which is already assembled..." << std::endl;
2625  return;
2626  }
2627  }
2628  }
2629  {
2630  int n_stencil = 1 + std::pow(2,dim);
2631  int n_dofs_cell = nstate*std::pow(max_degree+1,dim);
2632  n_vmult += n_stencil*n_dofs_cell;
2633  dRdW_form += 1;
2634  }
2636  volume_nodes_dRdW = high_order_grid->volume_nodes;
2637  CFL_mass_dRdW = CFL_mass;
2638 
2639  system_matrix = 0;
2640  }
2641  if (compute_dRdX) {
2642  pcout << " with dRdX...";
2643 
2644  auto diff_sol = solution;
2645  diff_sol -= solution_dRdX;
2646  const double l2_norm_sol = diff_sol.l2_norm();
2647 
2648  if (l2_norm_sol == 0.0) {
2649 
2650  auto diff_node = high_order_grid->volume_nodes;
2651  diff_node -= volume_nodes_dRdX;
2652  const double l2_norm_node = diff_node.l2_norm();
2653 
2654  if (l2_norm_node == 0.0) {
2655  pcout << " which is already assembled..." << std::endl;
2656  return;
2657  }
2658  }
2660  volume_nodes_dRdX = high_order_grid->volume_nodes;
2661 
2662  if ( dRdXv.m() != solution.size() || dRdXv.n() != high_order_grid->volume_nodes.size()) {
2663 
2664  allocate_dRdX();
2665  }
2666  dRdXv = 0;
2667  }
2668  if (compute_d2R) {
2669  pcout << " with d2RdWdW, d2RdWdX, d2RdXdX...";
2670  auto diff_sol = solution;
2671  diff_sol -= solution_d2R;
2672  const double l2_norm_sol = diff_sol.l2_norm();
2673 
2674  if (l2_norm_sol == 0.0) {
2675 
2676  auto diff_node = high_order_grid->volume_nodes;
2677  diff_node -= volume_nodes_d2R;
2678  const double l2_norm_node = diff_node.l2_norm();
2679 
2680  if (l2_norm_node == 0.0) {
2681 
2682  auto diff_dual = dual;
2683  diff_dual -= dual_d2R;
2684  const double l2_norm_dual = diff_dual.l2_norm();
2685  if (l2_norm_dual == 0.0) {
2686  pcout << " which is already assembled..." << std::endl;
2687  return;
2688  }
2689  }
2690  }
2692  volume_nodes_d2R = high_order_grid->volume_nodes;
2693  dual_d2R = dual;
2694 
2695  if ( d2RdWdW.m() != solution.size()
2696  || d2RdWdX.m() != solution.size()
2697  || d2RdWdX.n() != high_order_grid->volume_nodes.size()
2698  || d2RdXdX.m() != high_order_grid->volume_nodes.size()) {
2699 
2701  }
2702  d2RdWdW = 0;
2703  d2RdWdX = 0;
2704  d2RdXdX = 0;
2705  }
2706  right_hand_side = 0;
2707 
2708 
2709  //const dealii::MappingManifold<dim,dim> mapping;
2710  //const dealii::MappingQ<dim,dim> mapping(10);//;max_degree+1);
2711  //const dealii::MappingQ<dim,dim> mapping(high_order_grid->max_degree);
2712  //const dealii::MappingQGeneric<dim,dim> mapping(high_order_grid->max_degree);
2713  const auto mapping = (*(high_order_grid->mapping_fe_field));
2714 
2715  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
2716 
2717  dealii::hp::FEValues<dim,dim> fe_values_collection_volume (mapping_collection, fe_collection, volume_quadrature_collection, this->volume_update_flags);
2718  dealii::hp::FEFaceValues<dim,dim> fe_values_collection_face_int (mapping_collection, fe_collection, face_quadrature_collection, this->face_update_flags);
2719  dealii::hp::FEFaceValues<dim,dim> fe_values_collection_face_ext (mapping_collection, fe_collection, face_quadrature_collection, this->neighbor_face_update_flags);
2720  dealii::hp::FESubfaceValues<dim,dim> fe_values_collection_subface (mapping_collection, fe_collection, face_quadrature_collection, this->face_update_flags);
2721 
2722  dealii::hp::FEValues<dim,dim> fe_values_collection_volume_lagrange (mapping_collection, fe_collection_lagrange, volume_quadrature_collection, this->volume_update_flags);
2723 
2724  const unsigned int init_grid_degree = high_order_grid->fe_system.tensor_degree();
2725  OPERATOR::basis_functions<dim,2*dim> soln_basis_int(1, max_degree, init_grid_degree);
2726  OPERATOR::basis_functions<dim,2*dim> soln_basis_ext(1, max_degree, init_grid_degree);
2727  OPERATOR::basis_functions<dim,2*dim> flux_basis_int(1, max_degree, init_grid_degree);
2728  OPERATOR::basis_functions<dim,2*dim> flux_basis_ext(1, max_degree, init_grid_degree);
2729  OPERATOR::local_basis_stiffness<dim,2*dim> flux_basis_stiffness(1, max_degree, init_grid_degree, true);
2730  OPERATOR::vol_projection_operator<dim,2*dim> soln_basis_projection_oper_int(1, max_degree, init_grid_degree);
2731  OPERATOR::vol_projection_operator<dim,2*dim> soln_basis_projection_oper_ext(1, max_degree, init_grid_degree);
2732  OPERATOR::mapping_shape_functions<dim,2*dim> mapping_basis(1, init_grid_degree, init_grid_degree);
2733 
2735  max_degree, max_degree, init_grid_degree,
2736  soln_basis_int, soln_basis_ext,
2737  flux_basis_int, flux_basis_ext,
2738  flux_basis_stiffness,
2739  soln_basis_projection_oper_int, soln_basis_projection_oper_ext,
2740  mapping_basis);
2741 
2742  solution.update_ghost_values();
2743 
2744 
2745  int assembly_error = 0;
2746  try {
2747 
2748  // update artificial dissipation discontinuity sensor only if using artificial dissipation
2750 
2751  // updates model variables only if there is a model
2752  if(all_parameters->pde_type == Parameters::AllParameters::PartialDifferentialEquation::physics_model ||
2753  all_parameters->pde_type == Parameters::AllParameters::PartialDifferentialEquation::physics_model_filtered) update_model_variables();
2754 
2755  // assembles and solves for auxiliary variable if necessary.
2756  assemble_auxiliary_residual(compute_dRdW, compute_dRdX, compute_d2R);
2757 
2758  dealii::Timer timer;
2760  timer.start();
2761  }
2762 
2763  auto metric_cell = high_order_grid->dof_handler_grid.begin_active();
2764  if(compute_d2R)
2765  {
2766  for (auto soln_cell = dof_handler.begin_active(); soln_cell != dof_handler.end(); ++soln_cell, ++metric_cell)
2767  {
2768  if (!soln_cell->is_locally_owned()) continue;
2769  assemble_cell_residual_and_ad_derivatives<codi_HessianComputationType>(
2770  soln_cell,
2771  metric_cell,
2772  compute_dRdW, compute_dRdX, compute_d2R,
2773  fe_values_collection_volume,
2774  fe_values_collection_face_int,
2775  fe_values_collection_face_ext,
2776  fe_values_collection_subface,
2777  fe_values_collection_volume_lagrange,
2778  soln_basis_int,
2779  soln_basis_ext,
2780  flux_basis_int,
2781  flux_basis_ext,
2782  flux_basis_stiffness,
2783  soln_basis_projection_oper_int,
2784  soln_basis_projection_oper_ext,
2785  mapping_basis,
2786  false,
2789  }
2790  }
2791  else if(compute_dRdW || compute_dRdX)
2792  {
2793  for (auto soln_cell = dof_handler.begin_active(); soln_cell != dof_handler.end(); ++soln_cell, ++metric_cell)
2794  {
2795  if (!soln_cell->is_locally_owned()) continue;
2796  assemble_cell_residual_and_ad_derivatives<codi_JacobianComputationType>(
2797  soln_cell,
2798  metric_cell,
2799  compute_dRdW, compute_dRdX, compute_d2R,
2800  fe_values_collection_volume,
2801  fe_values_collection_face_int,
2802  fe_values_collection_face_ext,
2803  fe_values_collection_subface,
2804  fe_values_collection_volume_lagrange,
2805  soln_basis_int,
2806  soln_basis_ext,
2807  flux_basis_int,
2808  flux_basis_ext,
2809  flux_basis_stiffness,
2810  soln_basis_projection_oper_int,
2811  soln_basis_projection_oper_ext,
2812  mapping_basis,
2813  false,
2816  }
2817  }
2818  else
2819  {
2820  for (auto soln_cell = dof_handler.begin_active(); soln_cell != dof_handler.end(); ++soln_cell, ++metric_cell)
2821  {
2822  if (!soln_cell->is_locally_owned()) continue;
2823  assemble_cell_residual_and_ad_derivatives<double>(
2824  soln_cell,
2825  metric_cell,
2826  compute_dRdW, compute_dRdX, compute_d2R,
2827  fe_values_collection_volume,
2828  fe_values_collection_face_int,
2829  fe_values_collection_face_ext,
2830  fe_values_collection_subface,
2831  fe_values_collection_volume_lagrange,
2832  soln_basis_int,
2833  soln_basis_ext,
2834  flux_basis_int,
2835  flux_basis_ext,
2836  flux_basis_stiffness,
2837  soln_basis_projection_oper_int,
2838  soln_basis_projection_oper_ext,
2839  mapping_basis,
2840  false,
2843  }
2844  }
2845 
2847  timer.stop();
2848  assemble_residual_time += timer.cpu_time();
2849  }
2850  } catch(...) {
2851  assembly_error = 1;
2852  }
2853  // NOTE: To debug the code with gdb, the above 3 lines `catch(...)` may need to be commented out
2854  const int mpi_assembly_error = dealii::Utilities::MPI::sum(assembly_error, mpi_communicator);
2855 
2856  if (mpi_assembly_error != 0) {
2857  std::cout << "Invalid residual assembly encountered..."
2858  << " Filling up RHS with 1s. " << std::endl;
2859  right_hand_side *= 0.0;
2860  right_hand_side.add(1.0);
2861  if (compute_dRdW) {
2862  std::cout << " Filling up Jacobian with mass matrix. " << std::endl;
2863  const bool do_inverse_mass_matrix = false;
2864  evaluate_mass_matrices (do_inverse_mass_matrix);
2865  system_matrix.copy_from(global_mass_matrix);
2866  }
2867  //if (compute_dRdX) {
2868  // dRdXv.trilinos_matrix().
2869  //}
2870  //if (compute_d2R) {
2871  // d2RdWdW = 0;
2872  // d2RdWdX = 0;
2873  // d2RdXdX = 0;
2874  //}
2875  }
2876 
2877  right_hand_side.compress(dealii::VectorOperation::add);
2878  right_hand_side.update_ghost_values();
2879  if ( compute_dRdW ) {
2880  system_matrix.compress(dealii::VectorOperation::add);
2881 
2882  if (global_mass_matrix.m() != system_matrix.m()) {
2883  const bool do_inverse_mass_matrix = false;
2884  evaluate_mass_matrices (do_inverse_mass_matrix);
2885  }
2886  if (CFL_mass != 0.0) {
2887  time_scaled_mass_matrices(CFL_mass);
2889  }
2890 
2891  Epetra_CrsMatrix *input_matrix = const_cast<Epetra_CrsMatrix *>(&(system_matrix.trilinos_matrix()));
2892  Epetra_CrsMatrix *output_matrix;
2893  epetra_rowmatrixtransposer_dRdW = std::make_unique<Epetra_RowMatrixTransposer> ( input_matrix );
2894  const bool make_data_contiguous = true;
2895  int error_transpose = epetra_rowmatrixtransposer_dRdW->CreateTranspose( make_data_contiguous, output_matrix);
2896  if (error_transpose) {
2897  std::cout << "Failed to create dRdW transpose... Aborting" << std::endl;
2898  //std::abort();
2899  }
2900  bool copy_values = true;
2901  system_matrix_transpose.reinit(*output_matrix, copy_values);
2902  delete(output_matrix);
2903 
2904  }
2905  if ( compute_dRdX ) dRdXv.compress(dealii::VectorOperation::add);
2906  if ( compute_d2R ) {
2907  d2RdWdW.compress(dealii::VectorOperation::add);
2908  d2RdXdX.compress(dealii::VectorOperation::add);
2909  d2RdWdX.compress(dealii::VectorOperation::add);
2910  }
2911  //if ( compute_dRdW ) system_matrix.compress(dealii::VectorOperation::insert);
2912  //system_matrix.print(std::cout);
2913 
2914 } // end of assemble_system_explicit ()
2915 
2916 template <int dim, int nspecies, typename real, typename MeshType>
2918 {
2919  pcout << "Evaluating residual Linf-norm..." << std::endl;
2920  const auto mapping = (*(high_order_grid->mapping_fe_field));
2921  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
2922 
2923  double residual_linf_norm = 0.0;
2924  std::vector<dealii::types::global_dof_index> dofs_indices;
2925  const dealii::UpdateFlags update_flags = dealii::update_values | dealii::update_JxW_values;
2926  dealii::hp::FEValues<dim,dim> fe_values_collection_volume (mapping_collection,
2927  fe_collection,
2929  update_flags);
2930 
2931  // Obtain the mapping from local dof indices to global dof indices
2932  for (const auto& cell : dof_handler.active_cell_iterators()) {
2933  if (!cell->is_locally_owned()) continue;
2934 
2935  const int i_fele = cell->active_fe_index();
2936  const int i_quad = i_fele;
2937  const int i_mapp = 0;
2938 
2939  fe_values_collection_volume.reinit (cell, i_quad, i_mapp, i_fele);
2940  const dealii::FEValues<dim,dim> &fe_values_vol = fe_values_collection_volume.get_present_fe_values();
2941 
2942  const dealii::FESystem<dim,dim> &fe_ref = fe_collection[i_fele];
2943  const unsigned int n_dofs = fe_ref.n_dofs_per_cell();
2944  const unsigned int n_quad = fe_values_vol.n_quadrature_points;
2945 
2946  dofs_indices.resize(n_dofs);
2947  cell->get_dof_indices (dofs_indices);
2948 
2949  for (unsigned int iquad = 0; iquad < n_quad; ++iquad) {
2950  double residual_val = 0.0;
2951  for (unsigned int idof = 0; idof < n_dofs; ++idof) {
2952  const unsigned int istate = fe_values_vol.get_fe().system_to_component_index(idof).first;
2953  residual_val += right_hand_side[dofs_indices[idof]] * fe_values_vol.shape_value_component(idof, iquad, istate);
2954  }
2955  residual_linf_norm = std::max(std::abs(residual_val), residual_val);
2956  }
2957 
2958  }
2959  const double mpi_residual_linf_norm = dealii::Utilities::MPI::max(residual_linf_norm, mpi_communicator);
2960  return mpi_residual_linf_norm;
2961 }
2962 
2963 
2964 template <int dim, int nspecies, typename real, typename MeshType>
2966 {
2967 
2968  //return get_residual_linfnorm ();
2969  //return right_hand_side.l2_norm();
2970  //return right_hand_side.l2_norm() / right_hand_side.size();
2971  //auto scaled_residual = right_hand_side;
2972  //global_mass_matrix.vmult(scaled_residual, right_hand_side);
2973  //return scaled_residual.l2_norm();
2974  //pcout << "Evaluating residual L2-norm..." << std::endl;
2975 
2976  const auto mapping = (*(high_order_grid->mapping_fe_field));
2977  dealii::hp::MappingCollection<dim> mapping_collection(mapping);
2978 
2979  double residual_l2_norm = 0.0;
2980  double domain_volume = 0.0;
2981  std::vector<dealii::types::global_dof_index> dofs_indices;
2982  const dealii::UpdateFlags update_flags = dealii::update_values | dealii::update_JxW_values;
2983  dealii::hp::FEValues<dim,dim> fe_values_collection_volume (mapping_collection,
2984  fe_collection,
2986  update_flags);
2987 
2988  // Obtain the mapping from local dof indices to global dof indices
2989  for (const auto& cell : dof_handler.active_cell_iterators()) {
2990  if (!cell->is_locally_owned()) continue;
2991 
2992  const int i_fele = cell->active_fe_index();
2993  const int i_quad = i_fele;
2994  const int i_mapp = 0;
2995 
2996  fe_values_collection_volume.reinit (cell, i_quad, i_mapp, i_fele);
2997  const dealii::FEValues<dim,dim> &fe_values_vol = fe_values_collection_volume.get_present_fe_values();
2998 
2999  const dealii::FESystem<dim,dim> &fe_ref = fe_collection[i_fele];
3000  const unsigned int n_dofs = fe_ref.n_dofs_per_cell();
3001  const unsigned int n_quad = fe_values_vol.n_quadrature_points;
3002 
3003  dofs_indices.resize(n_dofs);
3004  cell->get_dof_indices (dofs_indices);
3005 
3006  for (unsigned int iquad = 0; iquad < n_quad; ++iquad) {
3007  double residual_val = 0.0;
3008  for (unsigned int idof = 0; idof < n_dofs; ++idof) {
3009  const unsigned int istate = fe_values_vol.get_fe().system_to_component_index(idof).first;
3010  residual_val += right_hand_side[dofs_indices[idof]] * fe_values_vol.shape_value_component(idof, iquad, istate);
3011  }
3012  residual_l2_norm += residual_val*residual_val * fe_values_vol.JxW(iquad);
3013  domain_volume += fe_values_vol.JxW(iquad);
3014  }
3015 
3016  }
3017  const double mpi_residual_l2_norm = dealii::Utilities::MPI::sum(residual_l2_norm, mpi_communicator);
3018  const double mpi_domain_volume = dealii::Utilities::MPI::sum(domain_volume, mpi_communicator);
3019  return std::sqrt(mpi_residual_l2_norm) / mpi_domain_volume;
3020 }
3021 
3022 template <int dim, int nspecies, typename real, typename MeshType>
3024 {
3025  return dof_handler.n_dofs();
3026 }
3027 
3028 
3029 #if PHILIP_DIM > 1
3030 template <int dim, typename DoFHandlerType = dealii::DoFHandler<dim>>
3031 class DataOutEulerFaces : public dealii::DataOutFaces<dim, DoFHandlerType>
3032 {
3033  static const unsigned int dimension = DoFHandlerType::dimension;
3034  static const unsigned int space_dimension = DoFHandlerType::space_dimension;
3035  using cell_iterator = typename dealii::DataOut_DoFData<DoFHandlerType, dimension - 1, dimension>::cell_iterator;
3036 
3037  using FaceDescriptor = typename std::pair<cell_iterator, unsigned int>;
3048  virtual FaceDescriptor first_face() override;
3049 
3071  virtual FaceDescriptor next_face(const FaceDescriptor &face) override;
3072 
3073 };
3074 
3075 template <int dim, typename DoFHandlerType>
3076 typename DataOutEulerFaces<dim, DoFHandlerType>::FaceDescriptor
3077 DataOutEulerFaces<dim, DoFHandlerType>::first_face()
3078 {
3079  // simply find first active cell with a face on the boundary
3080  typename dealii::Triangulation<dimension, space_dimension>::active_cell_iterator
3081  cell = this->triangulation->begin_active();
3082  for (; cell != this->triangulation->end(); ++cell)
3083  if (cell->is_locally_owned())
3084  for (const unsigned int f : dealii::GeometryInfo<dimension>::face_indices())
3085  if (cell->face(f)->at_boundary())
3086  if (cell->face(f)->boundary_id() == 1001)
3087  return FaceDescriptor(cell, f);
3088 
3089  // just return an invalid descriptor if we haven't found a locally
3090  // owned face. this can happen in parallel where all boundary
3091  // faces are owned by other processors
3092  return FaceDescriptor();
3093 }
3094 
3095 template <int dim, typename DoFHandlerType>
3096 typename DataOutEulerFaces<dim, DoFHandlerType>::FaceDescriptor
3097 DataOutEulerFaces<dim, DoFHandlerType>::next_face(const FaceDescriptor &old_face)
3098 {
3099  FaceDescriptor face = old_face;
3100 
3101  // first check whether the present cell has more faces on the boundary. since
3102  // we started with this face, its cell must clearly be locally owned
3103  Assert(face.first->is_locally_owned(), dealii::ExcInternalError());
3104  for (unsigned int f = face.second + 1; f < dealii::GeometryInfo<dimension>::faces_per_cell; ++f)
3105  if (face.first->face(f)->at_boundary())
3106  if (face.first->face(f)->boundary_id() == 1001) {
3107  // yup, that is so, so return it
3108  face.second = f;
3109  return face;
3110  }
3111 
3112  // otherwise find the next active cell that has a face on the boundary
3113 
3114  // convert the iterator to an active_iterator and advance this to the next
3115  // active cell
3116  typename dealii::Triangulation<dimension, space_dimension>::active_cell_iterator
3117  active_cell = face.first;
3118 
3119  // increase face pointer by one
3120  ++active_cell;
3121 
3122  // while there are active cells
3123  while (active_cell != this->triangulation->end()) {
3124  // check all the faces of this active cell. but skip it altogether
3125  // if it isn't locally owned
3126  if (active_cell->is_locally_owned())
3127  for (const unsigned int f : dealii::GeometryInfo<dimension>::face_indices())
3128  if (active_cell->face(f)->at_boundary())
3129  if (active_cell->face(f)->boundary_id() == 1001) {
3130  face.first = active_cell;
3131  face.second = f;
3132  return face;
3133  }
3134 
3135  // the present cell had no faces on the boundary (or was not locally
3136  // owned), so check next cell
3137  ++active_cell;
3138  }
3139 
3140  // we fell off the edge, so return with invalid pointer
3141  face.first = this->triangulation->end();
3142  face.second = 0;
3143  return face;
3144 }
3145 
3146 template <int dim>
3147 class NormalPostprocessor : public dealii::DataPostprocessorVector<dim>
3148 {
3149 public:
3150  NormalPostprocessor ()
3151  : dealii::DataPostprocessorVector<dim> ("normal", dealii::update_normal_vectors)
3152  {}
3153  virtual void
3154  evaluate_vector_field (const dealii::DataPostprocessorInputs::Vector<dim> &input_data, std::vector<dealii::Vector<double>> &computed_quantities) const override
3155  {
3156  // ensure that there really are as many output slots
3157  // as there are points at which DataOut provides the
3158  // gradients:
3159  AssertDimension (input_data.normals.size(), computed_quantities.size());
3160  // then loop over all of these inputs:
3161  for (unsigned int p=0; p<input_data.solution_gradients.size(); ++p) {
3162  // ensure that each output slot has exactly 'dim'
3163  // components (as should be expected, given that we
3164  // want to create vector-valued outputs), and copy the
3165  // gradients of the solution at the evaluation points
3166  // into the output slots:
3167  AssertDimension (computed_quantities[p].size(), dim);
3168  for (unsigned int d=0; d<dim; ++d)
3169  computed_quantities[p][d] = input_data.normals[p][d];
3170  }
3171  }
3172  virtual void
3173  evaluate_scalar_field (const dealii::DataPostprocessorInputs::Scalar<dim> &input_data, std::vector<dealii::Vector<double> > &computed_quantities) const override
3174  {
3175  // ensure that there really are as many output slots
3176  // as there are points at which DataOut provides the
3177  // gradients:
3178  AssertDimension (input_data.normals.size(), computed_quantities.size());
3179  // then loop over all of these inputs:
3180  for (unsigned int p=0; p<input_data.solution_gradients.size(); ++p) {
3181  // ensure that each output slot has exactly 'dim'
3182  // components (as should be expected, given that we
3183  // want to create vector-valued outputs), and copy the
3184  // gradients of the solution at the evaluation points
3185  // into the output slots:
3186  AssertDimension (computed_quantities[p].size(), dim);
3187  for (unsigned int d=0; d<dim; ++d)
3188  computed_quantities[p][d] = input_data.normals[p][d];
3189  }
3190  }
3191 };
3192 
3193 
3194 
3195 template <int dim, int nspecies, typename real, typename MeshType>
3196 void DGBase<dim,nspecies,real,MeshType>::output_face_results_vtk (const unsigned int cycle, const double current_time,
3197  const bool output_time_averaged_solution,
3198  const bool output_fluctuating_quantities)// const
3199 {
3200 
3201  DataOutEulerFaces<dim, dealii::DoFHandler<dim>> data_out;
3202 
3203  data_out.attach_dof_handler (dof_handler);
3204 
3205  std::vector<std::string> position_names;
3206  for(int d=0;d<dim;++d) {
3207  if (d==0) position_names.push_back("x");
3208  if (d==1) position_names.push_back("y");
3209  if (d==2) position_names.push_back("z");
3210  }
3211  std::vector<dealii::DataComponentInterpretation::DataComponentInterpretation> data_component_interpretation(dim, dealii::DataComponentInterpretation::component_is_scalar);
3212  data_out.add_data_vector (high_order_grid->dof_handler_grid, high_order_grid->volume_nodes, position_names, data_component_interpretation);
3213 
3214  dealii::Vector<float> subdomain(triangulation->n_active_cells());
3215  for (unsigned int i = 0; i < subdomain.size(); ++i) {
3216  subdomain(i) = triangulation->locally_owned_subdomain();
3217  }
3218  const std::string name = "subdomain";
3219  data_out.add_data_vector(subdomain, name, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim-1,dim>::DataVectorType::type_cell_data);
3220 
3222  data_out.add_data_vector(artificial_dissipation_coeffs, std::string("artificial_dissipation_coeffs"), dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim-1,dim>::DataVectorType::type_cell_data);
3223  data_out.add_data_vector(artificial_dissipation_se, std::string("artificial_dissipation_se"), dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim-1,dim>::DataVectorType::type_cell_data);
3224  data_out.add_data_vector(dof_handler_artificial_dissipation, artificial_dissipation_c0, std::string("artificial_dissipation_c0"));
3225  }
3226 
3227  data_out.add_data_vector(max_dt_cell, std::string("max_dt_cell"), dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim-1,dim>::DataVectorType::type_cell_data);
3228 
3229  data_out.add_data_vector(cell_volume, std::string("cell_volume"), dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim-1,dim>::DataVectorType::type_cell_data);
3230 
3231 
3232  // Let the physics post-processor determine what to output.
3233  const std::unique_ptr< dealii::DataPostprocessor<dim> > post_processor = Postprocess::PostprocessorFactory<dim,nspecies>::create_Postprocessor(all_parameters);
3234  if(output_time_averaged_solution && !output_fluctuating_quantities){
3235  data_out.add_data_vector (time_averaged_solution, *post_processor);
3236  } else if(output_fluctuating_quantities && !output_time_averaged_solution){
3237  std::vector<std::string> fluctuating_quantities_names = {"u'v'","u'u'", "v'v'", "w'w'", "u'w'"};
3238  data_out.add_data_vector (fluctuating_quantities, fluctuating_quantities_names, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim-1,dim>::DataVectorType::type_dof_data);
3239  } else {
3240  data_out.add_data_vector (solution, *post_processor);
3241  }
3242 
3243 
3244  NormalPostprocessor<dim> normals_post_processor;
3245  data_out.add_data_vector (solution, normals_post_processor);
3246 
3247  // Output the polynomial degree in each cell
3248  std::vector<unsigned int> active_fe_indices;
3249  dof_handler.get_active_fe_indices(active_fe_indices);
3250  dealii::Vector<double> active_fe_indices_dealiivector(active_fe_indices.begin(), active_fe_indices.end());
3251  dealii::Vector<double> cell_poly_degree = active_fe_indices_dealiivector;
3252 
3253  data_out.add_data_vector (active_fe_indices_dealiivector, "PolynomialDegree", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim-1,dim>::DataVectorType::type_cell_data);
3254 
3255  // Output absolute value of the residual so that we can visualize it on a logscale.
3256  std::vector<std::string> residual_names;
3257  for(int s=0;s<nstate;++s) {
3258  std::string varname = "residual" + dealii::Utilities::int_to_string(s,1);
3259  residual_names.push_back(varname);
3260  }
3261  auto residual = right_hand_side;
3262  for (auto &&rhs_value : residual) {
3263  if (std::signbit(rhs_value)) rhs_value = -rhs_value;
3264  if (rhs_value == 0.0) rhs_value = std::numeric_limits<double>::min();
3265  }
3266  residual.update_ghost_values();
3267  data_out.add_data_vector (residual, residual_names, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim-1,dim>::DataVectorType::type_dof_data);
3268 
3269  //for(int s=0;s<nstate;++s) {
3270  // residual_names[s] = "scaled_" + residual_names[s];
3271  //}
3272  //global_mass_matrix.vmult(residual, right_hand_side);
3273  //for (auto &&rhs_value : residual) {
3274  // if (std::signbit(rhs_value)) rhs_value = -rhs_value;
3275  // if (rhs_value == 0.0) rhs_value = std::numeric_limits<double>::min();
3276  //}
3277  //residual.update_ghost_values();
3278  //data_out.add_data_vector (residual, residual_names, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim-1,dim>::DataVectorType::type_dof_data);
3279 
3280 
3281  //typename dealii::DataOut<dim,dealii::DoFHandler<dim>>::CurvedCellRegion curved = dealii::DataOut<dim,dealii::DoFHandler<dim>>::CurvedCellRegion::curved_inner_cells;
3282  //typename dealii::DataOut<dim>::CurvedCellRegion curved = dealii::DataOut<dim>::CurvedCellRegion::curved_boundary;
3283  //typename dealii::DataOut<dim>::CurvedCellRegion curved = dealii::DataOut<dim>::CurvedCellRegion::no_curved_cells;
3284 
3285  const dealii::Mapping<dim> &mapping = (*(high_order_grid->mapping_fe_field));
3286  const int grid_degree = high_order_grid->max_degree;
3287  //const int n_subdivisions = max_degree+1;//+30; // if write_higher_order_cells, n_subdivisions represents the order of the cell
3288  //const int n_subdivisions = 1;//+30; // if write_higher_order_cells, n_subdivisions represents the order of the cell
3289  const int n_subdivisions = grid_degree;
3290  data_out.build_patches(mapping, n_subdivisions);
3291  //const bool write_higher_order_cells = (dim>1 && max_degree > 1) ? true : false;
3292  const bool write_higher_order_cells = false;//(dim>1 && grid_degree > 1) ? true : false;
3293  dealii::DataOutBase::VtkFlags vtkflags(current_time,cycle,true,dealii::DataOutBase::VtkFlags::ZlibCompressionLevel::best_compression,write_higher_order_cells);
3294  data_out.set_flags(vtkflags);
3295 
3296  const int iproc = dealii::Utilities::MPI::this_mpi_process(mpi_communicator);
3297  std::string filename_prefix = "surface_solution"; // default
3298  if(output_time_averaged_solution && !output_fluctuating_quantities) filename_prefix = "time_averaged_surface_solution";
3299  else if(output_fluctuating_quantities && !output_time_averaged_solution) filename_prefix = "fluctuating_surface_quantities";
3300  std::string filename = this->all_parameters->solution_vtk_files_directory_name + "/" + filename_prefix + "-" + dealii::Utilities::int_to_string(dim, 1) +"D_maxpoly"+dealii::Utilities::int_to_string(max_degree, 2)+"-";
3301  filename += dealii::Utilities::int_to_string(cycle, 4) + ".";
3302  filename += dealii::Utilities::int_to_string(iproc, 4);
3303  filename += ".vtu";
3304  std::ofstream output(filename);
3305  data_out.write_vtu(output);
3306  //std::cout << "Writing out file: " << filename << std::endl;
3307 
3308  if (iproc == 0) {
3309  std::vector<std::string> filenames;
3310  std::string filename_prefix = "surface_solution"; // default
3311  if(output_time_averaged_solution && !output_fluctuating_quantities) filename_prefix = "time_averaged_surface_solution";
3312  else if(output_fluctuating_quantities && !output_time_averaged_solution) filename_prefix = "fluctuating_surface_quantities";
3313  for (unsigned int iproc = 0; iproc < dealii::Utilities::MPI::n_mpi_processes(mpi_communicator); ++iproc) {;
3314  std::string fn = filename_prefix + "-" + dealii::Utilities::int_to_string(dim, 1) +"D_maxpoly"+dealii::Utilities::int_to_string(max_degree, 2)+"-";
3315  fn += dealii::Utilities::int_to_string(cycle, 4) + ".";
3316  fn += dealii::Utilities::int_to_string(iproc, 4);
3317  fn += ".vtu";
3318  filenames.push_back(fn);
3319  }
3320  std::string master_fn = this->all_parameters->solution_vtk_files_directory_name + "/" + "surface_solution-" + dealii::Utilities::int_to_string(dim, 1) +"D_maxpoly"+dealii::Utilities::int_to_string(max_degree, 2)+"-";
3321  master_fn += dealii::Utilities::int_to_string(cycle, 4) + ".pvtu";
3322  std::ofstream master_output(master_fn);
3323  data_out.write_pvtu_record(master_output, filenames);
3324  }
3327  (output_time_averaged_solution == false) && (output_fluctuating_quantities == false)) {
3328  output_face_results_vtk (cycle, current_time, true, false);
3331  output_face_results_vtk (cycle, current_time, false, true);
3332  }
3333  }
3334 
3335 }
3336 #endif
3337 
3338 template <int dim, int nspecies, typename real, typename MeshType>
3339 void DGBase<dim,nspecies,real,MeshType>::output_results_vtk (const unsigned int cycle, const double current_time,
3340  const bool output_time_averaged_solution,
3341  const bool output_fluctuating_quantities)// const
3342 {
3343 #if PHILIP_DIM>1
3344  if(this->all_parameters->output_face_results_vtk) output_face_results_vtk (cycle, current_time);
3345 #endif
3346 
3347  const bool enable_higher_order_vtk_output = this->all_parameters->enable_higher_order_vtk_output;
3348  dealii::DataOut<dim, dealii::DoFHandler<dim>> data_out;
3349 
3350  data_out.attach_dof_handler (dof_handler);
3351 
3352  std::vector<std::string> position_names;
3353  for(int d=0;d<dim;++d) {
3354  if (d==0) position_names.push_back("x");
3355  if (d==1) position_names.push_back("y");
3356  if (d==2) position_names.push_back("z");
3357  }
3358  std::vector<dealii::DataComponentInterpretation::DataComponentInterpretation> data_component_interpretation(dim, dealii::DataComponentInterpretation::component_is_scalar);
3359  data_out.add_data_vector (high_order_grid->dof_handler_grid, high_order_grid->volume_nodes, position_names, data_component_interpretation);
3360 
3361  dealii::Vector<float> subdomain(triangulation->n_active_cells());
3362  for (unsigned int i = 0; i < subdomain.size(); ++i) {
3363  subdomain(i) = triangulation->locally_owned_subdomain();
3364  }
3365  data_out.add_data_vector(subdomain, "subdomain", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
3366 
3368  data_out.add_data_vector(artificial_dissipation_coeffs, "artificial_dissipation_coeffs", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
3369  data_out.add_data_vector(artificial_dissipation_se, "artificial_dissipation_se", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
3370  data_out.add_data_vector(dof_handler_artificial_dissipation, artificial_dissipation_c0, "artificial_dissipation_c0");
3371  }
3372 
3373  data_out.add_data_vector(max_dt_cell, "max_dt_cell", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
3374 
3375  data_out.add_data_vector(reduced_mesh_weights, "reduced_mesh_weights", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
3376 
3377  data_out.add_data_vector(cell_volume, "cell_volume", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
3378 
3379 
3380  // Let the physics post-processor determine what to output.
3381  const std::unique_ptr< dealii::DataPostprocessor<dim> > post_processor = Postprocess::PostprocessorFactory<dim,nspecies>::create_Postprocessor(all_parameters);
3382  if(output_time_averaged_solution && !output_fluctuating_quantities){
3383  data_out.add_data_vector (time_averaged_solution, *post_processor);
3384  } else if(output_fluctuating_quantities && !output_time_averaged_solution){
3385  std::vector<std::string> fluctuating_quantities_names = {"u'v'","u'u'", "v'v'", "w'w'", "u'w'"};
3386  data_out.add_data_vector (fluctuating_quantities, fluctuating_quantities_names, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_dof_data);
3387  } else {
3388  data_out.add_data_vector (solution, *post_processor);
3389  }
3390 
3391  // Output the polynomial degree in each cell
3392  std::vector<unsigned int> active_fe_indices;
3393  dof_handler.get_active_fe_indices(active_fe_indices);
3394  dealii::Vector<double> active_fe_indices_dealiivector(active_fe_indices.begin(), active_fe_indices.end());
3395  dealii::Vector<double> cell_poly_degree = active_fe_indices_dealiivector;
3396 
3397  data_out.add_data_vector (active_fe_indices_dealiivector, "PolynomialDegree", dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_cell_data);
3398 
3399  // Output absolute value of the residual so that we can visualize it on a logscale.
3400  std::vector<std::string> residual_names;
3401  for(int s=0;s<nstate;++s) {
3402  std::string varname = "residual" + dealii::Utilities::int_to_string(s,1);
3403  residual_names.push_back(varname);
3404  }
3405  auto residual = right_hand_side;
3406  for (auto &&rhs_value : residual) {
3407  if (std::signbit(rhs_value)) rhs_value = -rhs_value;
3408  if (rhs_value == 0.0) rhs_value = std::numeric_limits<double>::min();
3409  }
3410  residual.update_ghost_values();
3411  data_out.add_data_vector (residual, residual_names, dealii::DataOut_DoFData<dealii::DoFHandler<dim>,dim>::DataVectorType::type_dof_data);
3412 
3413  typename dealii::DataOut<dim,dealii::DoFHandler<dim>>::CurvedCellRegion curved = dealii::DataOut<dim,dealii::DoFHandler<dim>>::CurvedCellRegion::curved_inner_cells;
3414  //typename dealii::DataOut<dim>::CurvedCellRegion curved = dealii::DataOut<dim>::CurvedCellRegion::curved_boundary;
3415  //typename dealii::DataOut<dim>::CurvedCellRegion curved = dealii::DataOut<dim>::CurvedCellRegion::no_curved_cells;
3416 
3417  const dealii::Mapping<dim> &mapping = (*(high_order_grid->mapping_fe_field));
3418  const unsigned int grid_degree = high_order_grid->max_degree;
3419  // If higher-order vtk output is not enabled, passing 0 will be interpreted as DataOutInterface::default_subdivisions
3420  const int n_subdivisions = (enable_higher_order_vtk_output) ? std::max(grid_degree,get_max_fe_degree()) : 0;
3421  data_out.build_patches(mapping, n_subdivisions, curved);
3422  const bool write_higher_order_cells = (n_subdivisions>1 && dim>1) ? true : false;
3423  dealii::DataOutBase::VtkFlags vtkflags(current_time,cycle,true,dealii::DataOutBase::VtkFlags::ZlibCompressionLevel::best_compression,write_higher_order_cells);
3424  data_out.set_flags(vtkflags);
3425 
3426  const int iproc = dealii::Utilities::MPI::this_mpi_process(mpi_communicator);
3427  std::string filename_prefix = "solution"; // default
3428  if(output_time_averaged_solution && !output_fluctuating_quantities) filename_prefix = "time_averaged_solution";
3429  else if(output_fluctuating_quantities && !output_time_averaged_solution) filename_prefix = "fluctuating_quantities";
3430  std::string filename = this->all_parameters->solution_vtk_files_directory_name + "/" + filename_prefix + "-" + dealii::Utilities::int_to_string(dim, 1) +"D_maxpoly"+dealii::Utilities::int_to_string(max_degree, 2)+"-";
3431  filename += dealii::Utilities::int_to_string(cycle, 4) + ".";
3432  filename += dealii::Utilities::int_to_string(iproc, 4);
3433  filename += ".vtu";
3434  std::ofstream output(filename);
3435  data_out.write_vtu(output);
3436  //std::cout << "Writing out file: " << filename << std::endl;
3437 
3438  if (iproc == 0) {
3439  std::vector<std::string> filenames;
3440  for (unsigned int iproc = 0; iproc < dealii::Utilities::MPI::n_mpi_processes(mpi_communicator); ++iproc) {
3441  std::string fn = filename_prefix + "-" + dealii::Utilities::int_to_string(dim, 1) +"D_maxpoly"+dealii::Utilities::int_to_string(max_degree, 2)+"-";
3442  fn += dealii::Utilities::int_to_string(cycle, 4) + ".";
3443  fn += dealii::Utilities::int_to_string(iproc, 4);
3444  fn += ".vtu";
3445  filenames.push_back(fn);
3446  }
3447  std::string master_fn = this->all_parameters->solution_vtk_files_directory_name + "/" + "solution-" + dealii::Utilities::int_to_string(dim, 1) +"D_maxpoly"+dealii::Utilities::int_to_string(max_degree, 2)+"-";
3448  master_fn += dealii::Utilities::int_to_string(cycle, 4) + ".pvtu";
3449  std::ofstream master_output(master_fn);
3450  data_out.write_pvtu_record(master_output, filenames);
3451  }
3452 
3455  (output_time_averaged_solution == false) && (output_fluctuating_quantities == false))/*Only when false, such that it's not endlessly recursive. Do not set to true.*/ {
3456  output_results_vtk (cycle, current_time, true, false); //time-averaged quantites
3459  output_results_vtk (cycle, current_time, false, true); //fluctuating quantitites
3460  }
3461  }
3462 
3463 }
3464 
3465 template <int dim, int nspecies, typename real, typename MeshType>
3467 {
3468  for (int idim=0; idim<dim; idim++) {
3470  auxiliary_right_hand_side[idim].add(1.0);
3471 
3473  auxiliary_solution[idim] *= 0.0;
3474  }
3475 }
3476 
3477 template <int dim, int nspecies, typename real, typename MeshType>
3479  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3480 {
3481  pcout << "Allocating DG system and initializing FEValues" << std::endl;
3482  // This function allocates all the necessary memory to the
3483  // system matrices and vectors.
3484 
3485  dof_handler.distribute_dofs(fe_collection);
3486  //This Cuthill_McKee renumbering for dof_handlr uses a lot of memory in 3D, is there another way?
3487  using RenumberDofsType = Parameters::AllParameters::RenumberDofsType;
3488  if(all_parameters->do_renumber_dofs && all_parameters->renumber_dofs_type == RenumberDofsType::CuthillMckee ){
3489  dealii::DoFRenumbering::Cuthill_McKee(dof_handler,true);
3490  }
3491  //const bool reversed_numbering = true;
3492  //dealii::DoFRenumbering::Cuthill_McKee(dof_handler, reversed_numbering);
3493  //const bool reversed_numbering = false;
3494  //const bool use_constraints = false;
3495  //dealii::DoFRenumbering::boost::minimum_degree(dof_handler, reversed_numbering, use_constraints);
3496  //dealii::DoFRenumbering::boost::king_ordering(dof_handler, reversed_numbering, use_constraints);
3497 
3498  // Solution and RHS
3499  locally_owned_dofs = dof_handler.locally_owned_dofs();
3500  dealii::DoFTools::extract_locally_relevant_dofs(dof_handler, ghost_dofs);
3502  ghost_dofs.subtract_set(locally_owned_dofs);
3503  //dealii::DoFTools::extract_locally_relevant_dofs(dof_handler, locally_relevant_dofs);
3504 
3506 
3507  // Allocates artificial dissipation variables when required.
3509 
3510  max_dt_cell.reinit(triangulation->n_active_cells());
3511  cell_volume.reinit(triangulation->n_active_cells());
3512 
3513  reduced_mesh_weights.reinit(triangulation->n_active_cells());
3514 
3515  // allocates model variables only if there is a model
3516  if(all_parameters->pde_type == Parameters::AllParameters::PartialDifferentialEquation::physics_model ||
3517  all_parameters->pde_type == Parameters::AllParameters::PartialDifferentialEquation::physics_model_filtered) allocate_model_variables();
3518 
3520  solution *= 0.0;
3521  solution.add(std::numeric_limits<real>::lowest());
3522  //right_hand_side.reinit(locally_owned_dofs, mpi_communicator);
3524  right_hand_side.add(1.0); // Avoid 0 initial residual for output and logarithmic visualization.
3525  //time averaged solution
3527  time_averaged_solution.reinit(locally_owned_dofs, ghost_dofs, mpi_communicator);
3528  time_averaged_solution *= 0.0;
3529  time_averaged_solution.add(std::numeric_limits<real>::lowest());
3530  }
3531  //fluctuating quantities (i.e, Reynolds stresses)
3533  fluctuating_quantities.reinit(locally_owned_dofs, ghost_dofs, mpi_communicator);
3534  fluctuating_quantities *= 0.0;
3535  fluctuating_quantities.add(std::numeric_limits<real>::lowest());
3536  }
3538  std::cout << "\nNeed time-averaged solution to compute Reynolds stresses. Please set do_compute_time_averaged_solution=true. Aborting...\n";
3539  std::abort();
3540  }
3541 
3542  allocate_dual_vector(compute_d2R);
3543 
3544  // Set use_auxiliary_eq flag
3546 
3547  // Set store_vol_flux_nodes flag
3549 
3550  // Set store_surf_flux_nodes flag
3552 
3553  // Allocate for auxiliary equation only.
3555 
3556  // Set the assemble resiudla time to 0 for clock_t type
3557  assemble_residual_time = 0.0;
3558 
3559  // System matrix allocation
3560  if (compute_dRdW || compute_dRdX || compute_d2R) {
3561  dealii::DynamicSparsityPattern dsp(locally_relevant_dofs);
3562  dealii::DoFTools::make_flux_sparsity_pattern(dof_handler, dsp);
3563  dealii::SparsityTools::distribute_sparsity_pattern(dsp, dof_handler.locally_owned_dofs(), mpi_communicator, locally_relevant_dofs);
3564 
3565  sparsity_pattern.copy_from(dsp);
3566 
3568  }
3569 
3570  // Make sure that derivatives are cleared when reallocating DG objects.
3571  // The call to assemble the derivatives will reallocate those derivatives
3572  // if they are ever needed.
3573  system_matrix_transpose.clear();
3574  dRdXv.clear();
3575  d2RdWdX.clear();
3576  d2RdWdW.clear();
3577  d2RdXdX.clear();
3578 
3579  if (compute_dRdW) {
3580  solution_dRdW.reinit(solution);
3581  solution_dRdW *= 0.0;
3582  volume_nodes_dRdW.reinit(high_order_grid->volume_nodes);
3583  volume_nodes_dRdW *= 0.0;
3584  }
3585 
3586  CFL_mass_dRdW = 0.0;
3587 
3588  if (compute_dRdX) {
3589  solution_dRdX.reinit(solution);
3590  solution_dRdX *= 0.0;
3591  volume_nodes_dRdX.reinit(high_order_grid->volume_nodes);
3592  volume_nodes_dRdX *= 0.0;
3593  }
3594 
3595  if (compute_d2R) {
3596  solution_d2R.reinit(solution);
3597  solution_d2R *= 0.0;
3598  volume_nodes_d2R.reinit(high_order_grid->volume_nodes);
3599  volume_nodes_d2R *= 0.0;
3600  dual_d2R.reinit(dual);
3601  dual_d2R *= 0.0;
3602  }
3603 }
3604 
3605 template <int dim, int nspecies, typename real, typename MeshType>
3607 {
3608  const dealii::IndexSet locally_owned_dofs_artificial_dissipation = dof_handler_artificial_dissipation.locally_owned_dofs();
3609 
3610  dealii::IndexSet ghost_dofs_artificial_dissipation;
3611  dealii::IndexSet locally_relevant_dofs_artificial_dissipation;
3612  dealii::DoFTools::extract_locally_relevant_dofs(dof_handler_artificial_dissipation, ghost_dofs_artificial_dissipation);
3613  locally_relevant_dofs_artificial_dissipation = ghost_dofs_artificial_dissipation;
3614  ghost_dofs_artificial_dissipation.subtract_set(locally_owned_dofs_artificial_dissipation);
3615 
3616  artificial_dissipation_c0.reinit(locally_owned_dofs_artificial_dissipation, ghost_dofs_artificial_dissipation, mpi_communicator);
3617  artificial_dissipation_c0.update_ghost_values();
3618 
3619  artificial_dissipation_coeffs.reinit(triangulation->n_active_cells());
3620  artificial_dissipation_se.reinit(triangulation->n_active_cells());
3621 }
3622 
3623 
3624 template <int dim, int nspecies, typename real, typename MeshType>
3626 {
3627  locally_owned_dofs = dof_handler.locally_owned_dofs();
3628  {
3629  dealii::SparsityPattern sparsity_pattern_d2RdWdX = get_d2RdWdX_sparsity_pattern ();
3630  const dealii::IndexSet &row_parallel_partitioning_d2RdWdX = locally_owned_dofs;
3631  const dealii::IndexSet &col_parallel_partitioning_d2RdWdX = high_order_grid->locally_owned_dofs_grid;
3632  d2RdWdX.reinit(row_parallel_partitioning_d2RdWdX, col_parallel_partitioning_d2RdWdX, sparsity_pattern_d2RdWdX, mpi_communicator);
3633  }
3634 
3635  {
3636  dealii::SparsityPattern sparsity_pattern_d2RdWdW = get_d2RdWdW_sparsity_pattern ();
3637  const dealii::IndexSet &row_parallel_partitioning_d2RdWdW = locally_owned_dofs;
3638  const dealii::IndexSet &col_parallel_partitioning_d2RdWdW = locally_owned_dofs;
3639  d2RdWdW.reinit(row_parallel_partitioning_d2RdWdW, col_parallel_partitioning_d2RdWdW, sparsity_pattern_d2RdWdW, mpi_communicator);
3640  }
3641 
3642  {
3643  dealii::SparsityPattern sparsity_pattern_d2RdXdX = get_d2RdXdX_sparsity_pattern ();
3644  const dealii::IndexSet &row_parallel_partitioning_d2RdXdX = high_order_grid->locally_owned_dofs_grid;
3645  const dealii::IndexSet &col_parallel_partitioning_d2RdXdX = high_order_grid->locally_owned_dofs_grid;
3646  d2RdXdX.reinit(row_parallel_partitioning_d2RdXdX, col_parallel_partitioning_d2RdXdX, sparsity_pattern_d2RdXdX, mpi_communicator);
3647  }
3648 }
3649 
3650 template <int dim, int nspecies, typename real, typename MeshType>
3652 {
3653  // dRdXv matrix allocation
3654  dealii::SparsityPattern dRdXv_sparsity_pattern = get_dRdX_sparsity_pattern ();
3655  const dealii::IndexSet &row_parallel_partitioning = locally_owned_dofs;
3656  const dealii::IndexSet &col_parallel_partitioning = high_order_grid->locally_owned_dofs_grid;
3657  dRdXv.reinit(row_parallel_partitioning, col_parallel_partitioning, dRdXv_sparsity_pattern, MPI_COMM_WORLD);
3658 }
3659 
3660 template <int dim, int nspecies, typename real, typename MeshType>
3662  const bool Cartesian_element,
3663  const unsigned int poly_degree, const unsigned int grid_degree,
3666  OPERATOR::local_mass<dim,2*dim> &reference_mass_matrix,
3670 {
3672  const FR_enum FR_Type = this->all_parameters->flux_reconstruction_type;
3673 
3675  const FR_Aux_enum FR_Type_Aux = this->all_parameters->flux_reconstruction_aux_type;
3676 
3677  // Note the fe_collection passed for metric mapping operators has to be COLLOCATED ON GRID NODES
3679 
3680  if(Cartesian_element || this->all_parameters->use_weight_adjusted_mass){//then we can factor out det of Jac and rapidly simplify
3681  reference_mass_matrix.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree], oneD_quadrature_collection[poly_degree]);
3682  }
3683  if(grid_degree > 1 || !Cartesian_element){//then we need to construct dim matrices on the fly
3685  }
3686  if((FR_Type != FR_enum::cDG && Cartesian_element) || (FR_Type != FR_enum::cDG && this->all_parameters->use_weight_adjusted_mass)){
3687  reference_FR.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree], oneD_quadrature_collection[poly_degree]);
3688  }
3689  if((use_auxiliary_eq && FR_Type_Aux != FR_Aux_enum::kDG && Cartesian_element) || (FR_Type_Aux != FR_Aux_enum::kDG && this->all_parameters->use_weight_adjusted_mass)){
3690  reference_FR_aux.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree], oneD_quadrature_collection[poly_degree]);
3691  }
3692  if(((FR_Type != FR_enum::cDG) ||
3693  (use_auxiliary_eq && FR_Type_Aux != FR_Aux_enum::kDG) ) && (grid_degree > 1 || !Cartesian_element)){
3695  }
3696 }
3697 
3698 template <int dim, int nspecies, typename real, typename MeshType>
3700 {
3702  const FR_enum FR_Type = this->all_parameters->flux_reconstruction_type;
3703 
3704  const double FR_user_specified_correction_parameter_value = this->all_parameters->FR_user_specified_correction_parameter_value;
3705 
3707  const FR_Aux_enum FR_Type_Aux = this->all_parameters->flux_reconstruction_aux_type;
3708 
3709  // flag for energy tests
3710  const bool use_energy = this->all_parameters->use_energy;
3711 
3712  // Mass matrix sparsity pattern
3713  dealii::DynamicSparsityPattern dsp(dof_handler.n_dofs());
3714  std::vector<dealii::types::global_dof_index> dofs_indices;
3715  for (auto cell = dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) {
3716 
3717  if (!cell->is_locally_owned()) continue;
3718 
3719  const unsigned int fe_index_curr_cell = cell->active_fe_index();
3720 
3721  // Current reference element related to this physical cell
3722  const dealii::FESystem<dim,dim> &current_fe_ref = fe_collection[fe_index_curr_cell];
3723  const unsigned int n_dofs_cell = current_fe_ref.n_dofs_per_cell();
3724 
3725  dofs_indices.resize(n_dofs_cell);
3726  cell->get_dof_indices (dofs_indices);
3727  for (unsigned int itest=0; itest<n_dofs_cell; ++itest) {
3728  for (unsigned int itrial=0; itrial<n_dofs_cell; ++itrial) {
3729  dsp.add(dofs_indices[itest], dofs_indices[itrial]);
3730  }
3731  }
3732  }
3733  // Initialize global matrices to 0.
3734  dealii::SparsityTools::distribute_sparsity_pattern(dsp, dof_handler.locally_owned_dofs(), mpi_communicator, locally_owned_dofs);
3735  mass_sparsity_pattern.copy_from(dsp);
3736  if (do_inverse_mass_matrix) {
3738  if (use_auxiliary_eq){
3740  }
3741  if (use_energy){//for split form get energy
3743  if (use_auxiliary_eq){
3745  }
3746  }
3747  } else {
3749  if (use_auxiliary_eq){
3751  }
3752  }
3753 
3754  // setup 1D operators for ONE STATE. We loop over states in assembly for speedup.
3755  const unsigned int init_grid_degree = high_order_grid->fe_system.tensor_degree();
3756  OPERATOR::mapping_shape_functions<dim,2*dim> mapping_basis(1, max_degree, init_grid_degree);//first set at max degree
3757  OPERATOR::basis_functions<dim,2*dim> basis(1, max_degree, init_grid_degree);
3758  OPERATOR::local_mass<dim,2*dim> reference_mass_matrix(1, max_degree, init_grid_degree);//first set at max degree
3759  OPERATOR::local_Flux_Reconstruction_operator<dim,2*dim> reference_FR(1, max_degree, init_grid_degree, FR_Type, FR_user_specified_correction_parameter_value);
3760  OPERATOR::local_Flux_Reconstruction_operator_aux<dim,2*dim> reference_FR_aux(1, max_degree, init_grid_degree, FR_Type_Aux);
3761  OPERATOR::derivative_p<dim,2*dim> deriv_p(1, max_degree, init_grid_degree);
3762 
3763  auto first_cell = dof_handler.begin_active();
3764  const bool Cartesian_first_element = (first_cell->manifold_id() == dealii::numbers::flat_manifold_id);
3765 
3766  reinit_operators_for_mass_matrix(Cartesian_first_element, max_degree, init_grid_degree, mapping_basis, basis, reference_mass_matrix, reference_FR, reference_FR_aux, deriv_p);
3767 
3768  //Loop over cells and set the matrices.
3769  auto metric_cell = high_order_grid->dof_handler_grid.begin_active();
3770  for (auto cell = dof_handler.begin_active(); cell!=dof_handler.end(); ++cell, ++metric_cell) {
3771 
3772  if (!cell->is_locally_owned()) continue;
3773 
3774  const bool Cartesian_element = (cell->manifold_id() == dealii::numbers::flat_manifold_id);
3775 
3776  const unsigned int fe_index_curr_cell = cell->active_fe_index();
3777  const unsigned int curr_grid_degree = high_order_grid->fe_system.tensor_degree();//in the future the metric cell's should store a local grid degree. currently high_order_grid dof_handler_grid doesn't have that capability
3778 
3779  //Check if need to recompute the 1D basis for the current degree (if different than previous cell)
3780  //That is, if the poly_degree, manifold type, or grid degree is different than previous reference operator
3781  if((fe_index_curr_cell != mapping_basis.current_degree) ||
3782  (curr_grid_degree != mapping_basis.current_grid_degree))
3783  {
3784  reinit_operators_for_mass_matrix(Cartesian_element, fe_index_curr_cell, curr_grid_degree, mapping_basis, basis, reference_mass_matrix, reference_FR, reference_FR_aux, deriv_p);
3785 
3786  mapping_basis.current_degree = fe_index_curr_cell;
3787  basis.current_degree = fe_index_curr_cell;
3788  reference_mass_matrix.current_degree = fe_index_curr_cell;
3789  reference_FR.current_degree = fe_index_curr_cell;
3790  reference_FR_aux.current_degree = fe_index_curr_cell;
3791  deriv_p.current_degree = fe_index_curr_cell;
3792  }
3793 
3794  // Current reference element related to this physical cell
3795  const unsigned int n_dofs_cell = fe_collection[fe_index_curr_cell].n_dofs_per_cell();
3796  const unsigned int n_quad_pts = volume_quadrature_collection[fe_index_curr_cell].size();
3797 
3798  //setup metric cell
3799  const dealii::FESystem<dim> &fe_metric = high_order_grid->fe_system;
3800  const unsigned int n_metric_dofs = high_order_grid->fe_system.dofs_per_cell;
3801  const unsigned int n_grid_nodes = n_metric_dofs/dim;
3802  std::vector<dealii::types::global_dof_index> metric_dofs_indices(n_metric_dofs);
3803  metric_cell->get_dof_indices (metric_dofs_indices);
3804  // get mapping_support points
3805  std::array<std::vector<real>,dim> mapping_support_points;
3806  for(int idim=0; idim<dim; idim++){
3807  mapping_support_points[idim].resize(n_metric_dofs/dim);
3808  }
3809  const std::vector<unsigned int > &index_renumbering = dealii::FETools::hierarchic_to_lexicographic_numbering<dim>(curr_grid_degree);
3810  for (unsigned int idof = 0; idof< n_metric_dofs; ++idof) {
3811  const real val = (high_order_grid->volume_nodes[metric_dofs_indices[idof]]);
3812  const unsigned int istate = fe_metric.system_to_component_index(idof).first;
3813  const unsigned int ishape = fe_metric.system_to_component_index(idof).second;
3814  const unsigned int igrid_node = index_renumbering[ishape];
3815  mapping_support_points[istate][igrid_node] = val;
3816  }
3817 
3818  //get determinant of Jacobian
3819  OPERATOR::metric_operators<real, dim, 2*dim> metric_oper(nstate, fe_index_curr_cell, curr_grid_degree);
3821  n_quad_pts, n_grid_nodes,
3822  mapping_support_points,
3823  mapping_basis);
3824 
3825  //Get dofs indices to set local matrices in global.
3826  dofs_indices.resize(n_dofs_cell);
3827  cell->get_dof_indices (dofs_indices);
3828  //Compute local matrices and set them in the global system.
3830  Cartesian_element,
3831  do_inverse_mass_matrix,
3832  fe_index_curr_cell,
3833  curr_grid_degree,
3834  n_quad_pts,
3835  n_dofs_cell,
3836  dofs_indices,
3837  metric_oper,
3838  basis,
3839  reference_mass_matrix,
3840  reference_FR,
3841  reference_FR_aux,
3842  deriv_p);
3843  }//end of cell loop
3844 
3845  //Compress global matrices.
3846  if (do_inverse_mass_matrix) {
3847  global_inverse_mass_matrix.compress(dealii::VectorOperation::insert);
3848  if (use_auxiliary_eq){
3849  global_inverse_mass_matrix_auxiliary.compress(dealii::VectorOperation::insert);
3850  }
3851  if (use_energy){//for split form energy
3852  global_mass_matrix.compress(dealii::VectorOperation::insert);
3853  if (use_auxiliary_eq){
3854  global_mass_matrix_auxiliary.compress(dealii::VectorOperation::insert);
3855  }
3856  }
3857  } else {
3858  global_mass_matrix.compress(dealii::VectorOperation::insert);
3859  if (use_auxiliary_eq){
3860  global_mass_matrix_auxiliary.compress(dealii::VectorOperation::insert);
3861  }
3862  }
3863 }
3864 
3865 template<int dim, int nspecies, typename real, typename MeshType>
3867  const bool Cartesian_element,
3868  const bool do_inverse_mass_matrix,
3869  const unsigned int poly_degree,
3870  const unsigned int /*curr_grid_degree*/,
3871  const unsigned int n_quad_pts,
3872  const unsigned int n_dofs_cell,
3873  const std::vector<dealii::types::global_dof_index> dofs_indices,
3876  OPERATOR::local_mass<dim,2*dim> &reference_mass_matrix,
3880 {
3882  const FR_enum FR_Type = this->all_parameters->flux_reconstruction_type;
3883 
3885  const FR_Aux_enum FR_Type_Aux = this->all_parameters->flux_reconstruction_aux_type;
3886 
3887  dealii::FullMatrix<real> local_mass_matrix(n_dofs_cell);
3888  dealii::FullMatrix<real> local_mass_matrix_inv(n_dofs_cell);
3889  dealii::FullMatrix<real> local_mass_matrix_aux(n_dofs_cell);
3890  dealii::FullMatrix<real> local_mass_matrix_aux_inv(n_dofs_cell);
3891 
3892  for(int istate=0; istate<nstate; istate++){
3893  const unsigned int n_shape_fns = n_dofs_cell / nstate;
3894  dealii::FullMatrix<real> local_mass_matrix_state(n_shape_fns);
3895  dealii::FullMatrix<real> local_mass_matrix_inv_state(n_shape_fns);
3896  dealii::FullMatrix<real> local_mass_matrix_aux_state(n_shape_fns);
3897  dealii::FullMatrix<real> local_mass_matrix_aux_inv_state(n_shape_fns);
3898  // compute mass matrix and inverse the standard way
3899  if(this->all_parameters->use_weight_adjusted_mass == false){
3900  //check if Cartesian grid because we can factor out determinant of Jacobian
3901  if(Cartesian_element){
3902  local_mass_matrix_state.add(metric_oper.det_Jac_vol[0],
3903  reference_mass_matrix.tensor_product_state(
3904  1,
3905  reference_mass_matrix.oneD_vol_operator,
3906  reference_mass_matrix.oneD_vol_operator,
3907  reference_mass_matrix.oneD_vol_operator));
3908  if(use_auxiliary_eq){
3909  local_mass_matrix_aux_state.add(1.0, local_mass_matrix_state);
3910  }
3911  if(FR_Type != FR_enum::cDG){
3912  local_mass_matrix_state.add(metric_oper.det_Jac_vol[0],
3914  reference_mass_matrix.oneD_vol_operator,
3915  1,
3916  n_shape_fns));
3917  }
3918  if(use_auxiliary_eq){
3919  if(FR_Type_Aux != FR_Aux_enum::kDG){
3920  local_mass_matrix_aux_state.add(metric_oper.det_Jac_vol[0],
3921  reference_FR_aux.build_dim_Flux_Reconstruction_operator(
3922  reference_mass_matrix.oneD_vol_operator,
3923  1,
3924  n_shape_fns));
3925  }
3926  }
3927  if(do_inverse_mass_matrix){
3928  local_mass_matrix_inv_state.invert(local_mass_matrix_state);
3929  if(use_auxiliary_eq)
3930  local_mass_matrix_aux_inv_state.invert(local_mass_matrix_aux_state);
3931  }
3932  }
3933  //if not a linear grid, we have to build the dim matrices on the fly
3934  else{
3935  //quadrature weights
3936  const std::vector<real> &quad_weights = volume_quadrature_collection[poly_degree].get_weights();
3937  local_mass_matrix_state = reference_mass_matrix.build_dim_mass_matrix(
3938  1,
3939  n_shape_fns, n_quad_pts,
3940  basis,
3941  metric_oper.det_Jac_vol,
3942  quad_weights);
3943 
3944  if(use_auxiliary_eq) local_mass_matrix_aux_state.add(1.0, local_mass_matrix_state);
3945 
3946  if(FR_Type != FR_enum::cDG){
3947  dealii::FullMatrix<real> local_FR(n_shape_fns);
3948  local_FR = reference_FR.build_dim_Flux_Reconstruction_operator_directly(
3949  1,
3950  n_shape_fns,
3951  deriv_p.oneD_vol_operator,
3952  local_mass_matrix_state);
3953  local_mass_matrix_state.add(1.0, local_FR);
3954  }
3955  if(use_auxiliary_eq){
3956  if(FR_Type_Aux != FR_Aux_enum::kDG){
3957  dealii::FullMatrix<real> local_FR_aux(n_shape_fns);
3958  local_FR_aux = reference_FR_aux.build_dim_Flux_Reconstruction_operator_directly(
3959  1,
3960  n_shape_fns,
3961  deriv_p.oneD_vol_operator,
3962  local_mass_matrix_aux_state);
3963  local_mass_matrix_aux_state.add(1.0, local_FR_aux);
3964  }
3965  }
3966  }
3967  if(do_inverse_mass_matrix){
3968  local_mass_matrix_inv_state.invert(local_mass_matrix_state);
3969  if(use_auxiliary_eq)
3970  local_mass_matrix_aux_inv_state.invert(local_mass_matrix_aux_state);
3971  }
3972  }
3973  else{//do weight adjusted inverse
3974  //Weight-adjusted framework based off Cicchino, Alexander, and Sivakumaran Nadarajah. "Nonlinearly Stable Split Forms for the Weight-Adjusted Flux Reconstruction High-Order Method: Curvilinear Numerical Validation." AIAA SCITECH 2022 Forum. 2022 for FR. For a DG background please refer to Chan, Jesse, and Lucas C. Wilcox. "On discretely entropy stable weight-adjusted discontinuous Galerkin methods: curvilinear meshes." Journal of Computational Physics 378 (2019): 366-393. Section 4.1.
3975  //quadrature weights
3976  const std::vector<real> &quad_weights = volume_quadrature_collection[poly_degree].get_weights();
3977  std::vector<real> J_inv(n_quad_pts);
3978  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
3979  J_inv[iquad] = 1.0 / metric_oper.det_Jac_vol[iquad];
3980  }
3981  dealii::FullMatrix<real> local_weighted_mass_matrix(n_shape_fns);
3982  dealii::FullMatrix<real> local_weighted_mass_matrix_aux(n_shape_fns);
3983  local_weighted_mass_matrix = reference_mass_matrix.build_dim_mass_matrix(
3984  1,
3985  n_shape_fns, n_quad_pts,
3986  basis,
3987  J_inv,
3988  quad_weights);
3989  if(use_auxiliary_eq)
3990  local_weighted_mass_matrix_aux.add(1.0, local_weighted_mass_matrix);
3991 
3992  if(FR_Type != FR_enum::cDG){
3993  dealii::FullMatrix<real> local_FR(n_shape_fns);
3994  local_FR = reference_FR.build_dim_Flux_Reconstruction_operator_directly(
3995  1,
3996  n_shape_fns,
3997  deriv_p.oneD_vol_operator,
3998  local_weighted_mass_matrix);
3999  local_weighted_mass_matrix.add(1.0, local_FR);
4000  }
4001  //auxiliary weighted not correct and not yet implemented properly...
4002  if(use_auxiliary_eq){
4003  if(FR_Type_Aux != FR_Aux_enum::kDG){
4004  dealii::FullMatrix<real> local_FR_aux(n_shape_fns);
4005  local_FR_aux = reference_FR_aux.build_dim_Flux_Reconstruction_operator_directly(
4006  1,
4007  n_shape_fns,
4008  deriv_p.oneD_vol_operator,
4009  local_mass_matrix);
4010  local_weighted_mass_matrix_aux.add(1.0, local_FR_aux);
4011  }
4012  }
4013  dealii::FullMatrix<real> ref_mass_dim(n_shape_fns);
4014  ref_mass_dim = reference_mass_matrix.tensor_product_state(
4015  1,
4016  reference_mass_matrix.oneD_vol_operator,
4017  reference_mass_matrix.oneD_vol_operator,
4018  reference_mass_matrix.oneD_vol_operator);
4019  if(FR_Type != FR_enum::cDG){
4020  dealii::FullMatrix<real> local_FR(n_shape_fns);
4021  local_FR = reference_FR.build_dim_Flux_Reconstruction_operator(
4022  reference_mass_matrix.oneD_vol_operator,
4023  1,
4024  n_shape_fns);
4025  ref_mass_dim.add(1.0, local_FR);
4026  }
4027  dealii::FullMatrix<real> ref_mass_dim_inv(n_shape_fns);
4028  ref_mass_dim_inv.invert(ref_mass_dim);
4029  dealii::FullMatrix<real> temp(n_shape_fns);
4030  ref_mass_dim_inv.mmult(temp, local_weighted_mass_matrix);
4031  temp.mmult(local_mass_matrix_inv_state, ref_mass_dim_inv);
4032  local_mass_matrix_state.invert(local_mass_matrix_inv_state);
4033  if(use_auxiliary_eq){
4034  dealii::FullMatrix<real> temp2(n_shape_fns);
4035  ref_mass_dim_inv.mmult(temp2, local_weighted_mass_matrix_aux);
4036  temp2.mmult(local_mass_matrix_aux_inv_state, ref_mass_dim_inv);
4037  local_mass_matrix_aux_state.invert(local_mass_matrix_aux_inv_state);
4038  }
4039  }
4040  //write the ONE state, dim sized mass matrices using symmetry into nstate, dim sized mass matrices.
4041  for(unsigned int test_shape=0; test_shape<n_shape_fns; test_shape++){
4042 
4043  const unsigned int test_index = istate * n_shape_fns + test_shape;
4044 
4045  for(unsigned int trial_shape=test_shape; trial_shape<n_shape_fns; trial_shape++){
4046  const unsigned int trial_index = istate * n_shape_fns + trial_shape;
4047  local_mass_matrix[test_index][trial_index] = local_mass_matrix_state[test_shape][trial_shape];
4048  local_mass_matrix[trial_index][test_index] = local_mass_matrix_state[test_shape][trial_shape];
4049 
4050  local_mass_matrix_inv[test_index][trial_index] = local_mass_matrix_inv_state[test_shape][trial_shape];
4051  local_mass_matrix_inv[trial_index][test_index] = local_mass_matrix_inv_state[test_shape][trial_shape];
4052 
4053  if(use_auxiliary_eq){
4054  local_mass_matrix_aux[test_index][trial_index] = local_mass_matrix_aux_state[test_shape][trial_shape];
4055  local_mass_matrix_aux[trial_index][test_index] = local_mass_matrix_aux_state[test_shape][trial_shape];
4056 
4057  local_mass_matrix_aux_inv[test_index][trial_index] = local_mass_matrix_aux_inv_state[test_shape][trial_shape];
4058  local_mass_matrix_aux_inv[trial_index][test_index] = local_mass_matrix_aux_inv_state[test_shape][trial_shape];
4059  }
4060  }
4061  }
4062  }
4063 
4064  //set in global matrices
4065  if (do_inverse_mass_matrix) {
4066  //set the global inverse mass matrix
4067  global_inverse_mass_matrix.set(dofs_indices, local_mass_matrix_inv);
4068  //set the global inverse mass matrix for auxiliary equations
4069  if(use_auxiliary_eq){
4070  global_inverse_mass_matrix_auxiliary.set(dofs_indices, local_mass_matrix_aux_inv);
4071  }
4072  //If an energy test, we also need to store the mass matrix to compute energy/entropy and conservation.
4073  if (this->all_parameters->use_energy){//for split form energy
4074  global_mass_matrix.set(dofs_indices, local_mass_matrix);
4075  if(use_auxiliary_eq){
4076  global_mass_matrix_auxiliary.set(dofs_indices, local_mass_matrix_aux);
4077  }
4078  }
4079  } else {
4080  //only store global mass matrix
4081  global_mass_matrix.set(dofs_indices, local_mass_matrix);
4082  if(use_auxiliary_eq){
4083  global_mass_matrix_auxiliary.set(dofs_indices, local_mass_matrix_aux);
4084  }
4085  }
4086 }
4087 
4088 template<int dim, int nspecies, typename real, typename MeshType>
4090  const dealii::LinearAlgebra::distributed::Vector<double> &input_vector,
4091  dealii::LinearAlgebra::distributed::Vector<double> &output_vector,
4092  const bool use_auxiliary_eq)
4093 {
4096  const FR_enum FR_Type = this->all_parameters->flux_reconstruction_type;
4097  const double FR_user_specified_correction_parameter_value = this->all_parameters->FR_user_specified_correction_parameter_value;
4098  const FR_Aux_enum FR_Type_Aux = this->all_parameters->flux_reconstruction_aux_type;
4099 
4100  const unsigned int init_grid_degree = high_order_grid->fe_system.tensor_degree();
4101  OPERATOR::mapping_shape_functions<dim,2*dim> mapping_basis(1, init_grid_degree, init_grid_degree);
4102 
4103  OPERATOR::FR_mass_inv<dim,2*dim> mass_inv(1, max_degree, init_grid_degree, FR_Type, FR_user_specified_correction_parameter_value);
4104  OPERATOR::FR_mass_inv_aux<dim,2*dim> mass_inv_aux(1, max_degree, init_grid_degree, FR_Type_Aux);
4105 
4106  OPERATOR::vol_projection_operator_FR<dim,2*dim> projection_oper(1, max_degree, init_grid_degree, FR_Type, FR_user_specified_correction_parameter_value, true);
4107  OPERATOR::vol_projection_operator_FR_aux<dim,2*dim> projection_oper_aux(1, max_degree, init_grid_degree, FR_Type_Aux, true);
4108 
4110 
4111  const unsigned int grid_degree = this->high_order_grid->fe_system.tensor_degree();
4112  const dealii::FESystem<dim> &fe_metric = high_order_grid->fe_system;
4113  const unsigned int n_metric_dofs = high_order_grid->fe_system.dofs_per_cell;
4114  auto metric_cell = high_order_grid->dof_handler_grid.begin_active();
4115 
4116  auto first_cell = dof_handler.begin_active();
4117  const bool Cartesian_first_element = (first_cell->manifold_id() == dealii::numbers::flat_manifold_id) ? true : false;
4118 
4119  if(Cartesian_first_element){//then we can factor out det of Jac and rapidly simplify
4120  if(use_auxiliary_eq){
4121  mass_inv_aux.build_1D_volume_operator(oneD_fe_collection_1state[max_degree], oneD_quadrature_collection[max_degree]);
4122  }
4123  else{
4125  }
4126  }
4127  else{//we always use weight-adjusted for curvilinear based off the projection operator
4128  if(use_auxiliary_eq){
4129  projection_oper_aux.build_1D_volume_operator(oneD_fe_collection_1state[max_degree], oneD_quadrature_collection[max_degree]);
4130  }
4131  else{
4132  projection_oper.build_1D_volume_operator(oneD_fe_collection_1state[max_degree], oneD_quadrature_collection[max_degree]);
4133  }
4134  }
4135 
4136  dealii::Timer timer;
4138  timer.start();
4139  }
4140 
4141  for (auto soln_cell = dof_handler.begin_active(); soln_cell != dof_handler.end(); ++soln_cell, ++metric_cell) {
4142  if (!soln_cell->is_locally_owned()) continue;
4143 
4144  const unsigned int poly_degree = soln_cell->active_fe_index();
4145  const unsigned int n_dofs_cell = fe_collection[poly_degree].n_dofs_per_cell();
4146  std::vector<dealii::types::global_dof_index> current_dofs_indices;
4147  current_dofs_indices.resize(n_dofs_cell);
4148  soln_cell->get_dof_indices (current_dofs_indices);
4149 
4150  const bool Cartesian_element = (soln_cell->manifold_id() == dealii::numbers::flat_manifold_id);
4151 
4152  // if poly degree, the element manifold type, or grid degree changed for this cell, reinitialize the reference operator
4153  if((poly_degree != mass_inv.current_degree && Cartesian_element && !use_auxiliary_eq) ||
4154  (poly_degree != projection_oper.current_degree && (grid_degree > 1 || Cartesian_element) && !use_auxiliary_eq))
4155  {
4157  if(Cartesian_element){//then we can factor out det of Jac and rapidly simplify
4159  if(use_auxiliary_eq){
4160  mass_inv_aux.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree], oneD_quadrature_collection[poly_degree]);
4161  }
4162  }
4163  else{//we always use weight-adjusted for curvilinear based off the projection operator
4164  projection_oper.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree], oneD_quadrature_collection[poly_degree]);
4165  if(use_auxiliary_eq){
4166  projection_oper_aux.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree], oneD_quadrature_collection[poly_degree]);
4167  }
4168  }
4169  }
4170 
4171  // get mapping support points and determinant of Jacobian
4172  // setup metric cell
4173  std::vector<dealii::types::global_dof_index> metric_dofs_indices(n_metric_dofs);
4174  metric_cell->get_dof_indices (metric_dofs_indices);
4175  // get mapping_support points
4176  std::array<std::vector<real>,dim> mapping_support_points;
4177  for(int idim=0; idim<dim; idim++){
4178  mapping_support_points[idim].resize(n_metric_dofs/dim);
4179  }
4180  const std::vector<unsigned int > &index_renumbering = dealii::FETools::hierarchic_to_lexicographic_numbering<dim>(grid_degree);
4181  for (unsigned int idof = 0; idof< n_metric_dofs; ++idof) {
4182  const real val = (high_order_grid->volume_nodes[metric_dofs_indices[idof]]);
4183  const unsigned int istate = fe_metric.system_to_component_index(idof).first;
4184  const unsigned int ishape = fe_metric.system_to_component_index(idof).second;
4185  const unsigned int igrid_node = index_renumbering[ishape];
4186  mapping_support_points[istate][igrid_node] = val;
4187  }
4188  //get determinant of Jacobian
4189  const unsigned int n_quad_pts = volume_quadrature_collection[poly_degree].size();
4190  const unsigned int n_grid_nodes = n_metric_dofs / dim;
4191  //get determinant of Jacobian
4192  OPERATOR::metric_operators<real, dim, 2*dim> metric_oper(1, poly_degree, grid_degree);
4194  n_quad_pts, n_grid_nodes,
4195  mapping_support_points,
4196  mapping_basis);
4197  //solve mass inverse times input vector for each state independently
4198  for(int istate=0; istate<nstate; istate++){
4199  const unsigned int n_shape_fns = n_dofs_cell / nstate;
4200  std::vector<real> local_input_vector(n_shape_fns);
4201  std::vector<real> local_output_vector(n_shape_fns);
4202 
4203  for(unsigned int ishape=0; ishape<n_shape_fns; ishape++){
4204  const unsigned int idof = istate * n_shape_fns + ishape;
4205  local_input_vector[ishape] = input_vector[current_dofs_indices[idof]];
4206  }
4207 
4208  if(Cartesian_element){
4209  if(use_auxiliary_eq){
4210  mass_inv_aux.matrix_vector_mult_1D(local_input_vector, local_output_vector,
4211  mass_inv_aux.oneD_vol_operator,
4212  false, 1.0 / metric_oper.det_Jac_vol[0]);
4213  }
4214  else{
4215  mass_inv.matrix_vector_mult_1D(local_input_vector, local_output_vector,
4216  mass_inv.oneD_vol_operator,
4217  false, 1.0 / metric_oper.det_Jac_vol[0]);
4218  }
4219  }
4220  else{
4221  if(use_auxiliary_eq){
4222  std::vector<real> projection_of_input(n_quad_pts);
4223  projection_oper_aux.matrix_vector_mult_1D(local_input_vector, projection_of_input,
4224  projection_oper_aux.oneD_transpose_vol_operator);
4225  const std::vector<double> &quad_weights = volume_quadrature_collection[poly_degree].get_weights();
4226  std::vector<real> JxW_inv(n_quad_pts);
4227  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
4228  JxW_inv[iquad] = 1.0 / (quad_weights[iquad] * metric_oper.det_Jac_vol[iquad]);
4229  }
4230  projection_oper_aux.inner_product_1D(projection_of_input, JxW_inv,
4231  local_output_vector,
4232  projection_oper_aux.oneD_transpose_vol_operator);
4233  }
4234  else{
4235  std::vector<real> projection_of_input(n_quad_pts);
4236  projection_oper.matrix_vector_mult_1D(local_input_vector, projection_of_input,
4237  projection_oper.oneD_transpose_vol_operator);
4238  const std::vector<double> &quad_weights = volume_quadrature_collection[poly_degree].get_weights();
4239  std::vector<real> JxW_inv(n_quad_pts);
4240  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
4241  JxW_inv[iquad] = 1.0 / (quad_weights[iquad] * metric_oper.det_Jac_vol[iquad]);
4242  }
4243  projection_oper.inner_product_1D(projection_of_input, JxW_inv,
4244  local_output_vector,
4245  projection_oper.oneD_transpose_vol_operator);
4246  }
4247  }
4248 
4249  for(unsigned int ishape=0; ishape<n_shape_fns; ishape++){
4250  const unsigned int idof = istate * n_shape_fns + ishape;
4251  output_vector[current_dofs_indices[idof]] = local_output_vector[ishape];
4252  }
4253  }//end of state loop
4254  }//end of cell loop
4255 
4257  timer.stop();
4258  assemble_residual_time += timer.cpu_time();
4259  }
4260 }
4261 
4262 template<int dim, int nspecies, typename real, typename MeshType>
4264  const dealii::LinearAlgebra::distributed::Vector<double> &input_vector,
4265  dealii::LinearAlgebra::distributed::Vector<double> &output_vector,
4266  const bool use_auxiliary_eq,
4267  const bool use_unmodified_mass_matrix)
4268 {
4271  const FR_enum FR_cDG = FR_enum::cDG;
4272  // if using only the M norm, set c=0 through the choice of cDG, which results in K=0
4273  // and the un-modified mass matrix will be applied.
4274  const FR_enum FR_Type = (use_unmodified_mass_matrix) ? FR_cDG : this->all_parameters->flux_reconstruction_type;
4275  const double FR_user_specified_correction_parameter_value = this->all_parameters->FR_user_specified_correction_parameter_value;
4276  const FR_Aux_enum FR_Type_Aux = this->all_parameters->flux_reconstruction_aux_type;
4277 
4278  const unsigned int init_grid_degree = high_order_grid->fe_system.tensor_degree();
4279  OPERATOR::mapping_shape_functions<dim,2*dim> mapping_basis(1, max_degree, init_grid_degree);
4280 
4281  OPERATOR::FR_mass<dim,2*dim> mass(1, max_degree, init_grid_degree, FR_Type, FR_user_specified_correction_parameter_value);
4282  OPERATOR::FR_mass_aux<dim,2*dim> mass_aux(1, max_degree, init_grid_degree, FR_Type_Aux);
4283 
4284  OPERATOR::vol_projection_operator<dim,2*dim> projection_oper(1, max_degree, init_grid_degree);
4285 
4287 
4288  const unsigned int grid_degree = this->high_order_grid->fe_system.tensor_degree();
4289  const dealii::FESystem<dim> &fe_metric = high_order_grid->fe_system;
4290  const unsigned int n_metric_dofs = high_order_grid->fe_system.dofs_per_cell;
4291  auto metric_cell = high_order_grid->dof_handler_grid.begin_active();
4292 
4293  auto first_cell = dof_handler.begin_active();
4294  const bool Cartesian_first_element = (first_cell->manifold_id() == dealii::numbers::flat_manifold_id);
4295 
4296  if(use_auxiliary_eq){
4298  if(grid_degree>1 || !Cartesian_first_element){
4299  projection_oper.build_1D_volume_operator(oneD_fe_collection_1state[max_degree], oneD_quadrature_collection[max_degree]);
4300  }
4301  }
4302  else{
4304  if(grid_degree>1 || !Cartesian_first_element){
4305  projection_oper.build_1D_volume_operator(oneD_fe_collection_1state[max_degree], oneD_quadrature_collection[max_degree]);
4306  }
4307  }
4308 
4309  for (auto soln_cell = dof_handler.begin_active(); soln_cell != dof_handler.end(); ++soln_cell, ++metric_cell) {
4310  if (!soln_cell->is_locally_owned()) continue;
4311 
4312  const unsigned int poly_degree = soln_cell->active_fe_index();
4313  const unsigned int n_dofs_cell = fe_collection[poly_degree].n_dofs_per_cell();
4314  std::vector<dealii::types::global_dof_index> current_dofs_indices;
4315  current_dofs_indices.resize(n_dofs_cell);
4316  soln_cell->get_dof_indices (current_dofs_indices);
4317 
4318  const bool Cartesian_element = (soln_cell->manifold_id() == dealii::numbers::flat_manifold_id) ? true : false;
4319 
4320  //if poly degree changed for this cell, rinitialize
4321  if((poly_degree != mass.current_degree && (grid_degree == 1 || Cartesian_element) && !use_auxiliary_eq) ||
4322  (poly_degree != projection_oper.current_degree && (grid_degree > 1 || !Cartesian_element) && !use_auxiliary_eq)){
4324  if(use_auxiliary_eq){
4326  if(grid_degree>1 || !Cartesian_element){
4327  projection_oper.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree], oneD_quadrature_collection[poly_degree]);
4328  }
4329  }
4330  else{
4332  if(grid_degree>1 || !Cartesian_element){
4333  projection_oper.build_1D_volume_operator(oneD_fe_collection_1state[poly_degree], oneD_quadrature_collection[poly_degree]);
4334  }
4335  }
4336  }
4337 
4338  //get mapping support points and determinant of Jacobian
4339  //setup metric cell
4340  std::vector<dealii::types::global_dof_index> metric_dofs_indices(n_metric_dofs);
4341  metric_cell->get_dof_indices (metric_dofs_indices);
4342  // get mapping_support points
4343  std::array<std::vector<real>,dim> mapping_support_points;
4344  for(int idim=0; idim<dim; idim++){
4345  mapping_support_points[idim].resize(n_metric_dofs/dim);
4346  }
4347  const std::vector<unsigned int > &index_renumbering = dealii::FETools::hierarchic_to_lexicographic_numbering<dim>(grid_degree);
4348  for (unsigned int idof = 0; idof< n_metric_dofs; ++idof) {
4349  const real val = (high_order_grid->volume_nodes[metric_dofs_indices[idof]]);
4350  const unsigned int istate = fe_metric.system_to_component_index(idof).first;
4351  const unsigned int ishape = fe_metric.system_to_component_index(idof).second;
4352  const unsigned int igrid_node = index_renumbering[ishape];
4353  mapping_support_points[istate][igrid_node] = val;
4354  }
4355  //get determinant of Jacobian
4356  const unsigned int n_quad_pts = volume_quadrature_collection[poly_degree].size();
4357  const unsigned int n_grid_nodes = n_metric_dofs / dim;
4358  //get determinant of Jacobian
4359  OPERATOR::metric_operators<real, dim, 2*dim> metric_oper(1, poly_degree, grid_degree);
4361  n_quad_pts, n_grid_nodes,
4362  mapping_support_points,
4363  mapping_basis);
4364 
4365  //solve mass inverse times input vector for each state independently
4366  for(int istate=0; istate<nstate; istate++){
4367  const unsigned int n_shape_fns = n_dofs_cell / nstate;
4368  std::vector<real> local_input_vector(n_shape_fns);
4369  std::vector<real> local_output_vector(n_shape_fns);
4370 
4371  for(unsigned int ishape=0; ishape<n_shape_fns; ishape++){
4372  const unsigned int idof = istate * n_shape_fns + ishape;
4373  local_input_vector[ishape] = input_vector[current_dofs_indices[idof]];
4374  }
4375  if(Cartesian_element){
4376  if(use_auxiliary_eq){
4377  mass_aux.matrix_vector_mult_1D(local_input_vector, local_output_vector,
4378  mass_aux.oneD_vol_operator,
4379  false, metric_oper.det_Jac_vol[0]);
4380  }
4381  else{
4382  mass.matrix_vector_mult_1D(local_input_vector, local_output_vector,
4383  mass.oneD_vol_operator,
4384  false, metric_oper.det_Jac_vol[0]);
4385  }
4386  }
4387  else{
4388  const unsigned int n_dofs_1D = projection_oper.oneD_vol_operator.n();
4389  const unsigned int n_quad_pts_1D = projection_oper.oneD_vol_operator.m();
4390  if(use_auxiliary_eq){
4391  const std::vector<double> &quad_weights = volume_quadrature_collection[poly_degree].get_weights();
4392  dealii::FullMatrix<double> proj_mass(n_quad_pts_1D, n_dofs_1D);
4393  projection_oper.oneD_vol_operator.Tmmult(proj_mass, mass_aux.oneD_vol_operator);
4394 
4395  std::vector<real> projection_of_input(n_quad_pts);
4396  projection_oper.matrix_vector_mult_1D(local_input_vector, projection_of_input,
4397  proj_mass);
4398  std::vector<real> JxW(n_quad_pts);
4399  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
4400  JxW[iquad] = (metric_oper.det_Jac_vol[iquad] / quad_weights[iquad]);
4401  }
4402  projection_oper.inner_product_1D(projection_of_input, JxW,
4403  local_output_vector,
4404  proj_mass);
4405  }
4406  else{
4407  const std::vector<double> &quad_weights = volume_quadrature_collection[poly_degree].get_weights();
4408 
4409  std::vector<real> proj_mass(n_shape_fns);
4410  mass.matrix_vector_mult_1D(local_input_vector, proj_mass,
4411  mass.oneD_vol_operator);
4412  std::vector<real> projection_of_input(n_quad_pts);
4413  std::vector<real> ones(n_shape_fns, 1.0);
4414  projection_oper.inner_product_1D(proj_mass, ones, projection_of_input,
4415  projection_oper.oneD_vol_operator);
4416  std::vector<real> JxW(n_quad_pts);
4417  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
4418  JxW[iquad] = (metric_oper.det_Jac_vol[iquad] / quad_weights[iquad])
4419  * projection_of_input[iquad];
4420  }
4421  std::vector<real> temp(n_shape_fns);
4422  projection_oper.matrix_vector_mult_1D(JxW,
4423  temp,
4424  projection_oper.oneD_vol_operator);
4425  mass.matrix_vector_mult_1D(temp,
4426  local_output_vector,
4427  mass.oneD_vol_operator);
4428 
4429  }
4430  }
4431 
4432  for(unsigned int ishape=0; ishape<n_shape_fns; ishape++){
4433  const unsigned int idof = istate * n_shape_fns + ishape;
4434  output_vector[current_dofs_indices[idof]] = local_output_vector[ishape];
4435  }
4436  }//end of state loop
4437  }//end of cell loop
4438 }
4439 
4440 template<int dim, int nspecies, typename real, typename MeshType>
4442 {
4443  system_matrix.add(scale, global_mass_matrix);
4444 }
4445 template<int dim, int nspecies, typename real, typename MeshType>
4447 {
4449 }
4450 template<int dim, int nspecies, typename real, typename MeshType>
4452 {
4455  std::vector<dealii::types::global_dof_index> dofs_indices;
4456  for (auto cell = dof_handler.begin_active(); cell!=dof_handler.end(); ++cell) {
4457 
4458  if (!cell->is_locally_owned()) continue;
4459 
4460  const unsigned int fe_index_curr_cell = cell->active_fe_index();
4461 
4462  // Current reference element related to this physical cell
4463  const dealii::FESystem<dim,dim> &current_fe_ref = fe_collection[fe_index_curr_cell];
4464  const unsigned int n_dofs_cell = current_fe_ref.n_dofs_per_cell();
4465 
4466  dofs_indices.resize(n_dofs_cell);
4467  cell->get_dof_indices (dofs_indices);
4468 
4469  const double max_dt = max_dt_cell[cell->active_cell_index()];
4470 
4471  for (unsigned int itest=0; itest<n_dofs_cell; ++itest) {
4472  const unsigned int istate_test = current_fe_ref.system_to_component_index(itest).first;
4473  for (unsigned int itrial=itest; itrial<n_dofs_cell; ++itrial) {
4474  const unsigned int istate_trial = current_fe_ref.system_to_component_index(itrial).first;
4475 
4476  if(istate_test==istate_trial) {
4477  const unsigned int row = dofs_indices[itest];
4478  const unsigned int col = dofs_indices[itrial];
4479  const double value = global_mass_matrix.el(row, col);
4480  const double new_val = value / (dt_scale * max_dt);
4481  AssertIsFinite(new_val);
4482  time_scaled_global_mass_matrix.set(row, col, new_val);
4483  if (row!=col) time_scaled_global_mass_matrix.set(col, row, new_val);
4484  }
4485  }
4486  }
4487  }
4488  time_scaled_global_mass_matrix.compress(dealii::VectorOperation::insert);
4489 }
4490 
4491 template<int dim, int nspecies, typename real> // To be replaced with operators->projection_operator
4492 std::vector< real > project_function(
4493  const std::vector< real > &function_coeff,
4494  const dealii::FESystem<dim,dim> &fe_input,
4495  const dealii::FESystem<dim,dim> &fe_output,
4496  const dealii::QGauss<dim> &projection_quadrature)
4497 {
4498  const unsigned int nstate = fe_input.n_components();
4499  const unsigned int n_vector_dofs_in = fe_input.dofs_per_cell;
4500  const unsigned int n_vector_dofs_out = fe_output.dofs_per_cell;
4501  const unsigned int n_dofs_in = n_vector_dofs_in / nstate;
4502  const unsigned int n_dofs_out = n_vector_dofs_out / nstate;
4503 
4504  assert(n_vector_dofs_in == function_coeff.size());
4505  assert(nstate == fe_output.n_components());
4506 
4507  const unsigned int n_quad_pts = projection_quadrature.size();
4508  const std::vector<dealii::Point<dim,double>> &unit_quad_pts = projection_quadrature.get_points();
4509 
4510  std::vector< real > function_coeff_out(n_vector_dofs_out); // output function coefficients.
4511  for (unsigned istate = 0; istate < nstate; ++istate) {
4512 
4513  std::vector< real > function_at_quad(n_quad_pts);
4514 
4515  // Output interpolation_operator is V^T in the notes.
4516  dealii::FullMatrix<double> interpolation_operator(n_dofs_out,n_quad_pts);
4517 
4518  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
4519  function_at_quad[iquad] = 0.0;
4520  for (unsigned int idof=0; idof<n_dofs_in; ++idof) {
4521  const unsigned int idof_vector = fe_input.component_to_system_index(istate,idof);
4522  function_at_quad[iquad] += function_coeff[idof_vector] * fe_input.shape_value_component(idof_vector,unit_quad_pts[iquad],istate);
4523  }
4524  function_at_quad[iquad] *= projection_quadrature.weight(iquad);
4525 
4526  for (unsigned int idof=0; idof<n_dofs_out; ++idof) {
4527  const unsigned int idof_vector = fe_output.component_to_system_index(istate,idof);
4528  interpolation_operator[idof][iquad] = fe_output.shape_value_component(idof_vector,unit_quad_pts[iquad],istate);
4529  }
4530  }
4531 
4532  std::vector< real > rhs(n_dofs_out);
4533  for (unsigned int idof=0; idof<n_dofs_out; ++idof) {
4534  rhs[idof] = 0.0;
4535  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
4536  rhs[idof] += interpolation_operator[idof][iquad] * function_at_quad[iquad];
4537  }
4538  }
4539 
4540  dealii::FullMatrix<double> mass(n_dofs_out, n_dofs_out);
4541  for(unsigned int row=0; row<n_dofs_out; ++row) {
4542  for(unsigned int col=0; col<n_dofs_out; ++col) {
4543  mass[row][col] = 0;
4544  }
4545  }
4546  for(unsigned int row=0; row<n_dofs_out; ++row) {
4547  for(unsigned int col=0; col<n_dofs_out; ++col) {
4548  for(unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
4549  mass[row][col] += interpolation_operator[row][iquad] * interpolation_operator[col][iquad] * projection_quadrature.weight(iquad);
4550  }
4551  }
4552  }
4553  dealii::FullMatrix<double> inverse_mass(n_dofs_out, n_dofs_out);
4554  inverse_mass.invert(mass);
4555 
4556  for(unsigned int row=0; row<n_dofs_out; ++row) {
4557  const unsigned int idof_vector = fe_output.component_to_system_index(istate,row);
4558  function_coeff_out[idof_vector] = 0.0;
4559  for(unsigned int col=0; col<n_dofs_out; ++col) {
4560  function_coeff_out[idof_vector] += inverse_mass[row][col] * rhs[col];
4561  }
4562  }
4563  }
4564 
4565  return function_coeff_out;
4566 
4567 }
4568 
4569 template <int dim, int nspecies, typename real,typename MeshType>
4570 template <typename real2>
4572  const dealii::Quadrature<dim> &volume_quadrature,
4573  const std::vector< real2 > &soln_coeff_high,
4574  const dealii::FiniteElement<dim,dim> &fe_high,
4575  const std::vector<real2> &jac_det)
4576 {
4577  const unsigned int degree = fe_high.tensor_degree();
4578 
4579  if (degree == 0) return 0;
4580 
4581  const unsigned int nstate = fe_high.components;
4582  const unsigned int n_dofs_high = fe_high.dofs_per_cell;
4583 
4584  // Lower degree basis.
4585  const unsigned int lower_degree = degree-1;
4586  const dealii::FE_DGQLegendre<dim> fe_dgq_lower(lower_degree);
4587  const dealii::FESystem<dim,dim> fe_lower(fe_dgq_lower, nstate);
4588 
4589  // Projection quadrature.
4590  const dealii::QGauss<dim> projection_quadrature(degree+5);
4591  std::vector< real2 > soln_coeff_lower = project_function<dim,nspecies,real2>( soln_coeff_high, fe_high, fe_lower, projection_quadrature);
4592 
4593  // Quadrature used for solution difference.
4594  const std::vector<dealii::Point<dim,double>> &unit_quad_pts = volume_quadrature.get_points();
4595 
4596  const unsigned int n_quad_pts = volume_quadrature.size();
4597  const unsigned int n_dofs_lower = fe_lower.dofs_per_cell;
4598 
4599  real2 element_volume = 0.0;
4600  real2 error = 0.0;
4601  real2 soln_norm = 0.0;
4602  std::vector<real2> soln_high(nstate);
4603  std::vector<real2> soln_lower(nstate);
4604  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
4605  for (unsigned int s=0; s<nstate; ++s) {
4606  soln_high[s] = 0.0;
4607  soln_lower[s] = 0.0;
4608  }
4609  // Interpolate solution
4610  for (unsigned int idof=0; idof<n_dofs_high; ++idof) {
4611  const unsigned int istate = fe_high.system_to_component_index(idof).first;
4612  soln_high[istate] += soln_coeff_high[idof] * fe_high.shape_value_component(idof,unit_quad_pts[iquad],istate);
4613  }
4614  // Interpolate low order solution
4615  for (unsigned int idof=0; idof<n_dofs_lower; ++idof) {
4616  const unsigned int istate = fe_lower.system_to_component_index(idof).first;
4617  soln_lower[istate] += soln_coeff_lower[idof] * fe_lower.shape_value_component(idof,unit_quad_pts[iquad],istate);
4618  }
4619  // Quadrature
4620  const real2 JxW = jac_det[iquad] * volume_quadrature.weight(iquad);
4621  element_volume += JxW;
4622  // Only integrate over the first state variable.
4623  // Persson and Peraire only did density.
4624  for (unsigned int s=0; s<1/*nstate*/; ++s)
4625  {
4626  error += (soln_high[s] - soln_lower[s]) * (soln_high[s] - soln_lower[s]) * JxW;
4627  soln_norm += soln_high[s] * soln_high[s] * JxW;
4628  }
4629  }
4630 
4631  if (soln_norm < 1e-15) return 0;
4632 
4633  const real2 S_e = sqrt(error / soln_norm);
4634  const real2 s_e = log10(S_e);
4635 
4637  const double s_0 = -0.00 - 4.00*log10(degree);
4639  const double low = s_0 - kappa;
4640  const double upp = s_0 + kappa;
4641 
4642  const real2 diameter = pow(element_volume, 1.0/dim);
4643  const real2 eps_0 = mu_scale * diameter / (double)degree;
4644 
4645  if ( s_e < low) return 0.0;
4646 
4647  if ( s_e > upp)
4648  {
4649  return eps_0;
4650  }
4651 
4652  const double PI = 4*atan(1);
4653  real2 eps = 1.0 + sin(PI * (s_e - s_0) * 0.5 / kappa);
4654  eps *= eps_0 * 0.5;
4655  return eps;
4656 }
4657 
4658 template <int dim, int nspecies, typename real, typename MeshType>
4659 void DGBase<dim,nspecies,real,MeshType>::set_current_time(const real current_time_input)
4660 {
4661  this->current_time = current_time_input;
4662 }
4663 
4664 #if PHILIP_DIM!=1
4666 #endif
4667 
4670 
4671 template double DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::Triangulation<PHILIP_DIM>>::discontinuity_sensor<double>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< double > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<double> &jac_det);
4672 template FadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::Triangulation<PHILIP_DIM>>::discontinuity_sensor<FadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< FadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<FadType> &jac_det);
4673 template RadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::Triangulation<PHILIP_DIM>>::discontinuity_sensor<RadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< RadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<RadType> &jac_det);
4674 template FadFadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::Triangulation<PHILIP_DIM>>::discontinuity_sensor<FadFadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< FadFadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<FadFadType> &jac_det);
4675 template RadFadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::Triangulation<PHILIP_DIM>>::discontinuity_sensor<RadFadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< RadFadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<RadFadType> &jac_det);
4676 
4677 
4678 template double DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::distributed::Triangulation<PHILIP_DIM>>::discontinuity_sensor<double>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< double > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<double> &jac_det);
4679 template FadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::distributed::Triangulation<PHILIP_DIM>>::discontinuity_sensor<FadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< FadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<FadType> &jac_det);
4680 template RadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::distributed::Triangulation<PHILIP_DIM>>::discontinuity_sensor<RadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< RadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<RadType> &jac_det);
4681 template FadFadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::distributed::Triangulation<PHILIP_DIM>>::discontinuity_sensor<FadFadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< FadFadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<FadFadType> &jac_det);
4682 template RadFadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::distributed::Triangulation<PHILIP_DIM>>::discontinuity_sensor<RadFadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< RadFadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<RadFadType> &jac_det);
4683 
4684 
4685 template double DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::shared::Triangulation<PHILIP_DIM>>::discontinuity_sensor<double>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< double > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<double> &jac_det);
4686 template FadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::shared::Triangulation<PHILIP_DIM>>::discontinuity_sensor<FadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< FadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<FadType> &jac_det);
4687 template RadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::shared::Triangulation<PHILIP_DIM>>::discontinuity_sensor<RadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< RadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<RadType> &jac_det);
4688 template FadFadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::shared::Triangulation<PHILIP_DIM>>::discontinuity_sensor<FadFadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< FadFadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<FadFadType> &jac_det);
4689 template RadFadType DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::shared::Triangulation<PHILIP_DIM>>::discontinuity_sensor<RadFadType>(const dealii::Quadrature<PHILIP_DIM> &volume_quadrature, const std::vector< RadFadType > &soln_coeff_high, const dealii::FiniteElement<PHILIP_DIM,PHILIP_DIM> &fe_high, const std::vector<RadFadType> &jac_det);
4690 
4691 
4692 
4693 template void
4694 DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::Triangulation<PHILIP_DIM>>::assemble_cell_residual_and_ad_derivatives<codi_JacobianComputationType> (
4695  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_cell,
4696  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_metric_cell,
4697  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
4698  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume,
4699  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_int,
4700  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_ext,
4701  dealii::hp::FESubfaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_subface,
4702  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume_lagrange,
4708  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_int,
4709  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_ext,
4711  const bool compute_auxiliary_right_hand_side,//flag on whether computing the Auxiliary variable's equations' residuals
4712  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
4713  std::array<dealii::LinearAlgebra::distributed::Vector<double>,PHILIP_DIM> &rhs_aux);
4714 
4715 template void
4716 DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::Triangulation<PHILIP_DIM>>::assemble_cell_residual_and_ad_derivatives<codi_HessianComputationType> (
4717  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_cell,
4718  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_metric_cell,
4719  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
4720  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume,
4721  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_int,
4722  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_ext,
4723  dealii::hp::FESubfaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_subface,
4724  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume_lagrange,
4730  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_int,
4731  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_ext,
4733  const bool compute_auxiliary_right_hand_side,//flag on whether computing the Auxiliary variable's equations' residuals
4734  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
4735  std::array<dealii::LinearAlgebra::distributed::Vector<double>,PHILIP_DIM> &rhs_aux);
4736 template void
4737 DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::distributed::Triangulation<PHILIP_DIM>>::assemble_cell_residual_and_ad_derivatives<codi_JacobianComputationType> (
4738  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_cell,
4739  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_metric_cell,
4740  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
4741  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume,
4742  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_int,
4743  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_ext,
4744  dealii::hp::FESubfaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_subface,
4745  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume_lagrange,
4751  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_int,
4752  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_ext,
4754  const bool compute_auxiliary_right_hand_side,//flag on whether computing the Auxiliary variable's equations' residuals
4755  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
4756  std::array<dealii::LinearAlgebra::distributed::Vector<double>,PHILIP_DIM> &rhs_aux);
4757 
4758 template void
4759 DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::distributed::Triangulation<PHILIP_DIM>>::assemble_cell_residual_and_ad_derivatives<codi_HessianComputationType> (
4760  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_cell,
4761  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_metric_cell,
4762  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
4763  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume,
4764  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_int,
4765  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_ext,
4766  dealii::hp::FESubfaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_subface,
4767  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume_lagrange,
4773  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_int,
4774  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_ext,
4776  const bool compute_auxiliary_right_hand_side,//flag on whether computing the Auxiliary variable's equations' residuals
4777  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
4778  std::array<dealii::LinearAlgebra::distributed::Vector<double>,PHILIP_DIM> &rhs_aux);
4779 
4780 
4781 
4782 template void
4783 DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::shared::Triangulation<PHILIP_DIM>>::assemble_cell_residual_and_ad_derivatives<codi_JacobianComputationType> (
4784  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_cell,
4785  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_metric_cell,
4786  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
4787  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume,
4788  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_int,
4789  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_ext,
4790  dealii::hp::FESubfaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_subface,
4791  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume_lagrange,
4797  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_int,
4798  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_ext,
4800  const bool compute_auxiliary_right_hand_side,//flag on whether computing the Auxiliary variable's equations' residuals
4801  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
4802  std::array<dealii::LinearAlgebra::distributed::Vector<double>,PHILIP_DIM> &rhs_aux);
4803 
4804 template void
4805 DGBase<PHILIP_DIM,PHILIP_SPECIES,double,dealii::parallel::shared::Triangulation<PHILIP_DIM>>::assemble_cell_residual_and_ad_derivatives<codi_HessianComputationType> (
4806  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_cell,
4807  const dealii::TriaActiveIterator<dealii::DoFCellAccessor<PHILIP_DIM, PHILIP_DIM, false>> &current_metric_cell,
4808  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
4809  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume,
4810  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_int,
4811  dealii::hp::FEFaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_face_ext,
4812  dealii::hp::FESubfaceValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_subface,
4813  dealii::hp::FEValues<PHILIP_DIM,PHILIP_DIM> &fe_values_collection_volume_lagrange,
4819  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_int,
4820  OPERATOR::vol_projection_operator<PHILIP_DIM,2*PHILIP_DIM> &soln_basis_projection_oper_ext,
4822  const bool compute_auxiliary_right_hand_side,//flag on whether computing the Auxiliary variable's equations' residuals
4823  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
4824  std::array<dealii::LinearAlgebra::distributed::Vector<double>,PHILIP_DIM> &rhs_aux);
4825 
4826 } // PHiLiP namespace
bool do_compute_Reynolds_stress
Flag for computing time-averaged Reynolds stresses.
void time_scale_solution_update(dealii::LinearAlgebra::distributed::Vector< double > &solution_update, const real CFL) const
Scales a solution update with the appropriate maximum time step.
Definition: dg_base.cpp:264
void reinit_operators_for_cell_residual_loop(const unsigned int poly_degree_int, const unsigned int poly_degree_ext, const unsigned int grid_degree, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis_int, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis_ext, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis_int, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis_ext, OPERATOR::local_basis_stiffness< dim, 2 *dim > &flux_basis_stiffness, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_int, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_ext, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis)
Builds needed operators for cell residual loop.
Definition: dg_base.cpp:2553
std::enable_if<!std::is_same< adtype, double >::value, void >::type assemble_face_codi_taped_derivatives_ad(typename dealii::DoFHandler< dim >::active_cell_iterator cell, typename dealii::DoFHandler< dim >::active_cell_iterator neighbor_cell, const dealii::types::global_dof_index current_cell_index, const dealii::types::global_dof_index neighbor_cell_index, const unsigned int iface, const unsigned int neighbor_iface, const real penalty, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_int, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_ext, dealii::hp::FESubfaceValues< dim, dim > &fe_values_collection_subface, const dealii::FESystem< dim, dim > &fe_int, const dealii::FESystem< dim, dim > &fe_ext, const std::vector< dealii::types::global_dof_index > &soln_dofs_indices_int, const std::vector< dealii::types::global_dof_index > &soln_dofs_indices_ext, const std::vector< dealii::types::global_dof_index > &metric_dofs_indices_int, const std::vector< dealii::types::global_dof_index > &metric_dofs_indices_ext, const unsigned int poly_degree_int, const unsigned int poly_degree_ext, const unsigned int grid_degree_int, const unsigned int grid_degree_ext, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis_int, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis_ext, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis_int, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis_ext, OPERATOR::local_basis_stiffness< dim, 2 *dim > &flux_basis_stiffness, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_int, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_ext, OPERATOR::metric_operators< adtype, dim, 2 *dim > &metric_oper_int, OPERATOR::metric_operators< adtype, dim, 2 *dim > &metric_oper_ext, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis, std::array< std::vector< adtype >, dim > &mapping_support_points, std::vector< real > &local_rhs_int_cell, std::vector< real > &local_rhs_ext_cell, dealii::Tensor< 1, dim, std::vector< real >> &current_cell_rhs_aux, dealii::LinearAlgebra::distributed::Vector< double > &rhs, std::array< dealii::LinearAlgebra::distributed::Vector< double >, dim > &rhs_aux, const bool compute_auxiliary_right_hand_side, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R, const bool is_a_subface=false, const unsigned int neighbor_i_subface=0)
Computes face term of the cell and performs automatic differentiation.
Definition: dg_base.cpp:1607
PartialDifferentialEquation pde_type
Store the PDE type to be solved.
void add_time_scaled_mass_matrices()
Add time scaled mass matrices to the system.
Definition: dg_base.cpp:4446
const dealii::hp::FECollection< dim > fe_collection_lagrange
Lagrange basis used in strong form.
Definition: dg_base.hpp:1137
The metric independent inverse of the FR mass matrix .
Definition: operators.h:815
dealii::SparsityPattern get_d2RdXdX_sparsity_pattern()
Evaluate SparsityPattern of the residual Hessian dual.d2RdXdX.
void allocate_artificial_dissipation()
Allocates variables of artificial dissipation.
Definition: dg_base.cpp:3606
Sacado::Fad::DFad< FadType > FadFadType
Sacado AD type that allows 2nd derivatives.
Definition: ADTypes.hpp:12
void set_dual(const dealii::LinearAlgebra::distributed::Vector< real > &dual_input)
Sets the stored dual variables used to compute the dual dotted with the residual Hessians.
Definition: dg_base.cpp:2363
void add_mass_matrices(const real scale)
Add mass matrices to the system scaled by a factor (likely time-step)
Definition: dg_base.cpp:4441
double max_artificial_dissipation_coeff
Stores maximum artificial dissipation while assembling the residual.
Definition: dg_base.hpp:1295
void apply_inverse_global_mass_matrix(const dealii::LinearAlgebra::distributed::Vector< double > &input_vector, dealii::LinearAlgebra::distributed::Vector< double > &output_vector, const bool use_auxiliary_eq=false)
Applies the inverse of the local metric dependent mass matrices when the global is not stored...
Definition: dg_base.cpp:4089
dealii::Point< dim > coordinates_of_highest_refined_cell(bool check_for_p_refined_cell=false)
Returns the coordinates of the most refined cell.
Definition: dg_base.cpp:328
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:2083
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:1150
virtual void assemble_boundary_term_and_build_operators_ad(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const std::vector< double > &soln_coeffs, const dealii::Tensor< 1, dim, std::vector< double >> &aux_soln_coeffs, const std::vector< double > &metric_coeffs, const std::vector< real > &local_dual, const unsigned int face_number, const unsigned int boundary_id, const unsigned int poly_degree, const unsigned int grid_degree, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_int, OPERATOR::metric_operators< double, dim, 2 *dim > &metric_oper, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis, std::array< std::vector< double >, dim > &mapping_support_points, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_int, const dealii::FESystem< dim, dim > &fe_soln, const real penalty, std::vector< double > &rhs, dealii::Tensor< 1, dim, std::vector< double >> &local_auxiliary_RHS, const bool compute_auxiliary_right_hand_side, double &dual_dot_residual)=0
Builds the necessary operators/fe values and assembles boundary residual. For double type...
dealii::LinearAlgebra::distributed::Vector< double > artificial_dissipation_c0
Artificial dissipation coefficients.
Definition: dg_base.hpp:1196
FlowSolverParam flow_solver_param
Contains the parameters for simulation cases (flow solver test)
Sacado::Fad::DFad< double > FadType
Sacado AD type for first derivatives.
Definition: ADTypes.hpp:11
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:1837
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:1217
dealii::TrilinosWrappers::SparseMatrix dRdXv
Definition: dg_base.hpp:356
bool output_face_results_vtk
Flag for outputting the surface solution vtk files.
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:1520
const dealii::FE_Q< dim > fe_q_artificial_dissipation
Continuous distribution of artificial dissipation.
Definition: dg_base.hpp:1190
double assemble_residual_time
Computational time for assembling residual.
Definition: dg_base.hpp:1184
dealii::ConditionalOStream pcout
Parallel std::cout that only outputs on mpi_rank==0.
Definition: dg_base.hpp:1259
codi_JacobianComputationType RadType
CoDiPaco reverse-AD type for first derivatives.
Definition: ADTypes.hpp:27
dealii::IndexSet ghost_dofs
Locally relevant ghost degrees of freedom.
Definition: dg_base.hpp:399
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:827
The metric independent FR mass matrix for auxiliary equation .
Definition: operators.h:893
void build_1D_shape_functions_at_volume_flux_nodes(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Constructs the volume and volume gradient operator.
Definition: operators.cpp:2325
bool freeze_artificial_dissipation
Flag to freeze artificial dissipation.
Definition: dg_base.hpp:1293
virtual void set_store_surf_flux_nodes()=0
Set store_surf_flux_nodes flag.
virtual void allocate_second_derivatives()
Allocates the second derivatives.
Definition: dg_base.cpp:3625
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:402
void output_face_results_vtk(const unsigned int cycle, const double current_time=0.0, const bool output_time_averaged_solution=false, const bool output_fluctuating_quantities=false)
Output Euler face solution.
const dealii::UpdateFlags neighbor_face_update_flags
Update flags needed at neighbor&#39; face points.
Definition: dg_base.hpp:1219
bool use_energy
Flag to use an energy monotonicity test.
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:1440
void build_determinant_volume_metric_Jacobian(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 > &mapping_basis)
Builds just the determinant of the volume metric determinant.
Definition: operators.cpp:2423
Projection operator corresponding to basis functions onto -norm for auxiliary equation.
Definition: operators.h:784
dealii::FullMatrix< double > build_dim_Flux_Reconstruction_operator(const dealii::FullMatrix< double > &local_Mass_Matrix, const int nstate, const unsigned int n_dofs)
Computes the dim sized flux reconstruction operator with simplified tensor product form...
Definition: operators.cpp:1758
dealii::hp::QCollection< dim-1 > face_quadrature_collection
Quadrature used to evaluate face integrals.
Definition: dg_base.hpp:1133
virtual void update_model_variables()=0
Update the necessary variables declared in src/physics/model.h.
dealii::TrilinosWrappers::SparseMatrix global_mass_matrix_auxiliary
Global auxiliary mass matrix.
Definition: dg_base.hpp:336
dealii::LinearAlgebra::distributed::Vector< double > volume_nodes_d2R
Definition: dg_base.hpp:443
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:733
Files for the baseline physics.
Definition: ADTypes.hpp:10
dealii::DoFHandler< dim > dof_handler_artificial_dissipation
Degrees of freedom handler for C0 artificial dissipation.
Definition: dg_base.hpp:1193
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:2313
dealii::TrilinosWrappers::SparseMatrix system_matrix_transpose
Definition: dg_base.hpp:347
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:1354
void allocate_auxiliary_equation()
Allocates the auxiliary equations&#39; variables and right hand side (primarily for Strong form diffusive...
Definition: dg_base.cpp:3466
bool use_weak_form
Flag to use weak or strong form of DG.
dealii::TrilinosWrappers::SparseMatrix global_mass_matrix
Global mass matrix.
Definition: dg_base.hpp:329
double time_to_start_averaging
Flag for starting time-averaged solution.
double get_residual_linfnorm() const
Returns the Linf-norm of the right_hand_side vector.
Definition: dg_base.cpp:2917
dealii::QGauss< 0 > oneD_face_quadrature
1D surface quadrature is always one single point for all poly degrees.
Definition: dg_base.hpp:1157
void reinit()
Reinitializes the DG object after a change of triangulation.
Definition: dg_base.cpp:112
std::enable_if<!std::is_same< adtype, double >::value, void >::type assemble_boundary_codi_taped_derivatives_ad(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const unsigned int iface, const unsigned int boundary_id, const real penalty, const std::vector< dealii::types::global_dof_index > &soln_dofs_indices, const std::vector< dealii::types::global_dof_index > &metric_dof_indices, const unsigned int poly_degree, const unsigned int grid_degree, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_int, OPERATOR::metric_operators< adtype, dim, 2 *dim > &metric_oper, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis, std::array< std::vector< adtype >, dim > &mapping_support_points, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_int, const dealii::FESystem< dim, dim > &fe_soln, std::vector< real > &local_rhs_cell, dealii::Tensor< 1, dim, std::vector< real >> &local_auxiliary_RHS, const bool compute_auxiliary_right_hand_side, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Computes boundary term of the cell if the cell has a face at the boundary and performs automatic diff...
Definition: dg_base.cpp:1246
std::shared_ptr< HighOrderGrid< dim, real, MeshType > > high_order_grid
High order grid that will provide the MappingFEField.
Definition: dg_base.hpp:1178
double get_residual_l2norm() const
Returns the L2-norm of the right_hand_side vector.
Definition: dg_base.cpp:2965
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:554
const int nstate
Number of state variables.
Definition: dg_base.hpp:96
dealii::hp::QCollection< dim > volume_quadrature_collection
Finite Element Collection to represent the high-order grid.
Definition: dg_base.hpp:1131
Flux_Reconstruction
Type of correction in Flux Reconstruction.
Flux_Reconstruction_Aux flux_reconstruction_aux_type
Store flux reconstruction type for the auxiliary variables.
-th order modal derivative of basis fuctions, ie/
Definition: operators.h:544
void evaluate_local_metric_dependent_mass_matrix_and_set_in_global_mass_matrix(const bool Cartesian_element, const bool do_inverse_mass_matrix, const unsigned int poly_degree, const unsigned int curr_grid_degree, const unsigned int n_quad_pts, const unsigned int n_dofs_cell, const std::vector< dealii::types::global_dof_index > dofs_indices, OPERATOR::metric_operators< real, dim, 2 *dim > &metric_oper, OPERATOR::basis_functions< dim, 2 *dim > &basis, OPERATOR::local_mass< dim, 2 *dim > &reference_mass_matrix, OPERATOR::local_Flux_Reconstruction_operator< dim, 2 *dim > &reference_FR, OPERATOR::local_Flux_Reconstruction_operator_aux< dim, 2 *dim > &reference_FR_aux, OPERATOR::derivative_p< dim, 2 *dim > &deriv_p)
Evaluates the metric dependent local mass matrices and inverses, then sets them in the global matrice...
Definition: dg_base.cpp:3866
virtual void assemble_auxiliary_residual(const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)=0
Asembles the auxiliary equations&#39; residuals and solves. Note: This function cannot be automatically d...
dealii::TrilinosWrappers::SparseMatrix d2RdWdX
Definition: dg_base.hpp:368
virtual void allocate_dual_vector(const bool compute_d2R)=0
Allocate the dual vector for optimization.
Main parameter class that contains the various other sub-parameter classes.
std::unique_ptr< Epetra_RowMatrixTransposer > epetra_rowmatrixtransposer_dRdW
Epetra_RowMatrixTransposer used to transpose the system_matrix.
Definition: dg_base.hpp:350
DGBase(const int nstate_input, const Parameters::AllParameters *const parameters_input, const unsigned int degree, const unsigned int max_degree_input, const unsigned int grid_degree_input, const std::shared_ptr< Triangulation > triangulation_input)
Principal constructor that will call delegated constructor.
Definition: dg_base.cpp:60
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:416
void build_1D_surface_gradient_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 0 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1284
dealii::LinearAlgebra::distributed::Vector< double > solution_dRdX
Definition: dg_base.hpp:433
dealii::Vector< double > artificial_dissipation_se
Artificial dissipation error ratio sensor in each cell.
Definition: dg_base.hpp:469
void set_all_cells_fe_degree(const unsigned int degree)
Refers to a collection Mappings, which represents the high-order grid.
Definition: dg_base.cpp:292
ESFR correction matrix without jac dependence.
Definition: operators.h:564
std::vector< real > det_Jac_vol
The determinant of the metric Jacobian at volume cubature nodes.
Definition: operators.h:1216
Local mass matrix without jacobian dependence.
Definition: operators.h:461
dealii::DoFHandler< dim > dof_handler
Finite Element Collection to represent the high-order grid.
Definition: dg_base.hpp:1175
unsigned int n_dofs() const
Number of degrees of freedom.
Definition: dg_base.cpp:3023
bool enable_higher_order_vtk_output
Enable writing of higher-order vtk results.
Flux_Reconstruction flux_reconstruction_type
Store flux reconstruction type.
bool use_auxiliary_eq
Flag for using the auxiliary equation.
Definition: dg_base.hpp:1305
dealii::TrilinosWrappers::SparseMatrix system_matrix
Definition: dg_base.hpp:343
dealii::FullMatrix< double > build_dim_mass_matrix(const int nstate, const unsigned int n_dofs, const unsigned int n_quad_pts, basis_functions< dim, n_faces > &basis, const std::vector< double > &det_Jac, const std::vector< double > &quad_weights)
Assemble the dim mass matrix on the fly with metric Jacobian dependence.
Definition: operators.cpp:1388
void reinit_operators_for_mass_matrix(const bool Cartesian_element, const unsigned int poly_degree, const unsigned int grid_degree, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis, OPERATOR::basis_functions< dim, 2 *dim > &basis, OPERATOR::local_mass< dim, 2 *dim > &reference_mass_matrix, OPERATOR::local_Flux_Reconstruction_operator< dim, 2 *dim > &reference_FR, OPERATOR::local_Flux_Reconstruction_operator_aux< dim, 2 *dim > &reference_FR_aux, OPERATOR::derivative_p< dim, 2 *dim > &deriv_p)
Builds needed operators to compute mass matrices/inverses efficiently.
Definition: dg_base.cpp:3661
dealii::Vector< double > cell_volume
Time it takes for the maximum wavespeed to cross the cell domain.
Definition: dg_base.hpp:454
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
Definition: dg_base.hpp:91
dealii::FullMatrix< double > oneD_transpose_vol_operator
Stores the transpose of the operator for fast weight-adjusted solves.
Definition: operators.h:779
dealii::FullMatrix< double > build_dim_Flux_Reconstruction_operator_directly(const int nstate, const unsigned int n_dofs, dealii::FullMatrix< double > &pth_deriv, dealii::FullMatrix< double > &mass_matrix)
Computes the dim sized flux reconstruction operator for general Mass Matrix (needed for curvilinear)...
Definition: operators.cpp:1697
virtual void assemble_volume_term_and_build_operators_ad(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const std::vector< double > &soln_coeffs, const dealii::Tensor< 1, dim, std::vector< double >> &aux_soln_coeffs, const std::vector< double > &metric_coeffs, const std::vector< real > &local_dual, const std::vector< dealii::types::global_dof_index > &soln_dofs_indices, const std::vector< dealii::types::global_dof_index > &metric_dofs_indices, const unsigned int poly_degree, const unsigned int grid_degree, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis, OPERATOR::local_basis_stiffness< dim, 2 *dim > &flux_basis_stiffness, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_int, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_ext, OPERATOR::metric_operators< double, dim, 2 *dim > &metric_oper, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis, std::array< std::vector< double >, dim > &mapping_support_points, dealii::hp::FEValues< dim, dim > &fe_values_collection_volume, dealii::hp::FEValues< dim, dim > &fe_values_collection_volume_lagrange, const dealii::FESystem< dim, dim > &fe_soln, std::vector< double > &rhs, dealii::Tensor< 1, dim, std::vector< double >> &local_auxiliary_RHS, const bool compute_auxiliary_right_hand_side, double &dual_dot_residual)=0
Builds the necessary operators/fe values and assembles volume residual. For double type...
MPI_Comm mpi_communicator
MPI communicator.
Definition: dg_base.hpp:1258
dealii::LinearAlgebra::distributed::Vector< double > dual_d2R
Definition: dg_base.hpp:446
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:471
void automatic_differentiation_indexing_1(const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R, const unsigned int n_soln_dofs, const unsigned int n_metric_dofs, unsigned int &w_start, unsigned int &w_end, unsigned int &x_start, unsigned int &x_end)
Definition: dg_base.cpp:2300
dealii::LinearAlgebra::distributed::Vector< double > volume_nodes_dRdW
Definition: dg_base.hpp:426
bool do_renumber_dofs
Flag for renumbering DOFs.
dealii::IndexSet locally_owned_dofs
Locally own degrees of freedom.
Definition: dg_base.hpp:398
Base metric operators class that stores functions used in both the volume and on surface.
Definition: operators.h:1131
void assemble_residual(const bool compute_dRdW=false, const bool compute_dRdX=false, const bool compute_d2R=false, const double CFL_mass=0.0)
Main loop of the DG class.
Definition: dg_base.cpp:2599
const unsigned int initial_degree
Initial polynomial degree assigned during constructor.
Definition: dg_base.hpp:99
dealii::SparsityPattern sparsity_pattern
Sparsity pattern used on the system_matrix.
Definition: dg_base.hpp:317
ESFR correction matrix for AUX EQUATION without jac dependence.
Definition: operators.h:684
std::array< dealii::LinearAlgebra::distributed::Vector< double >, dim > auxiliary_solution
The auxiliary equations&#39; solution.
Definition: dg_base.hpp:419
dealii::FullMatrix< double > oneD_vol_operator
Stores the one dimensional volume operator.
Definition: operators.h:380
void assemble_cell_residual_and_ad_derivatives(const dealii::TriaActiveIterator< dealii::DoFCellAccessor< dim, dim, false >> &current_cell, const dealii::TriaActiveIterator< dealii::DoFCellAccessor< dim, dim, false >> &current_metric_cell, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R, dealii::hp::FEValues< dim, dim > &fe_values_collection_volume, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_int, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_ext, dealii::hp::FESubfaceValues< dim, dim > &fe_values_collection_subface, dealii::hp::FEValues< dim, dim > &fe_values_collection_volume_lagrange, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis_int, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis_ext, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis_int, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis_ext, OPERATOR::local_basis_stiffness< dim, 2 *dim > &flux_basis_stiffness, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_int, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_ext, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis, const bool compute_auxiliary_right_hand_side, dealii::LinearAlgebra::distributed::Vector< double > &rhs, std::array< dealii::LinearAlgebra::distributed::Vector< double >, dim > &rhs_aux)
Used in assemble_residual().
Definition: dg_base.cpp:453
bool do_compute_time_averaged_solution
Flag for computing time-averaged solution.
The mapping shape functions evaluated at the desired nodes (facet set included in volume grid nodes f...
Definition: operators.h:1071
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:771
double getValue(const real2 &x)
Returns the value from a CoDiPack variable.
Definition: dg_base.cpp:2290
unsigned int current_grid_degree
Stores the degree of the current grid degree.
Definition: operators.h:1084
dealii::Vector< double > max_dt_cell
Time it takes for the maximum wavespeed to cross the cell domain.
Definition: dg_base.hpp:461
virtual void allocate_model_variables()=0
Allocate the necessary variables declared in src/physics/model.h.
double FR_user_specified_correction_parameter_value
User specified flux recontruction correction parameter value.
unsigned int get_min_fe_degree()
Gets the minimum value of currently active FE degree.
Definition: dg_base.cpp:316
dealii::SparsityPattern get_d2RdWdX_sparsity_pattern()
Evaluate SparsityPattern of the residual Hessian dual.d2RdXdW.
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:1949
dealii::LinearAlgebra::distributed::Vector< double > solution_dRdW
Definition: dg_base.hpp:423
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:1873
The metric independent FR mass matrix .
Definition: operators.h:865
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:1909
void inner_product_1D(const std::vector< real > &input_vect, const std::vector< double > &weight_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const bool adding=false, const double factor=1.0)
Apply the inner product operation using the 1D operator in each direction.
Definition: operators.cpp:640
virtual void set_use_auxiliary_eq()=0
Set use_auxiliary_eq flag.
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:2053
dealii::LinearAlgebra::distributed::Vector< double > volume_nodes_dRdX
Definition: dg_base.hpp:436
dealii::LinearAlgebra::distributed::Vector< double > right_hand_side
Residual of the current solution.
Definition: dg_base.hpp:396
dealii::hp::QCollection< 1 > oneD_quadrature_collection
1D quadrature to generate Lagrange polynomials for the sake of flux interpolation.
Definition: dg_base.hpp:1155
const dealii::UpdateFlags volume_update_flags
Update flags needed at volume points.
Definition: dg_base.hpp:1212
double kappa_artificial_dissipation
Parameter kappa from Persson and Peraire, 2008.
Flux_Reconstruction_Aux
Type of correction in Flux Reconstruction for the auxiliary variables.
std::array< dealii::LinearAlgebra::distributed::Vector< double >, dim > auxiliary_right_hand_side
The auxiliary equations&#39; right hand sides.
Definition: dg_base.hpp:416
dealii::TrilinosWrappers::SparseMatrix d2RdXdX
Definition: dg_base.hpp:364
virtual void build_volume_metric_operators(const unsigned int poly_degree, const unsigned int grid_degree, const std::vector< double > &metric_coeffs, OPERATOR::metric_operators< double, dim, 2 *dim > &metric_oper, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis, std::array< std::vector< double >, dim > &mapping_support_points)=0
Builds volume metric operators (metric cofactor and determinant of metric Jacobian). For double type.
real2 discontinuity_sensor(const dealii::Quadrature< dim > &volume_quadrature, const std::vector< real2 > &soln_coeff_high, const dealii::FiniteElement< dim, dim > &fe_high, const std::vector< real2 > &jac_det)
Definition: dg_base.cpp:4571
dealii::LinearAlgebra::distributed::Vector< double > solution
Current modal coefficients of the solution.
Definition: dg_base.hpp:409
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:877
double mu_artificial_dissipation
Parameter mu from Persson & Peraire, 2008.
dealii::LinearAlgebra::distributed::Vector< real > dual
Current optimization dual variables corresponding to the residual constraints also known as the adjoi...
Definition: dg_base.hpp:483
bool store_surf_flux_nodes
Flag for storing surface flux nodes.
Definition: dg_base.hpp:1313
void update_artificial_dissipation_discontinuity_sensor()
Update discontinuity sensor.
Definition: dg_base.cpp:2369
RenumberDofsType
Renumber dofs type.
real evaluate_penalty_scaling(const DoFCellAccessorType &cell, const int iface, const dealii::hp::FECollection< dim > fe_collection) const
Definition: dg_base.cpp:397
std::string solution_vtk_files_directory_name
Name of directory for writing solution vtk files.
The metric independent inverse of the FR mass matrix for auxiliary equation .
Definition: operators.h:842
Projection operator corresponding to basis functions onto -norm.
Definition: operators.h:749
const dealii::hp::FECollection< 1 > oneD_fe_collection
1D Finite Element Collection for p-finite-element to represent the solution
Definition: dg_base.hpp:1143
dealii::SparsityPattern mass_sparsity_pattern
Sparsity pattern used on the system_matrix.
Definition: dg_base.hpp:321
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:2304
const unsigned int max_degree
Maximum degree used for p-refi1nement.
Definition: dg_base.hpp:104
dealii::Vector< double > artificial_dissipation_coeffs
Artificial dissipation in each cell.
Definition: dg_base.hpp:466
FluxNodes flux_nodes_type
Store selected FluxNodes from the input file.
real current_time
The current time set in set_current_time()
Definition: dg_base.hpp:1188
dealii::IndexSet locally_relevant_dofs
Union of locally owned degrees of freedom and relevant ghost degrees of freedom.
Definition: dg_base.hpp:400
double CFL_mass_dRdW
CFL used to add mass matrix in the optimization FlowConstraints class.
Definition: dg_base.hpp:429
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:1679
double time_to_start_computing_Reynolds_stress
Flag for starting to compute Reynolds stresses. This needs to be after the time-averaging has started...
dealii::TrilinosWrappers::SparseMatrix global_inverse_mass_matrix
Global inverser mass matrix.
Definition: dg_base.hpp:332
void set_current_time(const real current_time_input)
Sets the current time within DG to be used for unsteady source terms.
Definition: dg_base.cpp:4659
dealii::TrilinosWrappers::SparseMatrix time_scaled_global_mass_matrix
Global mass matrix divided by the time scales.
Definition: dg_base.hpp:325
const dealii::UpdateFlags face_update_flags
Update flags needed at face points.
Definition: dg_base.hpp:1215
bool add_artificial_dissipation
Flag to add artificial dissipation from Persson&#39;s shock capturing paper.
const unsigned int max_grid_degree
Maximum grid degree used for hp-refi1nement.
Definition: dg_base.hpp:109
dealii::SparsityPattern get_d2RdWdW_sparsity_pattern()
Evaluate SparsityPattern of the residual Hessian dual.d2RdWdW.
void evaluate_mass_matrices(bool do_inverse_mass_matrix=false)
Allocates and evaluates the mass matrices for the entire grid.
Definition: dg_base.cpp:3699
std::vector< real > project_function(const std::vector< real > &function_coeff, const dealii::FESystem< dim, dim > &fe_input, const dealii::FESystem< dim, dim > &fe_output, const dealii::QGauss< dim > &projection_quadrature)
Get the coefficients of a function projected onto a set of basis (to be replaced with operators->proj...
Definition: dg_base.cpp:4492
std::shared_ptr< Triangulation > triangulation
Mesh.
Definition: dg_base.hpp:160
bool current_cell_should_do_the_work(const DoFCellAccessorType1 &current_cell, const DoFCellAccessorType2 &neighbor_cell) const
In the case that two cells have the same coarseness, this function decides if the current cell should...
Definition: dg_base.cpp:417
double sipg_penalty_factor
Scaling of Symmetric Interior Penalty term to ensure coercivity.
MassiveCollectionTuple create_collection_tuple(const unsigned int max_degree, const int nstate, const Parameters::AllParameters *const parameters_input) const
Used in the delegated constructor.
Definition: dg_base.cpp:142
bool use_weight_adjusted_mass
Flag to use weight-adjusted Mass Matrix for curvilinear elements.
const dealii::hp::FECollection< dim > fe_collection
Finite Element Collection for p-finite-element to represent the solution.
Definition: dg_base.hpp:1120
void apply_global_mass_matrix(const dealii::LinearAlgebra::distributed::Vector< double > &input_vector, dealii::LinearAlgebra::distributed::Vector< double > &output_vector, const bool use_auxiliary_eq=false, const bool use_unmodified_mass_matrix=false)
Applies the local metric dependent mass matrices when the global is not stored.
Definition: dg_base.cpp:4263
void set_high_order_grid(std::shared_ptr< HighOrderGrid< dim, real, MeshType >> new_high_order_grid)
Sets the associated high order grid with the provided one.
Definition: dg_base.cpp:121
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:1990
DGBase is independent of the number of state variables.
Definition: dg_base.hpp:82
const dealii::hp::FECollection< 1 > oneD_fe_collection_flux
1D collocated flux basis used in strong form
Definition: dg_base.hpp:1153
void time_scaled_mass_matrices(const real scale)
Definition: dg_base.cpp:4451
virtual void set_store_vol_flux_nodes()=0
Set store_vol_flux_nodes flag.
dealii::FullMatrix< double > tensor_product_state(const int nstate, const dealii::FullMatrix< double > &basis_x, const dealii::FullMatrix< double > &basis_y, const dealii::FullMatrix< double > &basis_z)
Returns the tensor product of matrices passed, but makes it sparse diagonal by state.
Definition: operators.cpp:106
std::enable_if<!std::is_same< adtype, double >::value, void >::type assemble_volume_codi_taped_derivatives_ad(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const std::vector< dealii::types::global_dof_index > &soln_dofs_indices, const std::vector< dealii::types::global_dof_index > &metric_dof_indices, const unsigned int poly_degree, const unsigned int grid_degree, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis, OPERATOR::local_basis_stiffness< dim, 2 *dim > &flux_basis_stiffness, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_int, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_ext, OPERATOR::metric_operators< adtype, dim, 2 *dim > &metric_oper, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis, std::array< std::vector< adtype >, dim > &mapping_support_points, dealii::hp::FEValues< dim, dim > &fe_values_collection_volume, dealii::hp::FEValues< dim, dim > &fe_values_collection_volume_lagrange, const dealii::FESystem< dim, dim > &fe_soln, std::vector< real > &local_rhs_cell, dealii::Tensor< 1, dim, std::vector< real >> &local_auxiliary_RHS, const bool compute_auxiliary_right_hand_side, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Computes the volume term of the cell and performs automatic differentiation.
Definition: dg_base.cpp:985
void automatic_differentiation_indexing_2(const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R, const unsigned int n_soln_dofs_int, const unsigned int n_soln_dofs_ext, const unsigned int n_metric_dofs, unsigned int &w_int_start, unsigned int &w_int_end, unsigned int &w_ext_start, unsigned int &w_ext_end, unsigned int &x_int_start, unsigned int &x_int_end, unsigned int &x_ext_start, unsigned int &x_ext_end)
Definition: dg_base.cpp:2327
ArtificialDissipationParam artificial_dissipation_param
Contains parameters for artificial dissipation.
codi_HessianComputationType RadFadType
Nested reverse-forward mode type for Jacobian and Hessian computation using TapeHelper.
Definition: ADTypes.hpp:28
RenumberDofsType renumber_dofs_type
Store selected RenumberDofsType from the input file.
virtual void allocate_dRdX()
Allocates the residual derivatives w.r.t the volume nodes.
Definition: dg_base.cpp:3651
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:2021
void build_1D_surface_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 0 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1257
std::tuple< dealii::hp::FECollection< dim >, dealii::hp::QCollection< dim >, dealii::hp::QCollection< dim-1 >, dealii::hp::FECollection< dim >, dealii::hp::FECollection< 1 >, dealii::hp::FECollection< 1 >, dealii::hp::FECollection< 1 >, dealii::hp::QCollection< 1 > > MassiveCollectionTuple
Makes for cleaner doxygen documentation.
Definition: dg_base.hpp:145
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:1081
virtual void allocate_system(const bool compute_dRdW=true, const bool compute_dRdX=true, const bool compute_d2R=true)
Allocates the system.
Definition: dg_base.cpp:3478
static std::unique_ptr< dealii::DataPostprocessor< dim > > create_Postprocessor(const Parameters::AllParameters *const parameters_input)
Create the post-processor with the correct template parameters.
unsigned int get_max_fe_degree()
Gets the maximum value of currently active FE degree.
Definition: dg_base.cpp:304
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:1237
Projection operator corresponding to basis functions onto M-norm (L2).
Definition: operators.h:723
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:582
dealii::FullMatrix< double > oneD_transpose_vol_operator
Stores the transpose of the operator for fast weight-adjusted solves.
Definition: operators.h:810
dealii::SparsityPattern get_dRdX_sparsity_pattern()
Evaluate SparsityPattern of dRdX.
Local stiffness matrix without jacobian dependence.
Definition: operators.h:497
virtual void assemble_face_term_and_build_operators_ad(typename dealii::DoFHandler< dim >::active_cell_iterator cell, typename dealii::DoFHandler< dim >::active_cell_iterator neighbor_cell, const dealii::types::global_dof_index current_cell_index, const dealii::types::global_dof_index neighbor_cell_index, const unsigned int iface, const unsigned int neighbor_iface, const std::vector< double > &soln_coeff_int, const std::vector< double > &soln_coeff_ext, const dealii::Tensor< 1, dim, std::vector< double >> &aux_soln_coeff_int, const dealii::Tensor< 1, dim, std::vector< double >> &aux_soln_coeff_ext, const std::vector< double > &metric_coefF_int, const std::vector< double > &metric_coefF_ext, const std::vector< double > &dual_int, const std::vector< double > &dual_ext, const unsigned int poly_degree_int, const unsigned int poly_degree_ext, const unsigned int grid_degree_int, const unsigned int grid_degree_ext, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis_int, OPERATOR::basis_functions< dim, 2 *dim > &soln_basis_ext, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis_int, OPERATOR::basis_functions< dim, 2 *dim > &flux_basis_ext, OPERATOR::local_basis_stiffness< dim, 2 *dim > &flux_basis_stiffness, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_int, OPERATOR::vol_projection_operator< dim, 2 *dim > &soln_basis_projection_oper_ext, OPERATOR::metric_operators< double, dim, 2 *dim > &metric_oper_int, OPERATOR::metric_operators< double, dim, 2 *dim > &metric_oper_ext, OPERATOR::mapping_shape_functions< dim, 2 *dim > &mapping_basis, std::array< std::vector< double >, dim > &mapping_support_points, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_int, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_ext, dealii::hp::FESubfaceValues< dim, dim > &fe_values_collection_subface, const dealii::FESystem< dim, dim > &fe_int, const dealii::FESystem< dim, dim > &fe_ext, const real penalty, std::vector< double > &rhs_int, std::vector< double > &rhs_ext, dealii::Tensor< 1, dim, std::vector< double >> &aux_rhs_int, dealii::Tensor< 1, dim, std::vector< double >> &aux_rhs_ext, const bool compute_auxiliary_right_hand_side, double &dual_dot_residual, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R, const bool is_a_subface, const unsigned int neighbor_i_subface)=0
Builds the necessary operators/fe values and assembles face residual. For double type.
int overintegration
Number of additional quadrature points to use.
void output_results_vtk(const unsigned int cycle, const double current_time=0.0, const bool output_time_averaged_solution=false, const bool output_fluctuating_quantities=false)
Output solution.
Definition: dg_base.cpp:3339
bool store_residual_cpu_time
Flag to store the residual local processor cpu time.
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:695
dealii::LinearAlgebra::distributed::Vector< double > solution_d2R
Definition: dg_base.hpp:440
dealii::TrilinosWrappers::SparseMatrix d2RdWdW
Definition: dg_base.hpp:360
dealii::TrilinosWrappers::SparseMatrix global_inverse_mass_matrix_auxiliary
Global inverse of the auxiliary mass matrix.
Definition: dg_base.hpp:339
bool store_vol_flux_nodes
Flag for storing volume flux nodes.
Definition: dg_base.hpp:1309