[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
weak_dg.cpp
1 #include <deal.II/base/tensor.h>
2 #include <deal.II/base/table.h>
3 
4 #include <deal.II/base/qprojector.h>
5 
6 #include <deal.II/lac/full_matrix.templates.h>
7 //#include <deal.II/lac/full_matrix.h>
8 
9 #include <deal.II/fe/fe_values.h>
10 
11 #include <deal.II/dofs/dof_handler.h>
12 #include <deal.II/dofs/dof_tools.h>
13 
14 #include <deal.II/lac/vector.h>
15 
16 #include "ADTypes.hpp"
17 
18 #include "solution/local_solution.hpp"
19 #include "weak_dg.hpp"
20 
21 #define KOPRIVA_METRICS_VOL
22 #define KOPRIVA_METRICS_FACE
23 #define KOPRIVA_METRICS_BOUNDARY
24 //#define FADFAD
25 
26 namespace {
27 template <typename real, int dim> using Coord = std::array<real, dim>;
28 // First index corresponds to the component of the coordinate, second index corresponds to the component of the gradient.
29 template <typename real, int dim> using CoordGrad = std::array<dealii::Tensor<1, dim, real>, dim>;
30 
31 template <typename real, int nstate> using State = std::array<real, nstate>;
32 // First index corresponds to the component of the state, second index corresponds to the component of the gradient.
33 template <typename real, int dim, int nstate> using DirectionalState = std::array<dealii::Tensor<1, dim, real>, nstate>;
34 }
35 
36 namespace {
39 template <typename number>
40 void gauss_jordan(dealii::FullMatrix<number> &input_matrix) {
41  Assert(!input_matrix.empty(), dealii::ExcMessage("Empty matrix"))
42  Assert(input_matrix.n_cols() == input_matrix.n_rows(), dealii::ExcMessage("Non quadratic matrix"));
43 
44  // Gauss-Jordan-Algorithm from Stoer & Bulirsch I (4th Edition) p. 153
45  const size_t N = input_matrix.n();
46 
47  // First get an estimate of the size of the elements of this matrix,
48  // for later checks whether the pivot element is large enough,
49  // for whether we have to fear that the matrix is not regular
50  number diagonal_sum = 0;
51  for (size_t i = 0; i < N; ++i) diagonal_sum = diagonal_sum + abs(input_matrix(i, i));
52  const number typical_diagonal_element = diagonal_sum / N;
53  (void)typical_diagonal_element;
54 
55  // initialize the array that holds the permutations that we find during pivot search
56  std::vector<size_t> p(N);
57  for (size_t i = 0; i < N; ++i) p[i] = i;
58 
59  for (size_t j = 0; j < N; ++j) {
60  // pivot search: search that part of the line on and
61  // right of the diagonal for the largest element
62  number max_pivot = abs(input_matrix(j, j));
63  size_t r = j;
64  for (size_t i = j + 1; i < N; ++i) {
65  if (abs(input_matrix(i, j)) > max_pivot) {
66  max_pivot = abs(input_matrix(i, j));
67  r = i;
68  }
69  }
70  // check whether the pivot is too small
71  Assert(max_pivot > 1.e-16 * typical_diagonal_element, dealii::ExcMessage("Non regular matrix"));
72 
73  // row interchange
74  if (r > j) {
75  for (size_t k = 0; k < N; ++k) std::swap(input_matrix(j, k), input_matrix(r, k));
76 
77  std::swap(p[j], p[r]);
78  }
79 
80  // transformation
81  const number hr = number(1.) / input_matrix(j, j);
82  input_matrix(j, j) = hr;
83  for (size_t k = 0; k < N; ++k) {
84  if (k == j) continue;
85  for (size_t i = 0; i < N; ++i) {
86  if (i == j) continue;
87  input_matrix(i, k) -= input_matrix(i, j) * input_matrix(j, k) * hr;
88  }
89  }
90  for (size_t i = 0; i < N; ++i) {
91  input_matrix(i, j) *= hr;
92  input_matrix(j, i) *= -hr;
93  }
94  input_matrix(j, j) = hr;
95  }
96  // column interchange
97  std::vector<number> hv(N);
98  for (size_t i = 0; i < N; ++i) {
99  for (size_t k = 0; k < N; ++k) hv[p[k]] = input_matrix(i, k);
100  for (size_t k = 0; k < N; ++k) input_matrix(i, k) = hv[k];
101  }
102 }
103 
105 
107 template <typename real>
108 double getValue(const real &x) {
109  if constexpr (std::is_same<real, double>::value) {
110  return x;
111  } else {
112  return getValue(x.value());
113  }
114 }
116 
120 template <int dim, typename real1, typename real2>
121 dealii::Tensor<1, dim, real1> vmult(const dealii::Tensor<2, dim, real1> A, const dealii::Tensor<1, dim, real2> x) {
122  dealii::Tensor<1, dim, real1> y;
123  for (int row = 0; row < dim; ++row) {
124  y[row] = 0.0;
125  for (int col = 0; col < dim; ++col) {
126  y[row] += A[row][col] * x[col];
127  }
128  }
129  return y;
130 }
131 
133 
137 template <int dim, typename real1>
138 real1 norm(const dealii::Tensor<1, dim, real1> x) {
139  real1 val = 0.0;
140  for (int row = 0; row < dim; ++row) {
141  val += x[row] * x[row];
142  }
143  return sqrt(val);
144 }
145 
151 void automatic_differentiation_indexing_1(
152  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
153  const unsigned int n_soln_dofs, const unsigned int n_metric_dofs,
154  unsigned int &w_start, unsigned int &w_end,
155  unsigned int &x_start, unsigned int &x_end)
156 {
157  w_start = 0;
158  w_end = 0;
159  x_start = 0;
160  x_end = 0;
161  if (compute_d2R || (compute_dRdW && compute_dRdX)) {
162  w_start = 0;
163  w_end = w_start + n_soln_dofs;
164  x_start = w_end;
165  x_end = x_start + n_metric_dofs;
166  } else if (compute_dRdW) {
167  w_start = 0;
168  w_end = w_start + n_soln_dofs;
169  x_start = w_end;
170  x_end = x_start + 0;
171  } else if (compute_dRdX) {
172  w_start = 0;
173  w_end = w_start + 0;
174  x_start = w_end;
175  x_end = x_start + n_metric_dofs;
176  } else {
177  std::cout << "Called the derivative version of the residual without requesting the derivative" << std::endl;
178  }
179 }
180 
186 void automatic_differentiation_indexing_2(
187  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R,
188  const unsigned int n_soln_dofs_int, const unsigned int n_soln_dofs_ext, const unsigned int n_metric_dofs,
189  unsigned int &w_int_start, unsigned int &w_int_end, unsigned int &w_ext_start, unsigned int &w_ext_end,
190  unsigned int &x_int_start, unsigned int &x_int_end, unsigned int &x_ext_start, unsigned int &x_ext_end)
191 {
192  // Current derivative order is: soln_int, soln_ext, metric_int, metric_ext
193  w_int_start = 0; w_int_end = 0; w_ext_start = 0; w_ext_end = 0;
194  x_int_start = 0; x_int_end = 0; x_ext_start = 0; x_ext_end = 0;
195  if (compute_d2R || (compute_dRdW && compute_dRdX)) {
196  w_int_start = 0;
197  w_int_end = w_int_start + n_soln_dofs_int;
198  w_ext_start = w_int_end;
199  w_ext_end = w_ext_start + n_soln_dofs_ext;
200  x_int_start = w_ext_end;
201  x_int_end = x_int_start + n_metric_dofs;
202  x_ext_start = x_int_end;
203  x_ext_end = x_ext_start + n_metric_dofs;
204  } else if (compute_dRdW) {
205  w_int_start = 0;
206  w_int_end = w_int_start + n_soln_dofs_int;
207  w_ext_start = w_int_end;
208  w_ext_end = w_ext_start + n_soln_dofs_ext;
209  x_int_start = w_ext_end;
210  x_int_end = x_int_start + 0;
211  x_ext_start = x_int_end;
212  x_ext_end = x_ext_start + 0;
213  } else if (compute_dRdX) {
214  w_int_start = 0;
215  w_int_end = w_int_start + 0;
216  w_ext_start = w_int_end;
217  w_ext_end = w_ext_start + 0;
218  x_int_start = w_ext_end;
219  x_int_end = x_int_start + n_metric_dofs;
220  x_ext_start = x_int_end;
221  x_ext_end = x_ext_start + n_metric_dofs;
222  } else {
223  std::cout << "Called the derivative version of the residual without requesting the derivative" << std::endl;
224  }
225 }
226 
227 template <int dim, typename real>
228 bool check_same_coords (
229  const std::vector<dealii::Point<dim>> &unit_quad_pts_int,
230  const std::vector<dealii::Point<dim>> &unit_quad_pts_ext,
231  const PHiLiP::LocalSolution<real, dim, dim> &metric_int,
232  const PHiLiP::LocalSolution<real, dim, dim> &metric_ext,
233  const double tolerance)
234 {
235  assert(unit_quad_pts_int.size() == unit_quad_pts_ext.size());
236  const unsigned int nquad = unit_quad_pts_int.size();
237  std::vector<Coord<real,dim>> coords_int = metric_int.evaluate_values(unit_quad_pts_int);
238  std::vector<Coord<real,dim>> coords_ext = metric_ext.evaluate_values(unit_quad_pts_ext);
239 
240  bool issame = true;
241  for (unsigned int iquad = 0; iquad < nquad; ++iquad) {
242  for (int d=0; d<dim; ++d) {
243  real abs_diff = abs(coords_int[iquad][d] - coords_ext[iquad][d]);
244  if (abs_diff > tolerance) {
245  real rel_diff = abs_diff / coords_int[iquad][d];
246  if (rel_diff > tolerance) {
247  issame = false;
248  }
249  }
250  }
251  if (!issame) {
252  std::cout << std::setprecision(std::numeric_limits<long double>::digits10 + 1);
253  std::cout << "coords_int ";
254  for (int d=0;d<dim;++d) {
255  std::cout << coords_int[iquad][d] << " ";
256  }
257  std::cout << std::endl;
258  std::cout << "coords_ext ";
259  for (int d=0;d<dim;++d) {
260  std::cout << coords_ext[iquad][d] << " ";
261  }
262  std::cout << std::endl;
263  }
264  }
265  return issame;
266 }
267 
268 template <int dim, typename real>
269 std::vector<dealii::Tensor<2,dim,real>> evaluate_metric_jacobian (
270  const std::vector<dealii::Point<dim>> &points,
271  const PHiLiP::LocalSolution<real, dim, dim> metric_solution)
272 {
273  const unsigned int n_dofs = metric_solution.finite_element.dofs_per_cell;
274  (void) n_dofs;
275  const unsigned int n_pts = points.size();
276 
277  AssertDimension(n_dofs, metric_solution.coefficients.size());
278 
279  std::vector<CoordGrad<real,dim>> coords_gradients = metric_solution.evaluate_reference_gradients(points);
280 
281  std::vector<dealii::Tensor<2,dim,real>> metric_jacobian(n_pts);
282 
283  for (unsigned int ipoint=0; ipoint<n_pts; ++ipoint) {
284  for (int row=0;row<dim;++row) {
285  for (int col=0;col<dim;++col) {
286  metric_jacobian[ipoint][row][col] = coords_gradients[ipoint][row][col];
287  }
288  }
289  }
290  return metric_jacobian;
291 }
292 
293 template <int dim, typename real>
294 std::vector <real> determinant_ArrayTensor(std::vector<CoordGrad<real,dim>> &coords_gradients)
295 {
296  const unsigned int n = coords_gradients.size();
297  std::vector <real> determinants(n);
298  for (unsigned int i=0; i<n; ++i) {
299  if constexpr(dim==1) {
300  determinants[i] = coords_gradients[i][0][0];
301  }
302  if constexpr(dim==2) {
303  determinants[i] = coords_gradients[i][0][0] * coords_gradients[i][1][1] - coords_gradients[i][0][1] * coords_gradients[i][1][0];
304  }
305  if constexpr(dim==3) {
306  determinants[i] = +coords_gradients[i][0][0] * (coords_gradients[i][1][1] * coords_gradients[i][2][2] - coords_gradients[i][1][2] * coords_gradients[i][2][1])
307  -coords_gradients[i][0][1] * (coords_gradients[i][1][0] * coords_gradients[i][2][2] - coords_gradients[i][1][2] * coords_gradients[i][2][0])
308  +coords_gradients[i][0][2] * (coords_gradients[i][1][0] * coords_gradients[i][2][1] - coords_gradients[i][1][1] * coords_gradients[i][2][0]);
309  }
310  }
311  return determinants;
312 }
313 
314 template <int dim, typename real>
315 void evaluate_covariant_metric_jacobian (
316  const dealii::Quadrature<dim> &quadrature,
317  const PHiLiP::LocalSolution<real, dim, dim> metric_solution,
318  std::vector<dealii::Tensor<2,dim,real>> &covariant_metric_jacobian,
319  std::vector<real> &jacobian_determinants)
320 {
321  const dealii::FiniteElement<dim> &fe_lagrange_grid = metric_solution.finite_element.base_element(0);
322 
323  const std::vector< dealii::Point<dim,double> > &unit_grid_pts = fe_lagrange_grid.get_unit_support_points();
324  std::vector<Coord<real, dim>> coords = metric_solution.evaluate_values(unit_grid_pts);
325  std::vector<CoordGrad<real, dim>> coords_gradients = metric_solution.evaluate_reference_gradients(unit_grid_pts);
326 
327  const std::vector< dealii::Point<dim,double> > &unit_quad_pts = quadrature.get_points();
328  std::vector<CoordGrad<real, dim>> quad_pts_coords_gradients = metric_solution.evaluate_reference_gradients(unit_quad_pts);
329 
330  const unsigned int n_grid_pts = unit_grid_pts.size();
331  const unsigned int n_quad_pts = unit_quad_pts.size();
332 
333  jacobian_determinants = determinant_ArrayTensor<dim,real>(quad_pts_coords_gradients);
334 
335  if constexpr (dim==1) {
336  for (unsigned int iquad = 0; iquad<n_quad_pts; ++iquad) {
337  const real invJ = 1.0/jacobian_determinants[iquad];
338  covariant_metric_jacobian[iquad][0][0] = invJ;
339  }
340  }
341 
342  if constexpr (dim==2) {
343  // Remark 5 of Kopriva (2006).
344  // Need to interpolate physical coordinates, and then differentiate it
345  // using the derivatives of the collocated Lagrange basis.
346 
347  std::vector<dealii::Tensor<2,dim,real>> dphys_dref_quad(n_quad_pts);
348 
349  // In 2D Cross-Product Form = Conservative-Curl Form
350  for (unsigned int iquad = 0; iquad<n_quad_pts; ++iquad) {
351 
352  dphys_dref_quad[iquad] = 0.0;
353 
354  const dealii::Point<dim,double> &quad_point = unit_quad_pts[iquad];
355 
356  for (unsigned int igrid = 0; igrid<n_grid_pts; ++igrid) {
357 
358  const dealii::Tensor<1,dim,double> shape_grad = fe_lagrange_grid.shape_grad(igrid, quad_point);
359 
360  for(int dphys=0; dphys<dim; dphys++) {
361  for(int dref=0; dref<dim; dref++) {
362  dphys_dref_quad[iquad][dphys][dref] += coords[igrid][dphys] * shape_grad[dref];
363  }
364  }
365  }
366  }
367 
368  // In 2D Cross-Product Form = Conservative-Curl Form
369  for (unsigned int iquad = 0; iquad<n_quad_pts; ++iquad) {
370 
371  const real invJ = 1.0/jacobian_determinants[iquad];
372 
373  covariant_metric_jacobian[iquad] = 0.0;
374 
375  // inv(A)^T = [ a b ]^-T = (1/det(A)) [ d -c ]
376  // [ c d ] [-b a ]
377  covariant_metric_jacobian[iquad][0][0] = dphys_dref_quad[iquad][1][1] * invJ;
378  covariant_metric_jacobian[iquad][0][1] = -dphys_dref_quad[iquad][1][0] * invJ;
379  covariant_metric_jacobian[iquad][1][0] = -dphys_dref_quad[iquad][0][1] * invJ;
380  covariant_metric_jacobian[iquad][1][1] = dphys_dref_quad[iquad][0][0] * invJ;
381 
382  }
383 
384  }
385  if constexpr (dim == 3) {
386 
387  // Evaluate the physical (Y grad Z), (Z grad X), (X grad
388  std::vector<real> Ta(n_grid_pts);
389  std::vector<real> Tb(n_grid_pts);
390  std::vector<real> Tc(n_grid_pts);
391 
392  std::vector<real> Td(n_grid_pts);
393  std::vector<real> Te(n_grid_pts);
394  std::vector<real> Tf(n_grid_pts);
395 
396  std::vector<real> Tg(n_grid_pts);
397  std::vector<real> Th(n_grid_pts);
398  std::vector<real> Ti(n_grid_pts);
399 
400  for(unsigned int igrid=0; igrid<n_grid_pts; igrid++) {
401  Ta[igrid] = 0.5*(coords_gradients[igrid][1][1] * coords[igrid][2] - coords_gradients[igrid][2][1] * coords[igrid][1]);
402  Tb[igrid] = 0.5*(coords_gradients[igrid][1][2] * coords[igrid][2] - coords_gradients[igrid][2][2] * coords[igrid][1]);
403  Tc[igrid] = 0.5*(coords_gradients[igrid][1][0] * coords[igrid][2] - coords_gradients[igrid][2][0] * coords[igrid][1]);
404 
405  Td[igrid] = 0.5*(coords_gradients[igrid][2][1] * coords[igrid][0] - coords_gradients[igrid][0][1] * coords[igrid][2]);
406  Te[igrid] = 0.5*(coords_gradients[igrid][2][2] * coords[igrid][0] - coords_gradients[igrid][0][2] * coords[igrid][2]);
407  Tf[igrid] = 0.5*(coords_gradients[igrid][2][0] * coords[igrid][0] - coords_gradients[igrid][0][0] * coords[igrid][2]);
408 
409  Tg[igrid] = 0.5*(coords_gradients[igrid][0][1] * coords[igrid][1] - coords_gradients[igrid][1][1] * coords[igrid][0]);
410  Th[igrid] = 0.5*(coords_gradients[igrid][0][2] * coords[igrid][1] - coords_gradients[igrid][1][2] * coords[igrid][0]);
411  Ti[igrid] = 0.5*(coords_gradients[igrid][0][0] * coords[igrid][1] - coords_gradients[igrid][1][0] * coords[igrid][0]);
412  }
413 
414  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++) {
415 
416  covariant_metric_jacobian[iquad] = 0.0;
417 
418  const dealii::Point<dim,double> &quad_point = unit_quad_pts[iquad];
419 
420  for(unsigned int igrid=0; igrid<n_grid_pts; igrid++) {
421 
422  const dealii::Tensor<1,dim,double> shape_grad = fe_lagrange_grid.shape_grad(igrid, quad_point);
423 
424  covariant_metric_jacobian[iquad][0][0] += shape_grad[2] * Ta[igrid] - shape_grad[1] * Tb[igrid];
425  covariant_metric_jacobian[iquad][1][0] += shape_grad[2] * Td[igrid] - shape_grad[1] * Te[igrid];
426  covariant_metric_jacobian[iquad][2][0] += shape_grad[2] * Tg[igrid] - shape_grad[1] * Th[igrid];
427 
428  covariant_metric_jacobian[iquad][0][1] += shape_grad[0] * Tb[igrid] - shape_grad[2] * Tc[igrid];
429  covariant_metric_jacobian[iquad][1][1] += shape_grad[0] * Te[igrid] - shape_grad[2] * Tf[igrid];
430  covariant_metric_jacobian[iquad][2][1] += shape_grad[0] * Th[igrid] - shape_grad[2] * Ti[igrid];
431 
432  covariant_metric_jacobian[iquad][0][2] += shape_grad[1] * Tc[igrid] - shape_grad[0] * Ta[igrid];
433  covariant_metric_jacobian[iquad][1][2] += shape_grad[1] * Tf[igrid] - shape_grad[0] * Td[igrid];
434  covariant_metric_jacobian[iquad][2][2] += shape_grad[1] * Ti[igrid] - shape_grad[0] * Tg[igrid];
435  }
436 
437  const real invJ = 1.0/jacobian_determinants[iquad];
438  covariant_metric_jacobian[iquad] *= invJ;
439 
440  }
441 
442  }
443 
444 }
445 }
446 
447 namespace PHiLiP {
448 
449 template <int dim, int nstate, typename real, typename MeshType>
451  const Parameters::AllParameters *const parameters_input,
452  const unsigned int degree,
453  const unsigned int max_degree_input,
454  const unsigned int grid_degree_input,
455  const std::shared_ptr<Triangulation> triangulation_input)
456  : DGBaseState<dim,nstate,real,MeshType>::DGBaseState(parameters_input, degree, max_degree_input, grid_degree_input, triangulation_input)
457 { }
458 
459 template <int dim, int nstate, typename real, typename MeshType>
461  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
462  const dealii::types::global_dof_index current_cell_index,
463  const dealii::FEValues<dim,dim> &fe_values_vol,
464  const std::vector<dealii::types::global_dof_index> &soln_dof_indices_int,
465  const std::vector<dealii::types::global_dof_index> &/*metric_dof_indices*/,
466  const unsigned int /*poly_degree*/,
467  const unsigned int /*grid_degree*/,
468  dealii::Vector<real> &/*local_rhs_int_cell*/,
469  const dealii::FEValues<dim,dim> &/*fe_values_lagrange*/)
470 {
471  using State = State<real, nstate>;
472  using DirectionalState = DirectionalState<real, dim, nstate>;
473 
474  (void) current_cell_index;
475 
476  const unsigned int n_quad_pts = fe_values_vol.n_quadrature_points;
477  const unsigned int n_soln_dofs_int = fe_values_vol.dofs_per_cell;
478 
479  AssertDimension (n_soln_dofs_int, soln_dof_indices_int.size());
480 
481  const std::vector<real> &JxW = fe_values_vol.get_JxW_values ();
482 
483  real cell_volume_estimate = 0.0;
484  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
485  cell_volume_estimate = cell_volume_estimate + JxW[iquad];
486  }
487  const real cell_volume = cell_volume_estimate;
488 
489  std::vector<State> soln_at_q(n_quad_pts);
490  std::vector<State> source_at_q;
491  std::vector<State> physical_source_at_q;
492  std::vector<DirectionalState> soln_grad_at_q(n_quad_pts);
493  std::vector<DirectionalState> conv_phys_flux_at_q(n_quad_pts);
494  std::vector<DirectionalState> diss_phys_flux_at_q(n_quad_pts);
495 
496  std::vector< real > soln_coeff(n_soln_dofs_int);
497  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
498  soln_coeff[idof] = DGBase<dim,real,MeshType>::solution(soln_dof_indices_int[idof]);
499  }
500 
501  typename dealii::DoFHandler<dim>::active_cell_iterator artificial_dissipation_cell(
502  this->triangulation.get(), cell->level(), cell->index(), &(this->dof_handler_artificial_dissipation));
503  const unsigned int n_dofs_arti_diss = this->fe_q_artificial_dissipation.dofs_per_cell;
504  std::vector<dealii::types::global_dof_index> dof_indices_artificial_dissipation(n_dofs_arti_diss);
505  artificial_dissipation_cell->get_dof_indices (dof_indices_artificial_dissipation);
506 
507  std::vector<real> artificial_diss_coeff_at_q(n_quad_pts);
508  real max_artificial_diss = 0.0;
509  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
510  artificial_diss_coeff_at_q[iquad] = 0.0;
511 
513  const dealii::Point<dim,real> point = fe_values_vol.get_quadrature().point(iquad);
514  for (unsigned int idof=0; idof<n_dofs_arti_diss; ++idof) {
515  const unsigned int index = dof_indices_artificial_dissipation[idof];
516  artificial_diss_coeff_at_q[iquad] += this->artificial_dissipation_c0[index] * this->fe_q_artificial_dissipation.shape_value(idof, point);
517  }
518  max_artificial_diss = std::max(artificial_diss_coeff_at_q[iquad], max_artificial_diss);
519  }
520  }
521 
522  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
523  for (int istate=0; istate<nstate; istate++) {
524  // Interpolate solution to the face quadrature points
525  soln_at_q[iquad][istate] = 0;
526  soln_grad_at_q[iquad][istate] = 0;
527  }
528  }
529  // Interpolate solution to face
530  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
531  for (unsigned int idof=0; idof<n_soln_dofs_int; ++idof) {
532  const unsigned int istate = fe_values_vol.get_fe().system_to_component_index(idof).first;
533  soln_at_q[iquad][istate] += soln_coeff[idof] * fe_values_vol.shape_value_component(idof, iquad, istate);
534  soln_grad_at_q[iquad][istate] += soln_coeff[idof] * fe_values_vol.shape_grad_component(idof, iquad, istate);
535  }
536  }
537 
538  const unsigned int cell_index = fe_values_vol.get_cell()->active_cell_index();
539  const unsigned int cell_degree = fe_values_vol.get_fe().tensor_degree();
540  const real diameter = fe_values_vol.get_cell()->diameter();
541  const real cell_diameter = cell_volume / std::pow(diameter,dim-1);
542  //const real cell_diameter = std::pow(cell_volume,1.0/dim);
543  //const real cell_diameter = cell_volume;
544  const real cell_radius = 0.5 * cell_diameter;
545  this->cell_volume[cell_index] = cell_volume;
546  this->max_dt_cell[cell_index] = DGBaseState<dim,nstate,real,MeshType>::evaluate_CFL ( soln_at_q, max_artificial_diss, cell_radius, cell_degree);
547 }
548 
549 template <int dim, int nstate, typename real2>
550 void compute_br2_correction(
551  const dealii::FESystem<dim,dim> &fe_soln,
552  const LocalSolution<real2, dim, dim> &metric_solution,
553  const std::vector<State<real2, nstate>> &lifting_op_R_rhs,
554  std::vector<State<real2, nstate>> &soln_grad_correction
555  )
556 {
557  const unsigned int n_faces = std::pow(2,dim);
558  const double br2_factor = n_faces * 1.01;
559 
560  // Get the base finite element
561  // Assumption is that the vector-valued finite element uses the same basis for every state equation.
562  const dealii::FiniteElement<dim> &base_fe = fe_soln.get_sub_fe(0,1);
563  const unsigned int n_base_dofs = base_fe.n_dofs_per_cell();
564 
565  // Build lifting term of BR2
566  // For this purposes of BR2, do NOT overintegrate to have a square invertible differentiation matrix
567  const int degree = base_fe.tensor_degree();
568  dealii::QGauss<dim> vol_quad(degree+1);
569  const unsigned int n_vol_quad = vol_quad.size();
570 
571  if (n_base_dofs != n_vol_quad) std::abort();
572 
573  // Obtain metric Jacobians at volume quadratures.
574  const std::vector<dealii::Point<dim,double>> &vol_unit_quad_pts = vol_quad.get_points();
575  using Tensor2D = dealii::Tensor<2,dim,real2>;
576  std::vector<Tensor2D> volume_metric_jac = evaluate_metric_jacobian (vol_unit_quad_pts, metric_solution);
577 
578  // Evaluate Vandermonde operator
579  dealii::FullMatrix<double> vandermonde_inverse(n_base_dofs, n_vol_quad);
580 
581  for (unsigned int idof_base=0; idof_base<n_base_dofs; ++idof_base) {
582  for (unsigned int iquad=0; iquad<n_vol_quad; ++iquad) {
583  vandermonde_inverse[idof_base][iquad] = base_fe.shape_value(idof_base, vol_quad.point(iquad));
584  }
585  }
586  gauss_jordan(vandermonde_inverse);
587 
588  std::vector< std::array<real2,nstate> > vandermonde_inv_rhs(n_vol_quad);
589  for (unsigned int kquad=0; kquad<n_vol_quad; ++kquad) {
590  for (int s=0; s<nstate; s++) {
591  vandermonde_inv_rhs[kquad][s] = 0.0;
592  for (unsigned int jdof_base=0; jdof_base<n_base_dofs; ++jdof_base) {
593  vandermonde_inv_rhs[kquad][s] += vandermonde_inverse[kquad][jdof_base] * lifting_op_R_rhs[jdof_base][s];
594  }
595  }
596  }
597  for (unsigned int kquad=0; kquad<n_vol_quad; ++kquad) {
598  for (int s=0; s<nstate; s++) {
599  vandermonde_inv_rhs[kquad][s] /= dealii::determinant(volume_metric_jac[kquad]) * vol_quad.weight(kquad);
600  }
601  }
602  for (unsigned int idof_base=0; idof_base<n_base_dofs; ++idof_base) {
603  for (int s=0; s<nstate; s++) {
604  soln_grad_correction[idof_base][s] = 0.0;
605  for (unsigned int kquad=0; kquad<n_vol_quad; ++kquad) {
606  soln_grad_correction[idof_base][s] += vandermonde_inverse[kquad][idof_base] * vandermonde_inv_rhs[kquad][s];
607  }
608  soln_grad_correction[idof_base][s] *= br2_factor;
609  //soln_grad_correction[idof_base][s] /= dim; // Due to the dot-product of the vector-valued mass matrix
610  }
611  }
612 }
613 
614 template <int dim, int nstate, typename real2>
615 void correct_the_gradient(
616  const std::vector<State<real2, nstate>> &soln_grad_corr,
617  const dealii::FESystem<dim,dim> &fe_soln,
618  const std::vector<DirectionalState<real2, dim, nstate>> &soln_jump,
619  const dealii::FullMatrix<double> &interpolation_operator,
620  const std::array<dealii::FullMatrix<real2>,dim> &gradient_operator,
621  std::vector<DirectionalState<real2, dim, nstate>> &soln_grad)
622 {
623  (void) soln_jump;
624  (void) soln_grad_corr;
625  (void) interpolation_operator;
626  (void) gradient_operator;
627  const unsigned int n_quad = soln_grad.size();
628  const unsigned int n_soln_dofs = fe_soln.dofs_per_cell;
629 
630  for (unsigned int iquad=0; iquad<n_quad; ++iquad) {
631  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
632  const unsigned int istate = fe_soln.system_to_component_index(idof).first;
633  const unsigned int idof_base = fe_soln.system_to_component_index(idof).second;
634  (void) istate;
635  (void) idof_base;
636  for (int d=0;d<dim;++d) {
637  //soln_grad[iquad][istate][d] += soln_jump[iquad][istate][d];
638  soln_grad[iquad][istate][d] += soln_grad_corr[idof_base][istate] * interpolation_operator[idof][iquad];
639  //soln_grad[iquad][istate][d] += soln_grad_corr[idof_base][istate] * gradient_operator[d][idof][iquad];
640  }
641  }
642  }
643 }
644 
645 template <int dim, int nstate, typename real, typename MeshType>
646 template <typename real2>
648  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
649  const dealii::types::global_dof_index current_cell_index,
650  const LocalSolution<real2, dim, nstate> &local_solution,
651  const LocalSolution<real2, dim, dim> &local_metric,
652  const std::vector< real > &local_dual,
653  const unsigned int face_number,
654  const unsigned int boundary_id,
658  const dealii::FEFaceValuesBase<dim,dim> &fe_values_boundary,
659  const real penalty,
660  const dealii::Quadrature<dim-1> &quadrature,
661  std::vector<real2> &rhs,
662  real2 &dual_dot_residual,
663  const bool compute_metric_derivatives)
664 {
665  const unsigned int n_soln_dofs = local_solution.finite_element.dofs_per_cell;
666  const unsigned int n_metric_dofs = local_metric.finite_element.dofs_per_cell;
667  const unsigned int n_quad_pts = fe_values_boundary.n_quadrature_points;
668 
669  dual_dot_residual = 0.0;
670  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
671  rhs[itest] = 0.0;
672  }
673 
674  using State = State<real2, nstate>;
675  using DirectionalState = DirectionalState<real2, dim, nstate>;
676 
677  const dealii::Quadrature<dim> face_quadrature
678  = dealii::QProjector<dim>::project_to_face(
679  dealii::ReferenceCell::get_hypercube(dim),
680  quadrature,
681  face_number);
682  const std::vector<dealii::Point<dim,real>> &unit_quad_pts = face_quadrature.get_points();
683  std::vector<dealii::Point<dim,real2>> real_quad_pts(unit_quad_pts.size());
684 
685  std::vector<dealii::Tensor<2,dim,real2>> metric_jacobian = evaluate_metric_jacobian (unit_quad_pts, local_metric);
686  std::vector<real2> jac_det(n_quad_pts);
687  std::vector<real2> surface_jac_det(n_quad_pts);
688  std::vector<dealii::Tensor<2,dim,real2>> jac_inv_tran(n_quad_pts);
689 
690  const dealii::Tensor<1,dim,real> unit_normal = dealii::GeometryInfo<dim>::unit_normal_vector[face_number];
691  std::vector<dealii::Tensor<1,dim,real2>> phys_unit_normal(n_quad_pts);
692 
693  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
694  if (compute_metric_derivatives) {
695  for (int d=0;d<dim;++d) { real_quad_pts[iquad][d] = 0;}
696  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
697  const int iaxis = local_metric.finite_element.system_to_component_index(idof).first;
698  real_quad_pts[iquad][iaxis] += local_metric.coefficients[idof] * local_metric.finite_element.shape_value(idof,unit_quad_pts[iquad]);
699  }
700 
701  const real2 jacobian_determinant = dealii::determinant(metric_jacobian[iquad]);
702  const dealii::Tensor<2,dim,real2> jacobian_transpose_inverse = dealii::transpose(dealii::invert(metric_jacobian[iquad]));
703 
704  jac_det[iquad] = jacobian_determinant;
705  jac_inv_tran[iquad] = jacobian_transpose_inverse;
706 
707  const dealii::Tensor<1,dim,real2> normal = vmult(jacobian_transpose_inverse, unit_normal);
708  const real2 area = norm(normal);
709 
710  surface_jac_det[iquad] = norm(normal)*jac_det[iquad];
711  // Technically the normals have jac_det multiplied.
712  // However, we use normalized normals by convention, so the term
713  // ends up appearing in the surface jacobian.
714  for (int d=0;d<dim;++d) {
715  phys_unit_normal[iquad][d] = normal[d] / area;
716  }
717 
718  // Exact mapping
719  // real_quad_pts[iquad] = fe_values_boundary.quadrature_point(iquad);
720  // surface_jac_det[iquad] = fe_values_boundary.JxW(iquad) / face_quadrature.weight(iquad);
721  // phys_unit_normal[iquad] = fe_values_boundary.normal_vector(iquad);
722 
723  } else {
724  real_quad_pts[iquad] = fe_values_boundary.quadrature_point(iquad);
725  surface_jac_det[iquad] = fe_values_boundary.JxW(iquad) / face_quadrature.weight(iquad);
726  phys_unit_normal[iquad] = fe_values_boundary.normal_vector(iquad);
727  }
728 
729  }
730 #ifdef KOPRIVA_METRICS_BOUNDARY
731  auto old_jac_det = jac_det;
732  auto old_jac_inv_tran = jac_inv_tran;
733 
734  if constexpr (dim != 1) {
735  evaluate_covariant_metric_jacobian<dim,real2> ( face_quadrature, local_metric, jac_inv_tran, jac_det);
736  }
737 #endif
738 
739  std::vector<real2> faceJxW(n_quad_pts);
740 
741  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
742  if (compute_metric_derivatives) {
743  const dealii::Tensor<1,dim,real2> normal = vmult(jac_inv_tran[iquad], unit_normal);
744  const real2 area = norm(normal);
745 
746  surface_jac_det[iquad] = norm(normal)*jac_det[iquad];
747  // Technically the normals have jac_det multiplied.
748  // However, we use normalized normals by convention, so the term
749  // ends up appearing in the surface jacobian.
750  for (int d=0;d<dim;++d) {
751  phys_unit_normal[iquad][d] = normal[d] / area;
752  }
753  }
754 
755  faceJxW[iquad] = surface_jac_det[iquad] * face_quadrature.weight(iquad);
756  }
757 
758  dealii::FullMatrix<real> interpolation_operator(n_soln_dofs,n_quad_pts);
759  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
760  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
761  interpolation_operator[idof][iquad] = local_solution.finite_element.shape_value(idof,unit_quad_pts[iquad]);
762  }
763  }
764  std::array<dealii::FullMatrix<real2>,dim> gradient_operator;
765  for (int d=0;d<dim;++d) {
766  gradient_operator[d].reinit(dealii::TableIndices<2>(n_soln_dofs, n_quad_pts));
767  }
768  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
769  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
770  if (compute_metric_derivatives) {
771  const dealii::Tensor<1,dim,real> ref_shape_grad = local_solution.finite_element.shape_grad(idof,unit_quad_pts[iquad]);
772  const dealii::Tensor<1,dim,real2> phys_shape_grad = vmult(jac_inv_tran[iquad], ref_shape_grad);
773  for (int d=0;d<dim;++d) {
774  gradient_operator[d][idof][iquad] = phys_shape_grad[d];
775  }
776 
777  // Exact mapping
778  // for (int d=0;d<dim;++d) {
779  // const unsigned int istate = fe_soln.system_to_component_index(idof).first;
780  // gradient_operator[d][idof][iquad] = fe_values_boundary.shape_grad_component(idof, iquad, istate)[d];
781  // }
782  } else {
783  for (int d=0;d<dim;++d) {
784  const unsigned int istate = local_solution.finite_element.system_to_component_index(idof).first;
785  gradient_operator[d][idof][iquad] = fe_values_boundary.shape_grad_component(idof, iquad, istate)[d];
786  }
787  }
788  }
789  }
790 
791 
792  std::vector<State> soln_int = local_solution.evaluate_values(unit_quad_pts);
793  std::vector<State> soln_ext(n_quad_pts);
794  std::vector<DirectionalState> soln_grad_int(n_quad_pts), soln_grad_ext(n_quad_pts);
795 
796  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
797 
798  for (int istate=0; istate<nstate; istate++) {
799  soln_grad_int[iquad][istate] = 0;
800  }
801  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
802  const int istate = fe_values_boundary.get_fe().system_to_component_index(idof).first;
803  for (int d=0;d<dim;++d) {
804  soln_grad_int[iquad][istate][d] += local_solution.coefficients[idof] * gradient_operator[d][idof][iquad];
805  }
806  }
807  }
808 
809  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
810  const dealii::Tensor<1,dim,real2> normal_int = phys_unit_normal[iquad];
811  physics.boundary_face_values (boundary_id, real_quad_pts[iquad], normal_int, soln_int[iquad], soln_grad_int[iquad], soln_ext[iquad], soln_grad_ext[iquad]);
812  }
813 
814  // Assemble BR2 gradient correction right-hand side
815  const dealii::FiniteElement<dim> &base_fe_int = local_solution.finite_element.get_sub_fe(0,1);
816  const unsigned int n_base_dofs_int = base_fe_int.n_dofs_per_cell();
817 
818  std::vector<DirectionalState > soln_grad_correction_int(n_base_dofs_int);
820  if (this->all_parameters->diss_num_flux_type == DissFlux::bassi_rebay_2) {
821 
822  // Obtain solution jump
823  std::vector<DirectionalState> soln_jump_int(n_quad_pts);
824  std::vector<DirectionalState> soln_jump_ext(n_quad_pts);
825  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
826  for (int s=0; s<nstate; s++) {
827  for (int d=0; d<dim; d++) {
828  soln_jump_int[iquad][s][d] = (soln_int[iquad][s] - soln_ext[iquad][s]) * (phys_unit_normal[iquad][d]);
829  soln_jump_ext[iquad][s][d] = (soln_ext[iquad][s] - soln_int[iquad][s]) * (-phys_unit_normal[iquad][d]);
830  }
831  }
832  }
833 
834  std::vector<State> lifting_op_R_rhs_int(n_base_dofs_int);
835  for (unsigned int idof_base=0; idof_base<n_base_dofs_int; ++idof_base) {
836  for (int s=0; s<nstate; s++) {
837 
838  const unsigned int idof = local_solution.finite_element.component_to_system_index(s, idof_base);
839  lifting_op_R_rhs_int[idof_base][s] = 0.0;
840 
841  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
842 
843  for (int d=0; d<dim; ++d) {
844  //const real2 basis_average = gradient_operator[d][idof][iquad];
845  const double basis_average = interpolation_operator[idof][iquad];
846  lifting_op_R_rhs_int[idof_base][s] -= soln_jump_int[iquad][s][d] * basis_average * faceJxW[iquad];
847  }
848  }
849 
850  }
851  }
852  std::vector<State> soln_grad_corr_int(n_base_dofs_int);
853  compute_br2_correction<dim,nstate,real2>(local_solution.finite_element, local_metric, lifting_op_R_rhs_int, soln_grad_corr_int);
854 
855  correct_the_gradient<dim,nstate,real2>( soln_grad_corr_int, local_solution.finite_element, soln_jump_int, interpolation_operator, gradient_operator, soln_grad_int);
856 
857  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
858  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
859  const unsigned int istate = local_solution.finite_element.system_to_component_index(idof).first;
860  const unsigned int idof_base = local_solution.finite_element.system_to_component_index(idof).second;
861  (void) istate;
862  (void) idof_base;
863  for (int d=0;d<dim;++d) {
864  //soln_grad_int[iquad][istate][d] += soln_jump_int[iquad][istate][d];
865  //soln_grad_int[iquad][istate][d] += soln_grad_corr_int[idof_base][istate] * interpolation_operator[idof][iquad];
866  //soln_grad_int[iquad][istate][d] += soln_grad_corr_int[idof_base][istate] * gradient_operator[d][idof][iquad];
867  //soln_grad_ext[iquad][istate][d] -= soln_grad_corr_int[idof_base][istate] * gradient_operator[d][idof][iquad];
868  soln_grad_ext[iquad][istate][d] = soln_grad_int[iquad][istate][d];
869  }
870  }
871  physics.boundary_face_values (boundary_id, real_quad_pts[iquad], phys_unit_normal[iquad], soln_int[iquad], soln_grad_int[iquad], soln_ext[iquad], soln_grad_ext[iquad]);
872  }
873 
874  }
875 
876 
877  std::vector<State> conv_num_flux_dot_n(n_quad_pts);
878  std::vector<State> diss_soln_num_flux(n_quad_pts); // u*
879  std::vector<DirectionalState> diss_flux_jump_int(n_quad_pts); // u*-u_int
880  std::vector<State> diss_auxi_num_flux_dot_n(n_quad_pts); // sigma*
881 
882  //const real2 cell_diameter = fe_values_boundary.get_cell()->diameter();
883  //const real2 artificial_diss_coeff = this->all_parameters->artificial_dissipation_param.add_artificial_dissipation ?
884  // this->discontinuity_sensor(cell_diameter, soln_coeff, fe_values_boundary.get_fe())
885  // : 0.0;
886  const real2 artificial_diss_coeff = this->all_parameters->artificial_dissipation_param.add_artificial_dissipation ?
887  this->artificial_dissipation_coeffs[current_cell_index]
888  : 0.0;
889  (void) artificial_diss_coeff;
890 
891  typename dealii::DoFHandler<dim>::active_cell_iterator artificial_dissipation_cell(
892  this->triangulation.get(), cell->level(), cell->index(), &(this->dof_handler_artificial_dissipation));
893  const unsigned int n_dofs_arti_diss = this->fe_q_artificial_dissipation.dofs_per_cell;
894  std::vector<dealii::types::global_dof_index> dof_indices_artificial_dissipation(n_dofs_arti_diss);
895  artificial_dissipation_cell->get_dof_indices (dof_indices_artificial_dissipation);
896 
897  std::vector<real> artificial_diss_coeff_at_q(n_quad_pts);
898  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
899  artificial_diss_coeff_at_q[iquad] = 0.0;
901  const dealii::Point<dim,real> point = unit_quad_pts[iquad];
902  for (unsigned int idof=0; idof<n_dofs_arti_diss; ++idof) {
903  const unsigned int index = dof_indices_artificial_dissipation[idof];
904  artificial_diss_coeff_at_q[iquad] += this->artificial_dissipation_c0[index] * this->fe_q_artificial_dissipation.shape_value(idof, point);
905  }
906  }
907  artificial_diss_coeff_at_q[iquad] = 0.0;
908  }
909 
910  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
911 
912  const dealii::Tensor<1,dim,real2> normal_int = phys_unit_normal[iquad];
913 
914  // Evaluate physical convective flux, physical dissipative flux
915  // Following the boundary treatment given by
916  // Hartmann, R., Numerical Analysis of Higher Order Discontinuous Galerkin Finite Element Methods,
917  // Institute of Aerodynamics and Flow Technology, DLR (German Aerospace Center), 2008.
918  // Details given on page 93
919  //conv_num_flux_dot_n[iquad] = conv_num_flux_fad_fad->evaluate_flux(soln_ext[iquad], soln_ext[iquad], normal_int);
920 
921  // So, I wasn't able to get Euler manufactured solutions to converge when F* = F*(Ubc, Ubc)
922  // Changing it back to the standdard F* = F*(Uin, Ubc)
923  // This is known not be adjoint consistent as per the paper above. Page 85, second to last paragraph.
924  // Losing 2p+1 OOA on functionals for all PDEs.
925  //conv_num_flux_dot_n[iquad] = conv_num_flux.evaluate_flux(soln_int[iquad], soln_ext[iquad], normal_int);
926  conv_num_flux_dot_n[iquad] = conv_num_flux.evaluate_flux(soln_int[iquad], soln_ext[iquad], normal_int);
927  // Notice that the flux uses the solution given by the Dirichlet or Neumann boundary condition
928  diss_soln_num_flux[iquad] = diss_num_flux.evaluate_solution_flux(soln_ext[iquad], soln_ext[iquad], normal_int);
929 
930  DirectionalState diss_soln_jump_int;
931  for (int s=0; s<nstate; s++) {
932  for (int d=0; d<dim; d++) {
933  diss_soln_jump_int[s][d] = (diss_soln_num_flux[iquad][s] - soln_int[iquad][s]) * normal_int[d];
934  }
935  }
936  diss_flux_jump_int[iquad] = physics.dissipative_flux (soln_int[iquad], diss_soln_jump_int, current_cell_index);
937 
939  const DirectionalState artificial_diss_flux_jump_int = DGBaseState<dim,nstate,real,MeshType>::artificial_dissip->calc_artificial_dissipation_flux(soln_int[iquad], diss_soln_jump_int,artificial_diss_coeff_at_q[iquad]);
940  for (int s=0; s<nstate; s++) {
941  diss_flux_jump_int[iquad][s] += artificial_diss_flux_jump_int[s];
942  }
943  }
944 
945  diss_auxi_num_flux_dot_n[iquad] = diss_num_flux.evaluate_auxiliary_flux(
946  //artificial_diss_coeff,
947  //artificial_diss_coeff,
948  current_cell_index,
949  current_cell_index,
950  artificial_diss_coeff_at_q[iquad],
951  artificial_diss_coeff_at_q[iquad],
952  soln_int[iquad], soln_ext[iquad],
953  soln_grad_int[iquad], soln_grad_ext[iquad],
954  normal_int, penalty, true);
955  }
956 
957  // Applying convection boundary condition
958  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
959 
960  real2 rhs_val = 0.0;
961 
962  const unsigned int istate = fe_values_boundary.get_fe().system_to_component_index(itest).first;
963 
964  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
965 
966  const real2 JxW_iquad = faceJxW[iquad];
967  // Convection
968  rhs_val = rhs_val - interpolation_operator[itest][iquad] * conv_num_flux_dot_n[iquad][istate] * JxW_iquad;
969  // Diffusive
970  rhs_val = rhs_val - interpolation_operator[itest][iquad] * diss_auxi_num_flux_dot_n[iquad][istate] * JxW_iquad;
971  for (int d=0;d<dim;++d) {
972  rhs_val = rhs_val + gradient_operator[d][itest][iquad] * diss_flux_jump_int[iquad][istate][d] * JxW_iquad;
973  }
974  }
975 
976 
977  rhs[itest] = rhs_val;
978  dual_dot_residual += local_dual[itest]*rhs_val;
979  }
980 }
981 
982 #ifdef FADFAD
983 template <int dim, int nstate, typename real, typename MeshType>
985  typename dealii::DoFHandler<dim>::active_cell_iterator /*cell*/,
986  const dealii::types::global_dof_index current_cell_index,
987  const unsigned int face_number,
988  const unsigned int boundary_id,
989  const dealii::FEFaceValuesBase<dim,dim> &fe_values_boundary,
990  const real penalty,
991  const dealii::FESystem<dim,dim> &fe_soln,
992  const dealii::Quadrature<dim-1> &quadrature,
993  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
994  const std::vector<dealii::types::global_dof_index> &soln_dof_indices,
995  dealii::Vector<real> &local_rhs_cell,
996  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
997 {
998  (void) current_cell_index;
999  using adtype = FadFadType;
1000 
1001  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
1002  const unsigned int n_soln_dofs = fe_values_boundary.dofs_per_cell;
1003  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
1004 
1005  (void) compute_dRdW; (void) compute_dRdX; (void) compute_d2R;
1006  const bool compute_metric_derivatives = true;//(!compute_dRdX && !compute_d2R) ? false : true;
1007  AssertDimension (n_soln_dofs, soln_dof_indices.size());
1008 
1009  std::vector< adtype > soln_coeff(n_soln_dofs);
1010  std::vector< adtype > coords_coeff(n_metric_dofs);
1011 
1012  unsigned int w_start, w_end, x_start, x_end;
1013  automatic_differentiation_indexing_1( compute_dRdW, compute_dRdX, compute_d2R,
1014  n_soln_dofs, n_metric_dofs,
1015  w_start, w_end, x_start, x_end );
1016 
1017  unsigned int i_derivative = 0;
1018  const unsigned int n_total_indep = x_end;
1019 
1020  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1021  const real val = this->solution(soln_dof_indices[idof]);
1022  soln_coeff[idof] = val;
1023  soln_coeff[idof].val() = val;
1024 
1025  if (compute_dRdW || compute_d2R) soln_coeff[idof].diff(i_derivative, n_total_indep);
1026  if (compute_d2R) soln_coeff[idof].val().diff(i_derivative, n_total_indep);
1027 
1028  if (compute_dRdW || compute_d2R) i_derivative++;
1029  }
1030  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1031  const real val = this->high_order_grid->volume_nodes[metric_dof_indices[idof]];
1032  coords_coeff[idof] = val;
1033  coords_coeff[idof].val() = val;
1034 
1035  if (compute_dRdX || compute_d2R) coords_coeff[idof].diff(i_derivative, n_total_indep);
1036  if (compute_d2R) coords_coeff[idof].val().diff(i_derivative, n_total_indep);
1037 
1038  if (compute_dRdX || compute_d2R) i_derivative++;
1039  }
1040 
1041  AssertDimension(i_derivative, n_total_indep);
1042 
1043  std::vector<real> local_dual(n_soln_dofs);
1044  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1045  local_dual[itest] = this->dual[soln_dof_indices[itest]];
1046  }
1047 
1049  const auto &conv_num_flux = *(DGBaseState<dim,nstate,real,MeshType>::conv_num_flux_fad_fad);
1050  const auto &diss_num_flux = *(DGBaseState<dim,nstate,real,MeshType>::diss_num_flux_fad_fad);
1051 
1052  std::vector<adtype> rhs(n_soln_dofs);
1053  adtype dual_dot_residual;
1055  cell,
1056  current_cell_index,
1057  soln_coeff,
1058  coords_coeff,
1059  local_dual,
1060  face_number,
1061  boundary_id,
1062  physics,
1063  conv_num_flux,
1064  diss_num_flux,
1065  fe_values_boundary,
1066  penalty,
1067  fe_soln,
1068  fe_metric,
1069  quadrature,
1070  rhs,
1071  dual_dot_residual,
1072  compute_metric_derivatives);
1073 
1074  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1075  local_rhs_cell[itest] += rhs[itest].val().val();
1076  }
1077 
1078  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1079  if (compute_dRdW) {
1080  std::vector<real> residual_derivatives(n_soln_dofs);
1081  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1082  const unsigned int i_dx = idof+w_start;
1083  residual_derivatives[idof] = rhs[itest].dx(i_dx).val();
1084  AssertIsFinite(residual_derivatives[idof]);
1085  }
1086  const bool elide_zero_values = false;
1087  this->system_matrix.add(soln_dof_indices[itest], soln_dof_indices, residual_derivatives, elide_zero_values);
1088  }
1089  if (compute_dRdX) {
1090  std::vector<real> residual_derivatives(n_metric_dofs);
1091  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1092  const unsigned int i_dx = idof+x_start;
1093  residual_derivatives[idof] = rhs[itest].dx(i_dx).val();
1094  }
1095  this->dRdXv.add(soln_dof_indices[itest], metric_dof_indices, residual_derivatives);
1096  }
1097 
1098  }
1099 
1100  if (compute_d2R) {
1101  std::vector<real> dWidW(n_soln_dofs);
1102  std::vector<real> dWidX(n_metric_dofs);
1103  std::vector<real> dXidX(n_metric_dofs);
1104  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
1105 
1106  const unsigned int i_dx = idof+w_start;
1107  const FadType dWi = dual_dot_residual.dx(i_dx);
1108 
1109  for (unsigned int jdof=0; jdof<n_soln_dofs; ++jdof) {
1110  const unsigned int j_dx = jdof+w_start;
1111  dWidW[jdof] = dWi.dx(j_dx);
1112  }
1113  this->d2RdWdW.add(soln_dof_indices[idof], soln_dof_indices, dWidW);
1114 
1115  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
1116  const unsigned int j_dx = jdof+x_start;
1117  dWidX[jdof] = dWi.dx(j_dx);
1118  }
1119  this->d2RdWdX.add(soln_dof_indices[idof], metric_dof_indices, dWidX);
1120  }
1121  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
1122 
1123  const unsigned int i_dx = idof+x_start;
1124  const FadType dXi = dual_dot_residual.dx(i_dx);
1125 
1126  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
1127  const unsigned int j_dx = jdof+x_start;
1128  dXidX[jdof] = dXi.dx(j_dx);
1129  }
1130  this->d2RdXdX.add(metric_dof_indices[idof], metric_dof_indices, dXidX);
1131  }
1132  }
1133 }
1134 #endif
1135 
1136 template <int dim, int nstate, typename real, typename MeshType>
1137 template <typename adtype>
1139  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
1140  const dealii::types::global_dof_index current_cell_index,
1141  const unsigned int face_number,
1142  const unsigned int boundary_id,
1143  const dealii::FEFaceValuesBase<dim,dim> &fe_values_boundary,
1144  const real penalty,
1145  const dealii::FESystem<dim,dim> &fe_soln,
1146  const dealii::Quadrature<dim-1> &quadrature,
1147  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
1148  const std::vector<dealii::types::global_dof_index> &soln_dof_indices,
1152  dealii::Vector<real> &local_rhs_cell,
1153  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
1154 {
1155  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
1156  const unsigned int n_soln_dofs = fe_values_boundary.dofs_per_cell;
1157  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
1158 
1159  (void) compute_dRdW; (void) compute_dRdX; (void) compute_d2R;
1160  const bool compute_metric_derivatives = true;//(!compute_dRdX && !compute_d2R) ? false : true;
1161  AssertDimension (n_soln_dofs, soln_dof_indices.size());
1162 
1163  LocalSolution<adtype, dim, nstate> local_solution(fe_soln);
1164  LocalSolution<adtype, dim, dim> local_metric(fe_metric);
1165 
1166  unsigned int w_start, w_end, x_start, x_end;
1167  automatic_differentiation_indexing_1( compute_dRdW, compute_dRdX, compute_d2R,
1168  n_soln_dofs, n_metric_dofs,
1169  w_start, w_end, x_start, x_end );
1170 
1171  using TH = codi::TapeHelper<adtype>;
1172  TH th;
1173  adtype::getGlobalTape();
1174  if (compute_dRdW || compute_dRdX || compute_d2R) {
1175  th.startRecording();
1176  }
1177  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1178  const real val = this->solution(soln_dof_indices[idof]);
1179  local_solution.coefficients[idof] = val;
1180 
1181  if (compute_dRdW || compute_d2R) {
1182  th.registerInput(local_solution.coefficients[idof]);
1183  } else {
1184  adtype::getGlobalTape().deactivateValue(local_solution.coefficients[idof]);
1185  }
1186  }
1187  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1188  const real val = this->high_order_grid->volume_nodes[metric_dof_indices[idof]];
1189  local_metric.coefficients[idof] = val;
1190 
1191  if (compute_dRdX || compute_d2R) {
1192  th.registerInput(local_metric.coefficients[idof]);
1193  } else {
1194  adtype::getGlobalTape().deactivateValue(local_metric.coefficients[idof]);
1195  }
1196  }
1197 
1198  std::vector<real> local_dual(n_soln_dofs);
1199  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1200  local_dual[itest] = this->dual[soln_dof_indices[itest]];
1201  }
1202 
1203  std::vector<adtype> rhs(n_soln_dofs);
1204  adtype dual_dot_residual;
1206  cell,
1207  current_cell_index,
1208  local_solution,
1209  local_metric,
1210  local_dual,
1211  face_number,
1212  boundary_id,
1213  physics,
1214  conv_num_flux,
1215  diss_num_flux,
1216  fe_values_boundary,
1217  penalty,
1218  quadrature,
1219  rhs,
1220  dual_dot_residual,
1221  compute_metric_derivatives);
1222 
1223  if (compute_dRdW || compute_dRdX) {
1224  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1225  th.registerOutput(rhs[itest]);
1226  }
1227  } else if (compute_d2R) {
1228  th.registerOutput(dual_dot_residual);
1229  }
1230  if (compute_dRdW || compute_dRdX || compute_d2R) {
1231  th.stopRecording();
1232  }
1233 
1234  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1235  local_rhs_cell(itest) += getValue<adtype>(rhs[itest]);
1236  AssertIsFinite(local_rhs_cell(itest));
1237  }
1238 
1239  if (compute_dRdW) {
1240  typename TH::JacobianType& jac = th.createJacobian();
1241  th.evalJacobian(jac);
1242  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1243 
1244  std::vector<real> residual_derivatives(n_soln_dofs);
1245  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1246  const unsigned int i_dx = idof+w_start;
1247  residual_derivatives[idof] = jac(itest,i_dx);
1248  AssertIsFinite(residual_derivatives[idof]);
1249  }
1250  const bool elide_zero_values = false;
1251  this->system_matrix.add(soln_dof_indices[itest], soln_dof_indices, residual_derivatives, elide_zero_values);
1252  }
1253  th.deleteJacobian(jac);
1254 
1255  }
1256 
1257  if (compute_dRdX) {
1258  typename TH::JacobianType& jac = th.createJacobian();
1259  th.evalJacobian(jac);
1260  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1261  std::vector<real> residual_derivatives(n_metric_dofs);
1262  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1263  const unsigned int i_dx = idof+x_start;
1264  residual_derivatives[idof] = jac(itest,i_dx);
1265  }
1266  this->dRdXv.add(soln_dof_indices[itest], metric_dof_indices, residual_derivatives);
1267  }
1268  th.deleteJacobian(jac);
1269  }
1270 
1271 
1272  if (compute_d2R) {
1273  typename TH::HessianType& hes = th.createHessian();
1274  th.evalHessian(hes);
1275 
1276  int i_dependent = (compute_dRdW || compute_dRdX) ? n_soln_dofs : 0;
1277 
1278  std::vector<real> dWidW(n_soln_dofs);
1279  std::vector<real> dWidX(n_metric_dofs);
1280  std::vector<real> dXidX(n_metric_dofs);
1281 
1282  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
1283 
1284  const unsigned int i_dx = idof+w_start;
1285 
1286  for (unsigned int jdof=0; jdof<n_soln_dofs; ++jdof) {
1287  const unsigned int j_dx = jdof+w_start;
1288  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
1289  }
1290  this->d2RdWdW.add(soln_dof_indices[idof], soln_dof_indices, dWidW);
1291 
1292  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
1293  const unsigned int j_dx = jdof+x_start;
1294  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
1295  }
1296  this->d2RdWdX.add(soln_dof_indices[idof], metric_dof_indices, dWidX);
1297  }
1298 
1299  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
1300 
1301  const unsigned int i_dx = idof+x_start;
1302 
1303  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
1304  const unsigned int j_dx = jdof+x_start;
1305  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
1306  }
1307  this->d2RdXdX.add(metric_dof_indices[idof], metric_dof_indices, dXidX);
1308  }
1309 
1310  th.deleteHessian(hes);
1311  }
1312  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1313  adtype::getGlobalTape().deactivateValue(local_solution.coefficients[idof]);
1314  }
1315  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1316  adtype::getGlobalTape().deactivateValue(local_metric.coefficients[idof]);
1317  }
1318 
1319 }
1320 
1321 template <int dim, int nstate, typename real, typename MeshType>
1323  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
1324  const dealii::types::global_dof_index current_cell_index,
1325  const unsigned int face_number,
1326  const unsigned int boundary_id,
1327  const dealii::FEFaceValuesBase<dim,dim> &fe_values_boundary,
1328  const real penalty,
1329  const dealii::FESystem<dim,dim> &fe_soln,
1330  const dealii::Quadrature<dim-1> &quadrature,
1331  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
1332  const std::vector<dealii::types::global_dof_index> &soln_dof_indices,
1336  dealii::Vector<real> &local_rhs_cell,
1337  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
1338 {
1339  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
1340  const unsigned int n_soln_dofs = fe_values_boundary.dofs_per_cell;
1341  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
1342 
1343  (void) compute_dRdW;
1344  (void) compute_dRdX;
1345  (void) compute_d2R;
1346 
1347  const bool compute_metric_derivatives = true; //= (!compute_dRdX && !compute_d2R) ? false : true;
1348  AssertDimension (n_soln_dofs, soln_dof_indices.size());
1349 
1350  LocalSolution<real, dim, nstate> local_solution(fe_soln);
1351  LocalSolution<real, dim, dim> local_metric(fe_metric);
1352 
1353  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
1354  const real val = this->solution(soln_dof_indices[idof]);
1355  local_solution.coefficients[idof] = val;
1356  }
1357  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
1358  const real val = this->high_order_grid->volume_nodes[metric_dof_indices[idof]];
1359  local_metric.coefficients[idof] = val;
1360  }
1361 
1362  std::vector<real> local_dual(n_soln_dofs);
1363  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1364  local_dual[itest] = this->dual[soln_dof_indices[itest]];
1365  }
1366 
1367  std::vector<real> rhs(n_soln_dofs);
1368  real dual_dot_residual;
1370  cell,
1371  current_cell_index,
1372  local_solution,
1373  local_metric,
1374  local_dual,
1375  face_number,
1376  boundary_id,
1377  physics,
1378  conv_num_flux,
1379  diss_num_flux,
1380  fe_values_boundary,
1381  penalty,
1382  quadrature,
1383  rhs,
1384  dual_dot_residual,
1385  compute_metric_derivatives);
1386 
1387  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
1388  local_rhs_cell(itest) += getValue<real>(rhs[itest]);
1389  AssertIsFinite(local_rhs_cell(itest));
1390  }
1391 
1392 }
1393 
1394 #ifndef FADFAD
1395 template <int dim, int nstate, typename real, typename MeshType>
1397  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
1398  const dealii::types::global_dof_index current_cell_index,
1399  const unsigned int face_number,
1400  const unsigned int boundary_id,
1401  const dealii::FEFaceValuesBase<dim,dim> &fe_values_boundary,
1402  const real penalty,
1403  const dealii::FESystem<dim,dim> &fe_soln,
1404  const dealii::Quadrature<dim-1> &quadrature,
1405  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
1406  const std::vector<dealii::types::global_dof_index> &soln_dof_indices,
1407  dealii::Vector<real> &local_rhs_cell,
1408  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
1409 {
1410  (void) current_cell_index;
1411  if (compute_d2R) {
1412  assemble_boundary_codi_taped_derivatives<codi_HessianComputationType>(
1413  cell,
1414  current_cell_index,
1415  face_number,
1416  boundary_id,
1417  fe_values_boundary,
1418  penalty,
1419  fe_soln,
1420  quadrature,
1421  metric_dof_indices,
1422  soln_dof_indices,
1426  local_rhs_cell,
1427  compute_dRdW, compute_dRdX, compute_d2R);
1428  } else if (compute_dRdW || compute_dRdX) {
1429  assemble_boundary_codi_taped_derivatives<codi_JacobianComputationType>(
1430  cell,
1431  current_cell_index,
1432  face_number,
1433  boundary_id,
1434  fe_values_boundary,
1435  penalty,
1436  fe_soln,
1437  quadrature,
1438  metric_dof_indices,
1439  soln_dof_indices,
1443  local_rhs_cell,
1444  compute_dRdW, compute_dRdX, compute_d2R);
1445  } else {
1447  cell,
1448  current_cell_index,
1449  face_number,
1450  boundary_id,
1451  fe_values_boundary,
1452  penalty,
1453  fe_soln,
1454  quadrature,
1455  metric_dof_indices,
1456  soln_dof_indices,
1460  local_rhs_cell,
1461  compute_dRdW, compute_dRdX, compute_d2R);
1462  }
1463 }
1464 #endif
1465 
1466 
1467 
1468 template<int dim>
1469 dealii::Quadrature<dim> project_face_quadrature(
1470  const dealii::Quadrature<dim - 1> &face_quadrature_lower_dim, const std::pair<unsigned int, int> face_subface_pair,
1471  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set) {
1472  dealii::Quadrature<dim> face_quadrature;
1473 
1474  if constexpr (dim == 3) {
1475  const dealii::Quadrature<dim> all_faces_quad =
1476  face_subface_pair.second == -1 ? dealii::QProjector<dim>::project_to_all_faces(
1477  dealii::ReferenceCell::get_hypercube(dim), face_quadrature_lower_dim)
1478  : dealii::QProjector<dim>::project_to_all_subfaces(
1479  dealii::ReferenceCell::get_hypercube(dim), face_quadrature_lower_dim);
1480  const unsigned int n_face_quad_pts = face_quadrature_lower_dim.size();
1481  std::vector<dealii::Point<dim>> points(n_face_quad_pts);
1482  std::vector<double> weights(n_face_quad_pts);
1483  for (unsigned int iquad = 0; iquad < n_face_quad_pts; ++iquad) {
1484  points[iquad] = all_faces_quad.point(iquad + face_data_set);
1485  weights[iquad] = all_faces_quad.weight(iquad + face_data_set);
1486  }
1487  face_quadrature = dealii::Quadrature<dim>(points, weights);
1488 
1489  } else {
1490  (void) face_data_set;
1491  if (face_subface_pair.second == -1) {
1492  face_quadrature = dealii::QProjector<dim>::project_to_face(
1493  dealii::ReferenceCell::get_hypercube(dim), face_quadrature_lower_dim, face_subface_pair.first);
1494  } else {
1495  face_quadrature = dealii::QProjector<dim>::project_to_subface(
1496  dealii::ReferenceCell::get_hypercube(dim), face_quadrature_lower_dim, face_subface_pair.first,
1497  face_subface_pair.second, dealii::RefinementCase<dim - 1>::isotropic_refinement);
1498  }
1499  }
1500  return face_quadrature;
1501 }
1502 
1503 template <int dim, int nstate, typename real, typename MeshType>
1504 template <typename real2>
1506  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
1507  const dealii::types::global_dof_index current_cell_index,
1508  const dealii::types::global_dof_index neighbor_cell_index,
1509  const LocalSolution<real2, dim, nstate> &soln_int,
1510  const LocalSolution<real2, dim, nstate> &soln_ext,
1511  const LocalSolution<real2, dim, dim> &metric_int,
1512  const LocalSolution<real2, dim, dim> &metric_ext,
1513  const std::vector< double > &dual_int,
1514  const std::vector< double > &dual_ext,
1515  const std::pair<unsigned int, int> face_subface_int,
1516  const std::pair<unsigned int, int> face_subface_ext,
1517  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_int,
1518  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_ext,
1522  const dealii::FEFaceValuesBase<dim,dim> &fe_values_int,
1523  const dealii::FEFaceValuesBase<dim,dim> &fe_values_ext,
1524  const real penalty,
1525  const dealii::Quadrature<dim-1> &face_quadrature,
1526  std::vector<real2> &rhs_int,
1527  std::vector<real2> &rhs_ext,
1528  real2 &dual_dot_residual,
1529  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
1530 {
1531  (void) compute_dRdW;
1532  const unsigned int n_soln_dofs_int = soln_int.finite_element.dofs_per_cell;
1533  const unsigned int n_soln_dofs_ext = soln_ext.finite_element.dofs_per_cell;
1534  const unsigned int n_face_quad_pts = face_quadrature.size();
1535 
1536  dual_dot_residual = 0.0;
1537  for (unsigned int itest=0; itest<n_soln_dofs_int; ++itest) {
1538  rhs_int[itest] = 0.0;
1539  }
1540  for (unsigned int itest=0; itest<n_soln_dofs_ext; ++itest) {
1541  rhs_ext[itest] = 0.0;
1542  }
1543 
1544  using State = State<real2, nstate>;
1545  using DirectionalState = DirectionalState<real2, dim, nstate>;
1546  using Tensor1D = dealii::Tensor<1,dim,real2>;
1547  using Tensor2D = dealii::Tensor<2,dim,real2>;
1548 
1549  dealii::Quadrature<dim> face_quadrature_int = project_face_quadrature<dim>(face_quadrature, face_subface_int, face_data_set_int);
1550  dealii::Quadrature<dim> face_quadrature_ext = project_face_quadrature<dim>(face_quadrature, face_subface_ext, face_data_set_ext);
1551 
1552  (void) compute_dRdW; (void) compute_dRdX; (void) compute_d2R;
1553  const bool compute_metric_derivatives = true; //(!compute_dRdX && !compute_d2R) ? false : true;
1554 
1555  const std::vector<dealii::Point<dim,double>> &unit_quad_pts_int = face_quadrature_int.get_points();
1556  const std::vector<dealii::Point<dim,double>> &unit_quad_pts_ext = face_quadrature_ext.get_points();
1557 
1558 
1559 
1560  // Use the metric Jacobian from the interior cell
1561  std::vector<Tensor2D> metric_jac_int = evaluate_metric_jacobian (unit_quad_pts_int, metric_int);
1562  std::vector<Tensor2D> metric_jac_ext = evaluate_metric_jacobian (unit_quad_pts_ext, metric_ext);
1563 
1564  const dealii::Tensor<1,dim,real> unit_normal_int = dealii::GeometryInfo<dim>::unit_normal_vector[face_subface_int.first];
1565  const dealii::Tensor<1,dim,real> unit_normal_ext = dealii::GeometryInfo<dim>::unit_normal_vector[face_subface_ext.first];
1566 
1567  // Use quadrature points of neighbor cell
1568  // Might want to use the maximum n_quad_pts1 and n_quad_pts2
1569  //const unsigned int n_face_quad_pts = fe_values_ext.n_quadrature_points;
1570 
1571  //const real2 cell_diameter_int = fe_values_int.get_cell()->diameter();
1572  //const real2 cell_diameter_ext = fe_values_ext.get_cell()->diameter();
1573  //const real2 artificial_diss_coeff_int = this->all_parameters->artificial_dissipation_param.add_artificial_dissipation ?
1574  // this->discontinuity_sensor(cell_diameter_int, soln_int.coefficients, fe_values_int.get_fe())
1575  // : 0.0;
1576  //const real2 artificial_diss_coeff_ext = this->all_parameters->artificial_dissipation_param.add_artificial_dissipation ?
1577  // this->discontinuity_sensor(cell_diameter_ext, soln_ext.coefficients, fe_values_ext.get_fe())
1578  // : 0.0;
1579  const real2 artificial_diss_coeff_int = this->all_parameters->artificial_dissipation_param.add_artificial_dissipation ?
1580  this->artificial_dissipation_coeffs[current_cell_index]
1581  : 0.0;
1582  const real2 artificial_diss_coeff_ext = this->all_parameters->artificial_dissipation_param.add_artificial_dissipation ?
1583  this->artificial_dissipation_coeffs[neighbor_cell_index]
1584  : 0.0;
1585 
1586  (void) artificial_diss_coeff_int;
1587  (void) artificial_diss_coeff_ext;
1588  typename dealii::DoFHandler<dim>::active_cell_iterator artificial_dissipation_cell(
1589  this->triangulation.get(), cell->level(), cell->index(), &(this->dof_handler_artificial_dissipation));
1590  const unsigned int n_dofs_arti_diss = this->fe_q_artificial_dissipation.dofs_per_cell;
1591  std::vector<dealii::types::global_dof_index> dof_indices_artificial_dissipation(n_dofs_arti_diss);
1592  artificial_dissipation_cell->get_dof_indices (dof_indices_artificial_dissipation);
1593 
1594  std::vector<real> artificial_diss_coeff_at_q(n_face_quad_pts);
1595  for (unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
1596  artificial_diss_coeff_at_q[iquad] = 0.0;
1597 
1599  const dealii::Point<dim,real> point = unit_quad_pts_int[iquad];
1600  for (unsigned int idof=0; idof<n_dofs_arti_diss; ++idof) {
1601  const unsigned int index = dof_indices_artificial_dissipation[idof];
1602  artificial_diss_coeff_at_q[iquad] += this->artificial_dissipation_c0[index] * this->fe_q_artificial_dissipation.shape_value(idof, point);
1603  }
1604  }
1605  artificial_diss_coeff_at_q[iquad] = 0.0;
1606  }
1607 
1608  std::vector<real2> jacobian_determinant_int(n_face_quad_pts);
1609  std::vector<real2> jacobian_determinant_ext(n_face_quad_pts);
1610  std::vector<Tensor2D> jacobian_transpose_inverse_int(n_face_quad_pts);
1611  std::vector<Tensor2D> jacobian_transpose_inverse_ext(n_face_quad_pts);
1612 
1613  for (unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
1614  if (compute_metric_derivatives) {
1615  jacobian_determinant_int[iquad] = dealii::determinant(metric_jac_int[iquad]);
1616  jacobian_determinant_ext[iquad] = dealii::determinant(metric_jac_ext[iquad]);
1617 
1618  jacobian_transpose_inverse_int[iquad] = dealii::transpose(dealii::invert(metric_jac_int[iquad]));
1619  jacobian_transpose_inverse_ext[iquad] = dealii::transpose(dealii::invert(metric_jac_ext[iquad]));
1620  }
1621  }
1622 
1623 #ifdef KOPRIVA_METRICS_FACE
1624  auto old_jacobian_determinant_int = jacobian_determinant_int;
1625  auto old_jacobian_determinant_ext = jacobian_determinant_ext;
1626  auto old_jacobian_transpose_inverse_int = jacobian_transpose_inverse_int;
1627  auto old_jacobian_transpose_inverse_ext = jacobian_transpose_inverse_ext;
1628 
1629  if constexpr (dim != 1) {
1630  evaluate_covariant_metric_jacobian<dim,real2> ( face_quadrature_int, metric_int, jacobian_transpose_inverse_int, jacobian_determinant_int);
1631  evaluate_covariant_metric_jacobian<dim,real2> ( face_quadrature_ext, metric_ext, jacobian_transpose_inverse_ext, jacobian_determinant_ext);
1632  }
1633 #endif
1634 
1635  // Note: This is ignored when use_periodic_bc is set to true -- this variable has no other function when dim!=1
1636  if(this->all_parameters->use_periodic_bc == false) {
1637  check_same_coords<dim,real2>(unit_quad_pts_int, unit_quad_pts_ext, metric_int, metric_ext, 1e-10);
1638  }
1639 
1640  // Compute metrics
1641  std::vector<Tensor1D> phys_unit_normal_int(n_face_quad_pts), phys_unit_normal_ext(n_face_quad_pts);
1642  std::vector<real2> surface_jac_det(n_face_quad_pts);
1643  std::vector<real2> faceJxW(n_face_quad_pts);
1644 
1645  dealii::FullMatrix<real> interpolation_operator_int(n_soln_dofs_int, n_face_quad_pts);
1646  dealii::FullMatrix<real> interpolation_operator_ext(n_soln_dofs_ext, n_face_quad_pts);
1647  std::array<dealii::FullMatrix<real2>,dim> gradient_operator_int, gradient_operator_ext;
1648  for (int d=0;d<dim;++d) {
1649  gradient_operator_int[d].reinit(dealii::TableIndices<2>(n_soln_dofs_int, n_face_quad_pts));
1650  gradient_operator_ext[d].reinit(dealii::TableIndices<2>(n_soln_dofs_ext, n_face_quad_pts));
1651  }
1652 
1653  for (unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
1654 
1655  real2 surface_jac_det_int, surface_jac_det_ext;
1656 
1657  if (compute_metric_derivatives) {
1658 
1659  const real2 jac_det_int = jacobian_determinant_int[iquad];
1660  const real2 jac_det_ext = jacobian_determinant_ext[iquad];
1661 
1662  const Tensor2D jac_inv_tran_int = jacobian_transpose_inverse_int[iquad];
1663  const Tensor2D jac_inv_tran_ext = jacobian_transpose_inverse_ext[iquad];
1664 
1665  const Tensor1D normal_int = vmult(jac_inv_tran_int, unit_normal_int);
1666  const Tensor1D normal_ext = vmult(jac_inv_tran_ext, unit_normal_ext);
1667  const real2 area_int = norm(normal_int);
1668  const real2 area_ext = norm(normal_ext);
1669 
1670  // Technically the normals have jac_det multiplied.
1671  // However, we use normalized normals by convention, so the term
1672  // ends up appearing in the surface jacobian.
1673 
1674  for (int d=0;d<dim;++d) {
1675  phys_unit_normal_int[iquad][d] = normal_int[d] / area_int;
1676  }
1677  for (int d=0;d<dim;++d) {
1678  phys_unit_normal_ext[iquad][d] = normal_ext[d] / area_ext;
1679  }
1680 
1681  surface_jac_det_int = area_int*jac_det_int;
1682  surface_jac_det_ext = area_ext*jac_det_ext;
1683 
1684 
1685  if (std::is_same<double,real2>::value) {
1686  bool valid_metrics = true;
1687  // surface_jac_det is the 'volume' compression/expansion of the face w.r.t. the reference cell,
1688  // analogous to volume jacobian determinant.
1689  //
1690  // When the cells have the same coarseness, their surface Jacobians must be the same.
1691  //
1692  // When the cells do not have the same coarseness, their surface Jacobians will not be the same.
1693  // Therefore, we must use the Jacobians coming from the smaller face since it accurately represents
1694  // the surface area being integrated.
1695  if (face_subface_int.second == -1 && face_subface_ext.second == -1) {
1696  if(abs(surface_jac_det_int-surface_jac_det_ext) > this->all_parameters->matching_surface_jac_det_tolerance) {
1697  pcout << std::endl;
1698  pcout << "iquad " << iquad << " Non-matching surface jacobians, int = "
1699  << surface_jac_det_int << ", ext = " << surface_jac_det_ext << ", diff = "
1700  << abs(surface_jac_det_int-surface_jac_det_ext) << std::endl;
1701 
1702  assert(abs(surface_jac_det_int-surface_jac_det_ext) < this->all_parameters->matching_surface_jac_det_tolerance);
1703  valid_metrics = false;
1704  }
1705  }
1706  real2 diff_norm = 0;
1707  for (int d=0;d<dim;++d) {
1708  const real2 diff = phys_unit_normal_int[iquad][d]+phys_unit_normal_ext[iquad][d];
1709  diff_norm += diff*diff;
1710  }
1711  diff_norm = sqrt(diff_norm);
1712  if (diff_norm > 1e-10) {
1713  std::cout << std::setprecision(std::numeric_limits<long double>::digits10 + 1);
1714  std::cout << "Non-matching normals. Error norm: " << diff_norm << std::endl;
1715  for (int d=0;d<dim;++d) {
1716  //assert(abs(phys_unit_normal_int[iquad][d]+phys_unit_normal_ext[iquad][d]) < 1e-10);
1717  std::cout << " normal_int["<<d<<"] : " << phys_unit_normal_int[iquad][d]
1718  << " normal_ext["<<d<<"] : " << phys_unit_normal_ext[iquad][d]
1719  << std::endl;
1720  }
1721  valid_metrics = false;
1722  }
1723  if (!valid_metrics) {
1724  //for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
1725  // rhs_int[itest_int] += 1e20;
1726  //}
1727  //for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
1728  // rhs_ext[itest_ext] += 1e20;
1729  //}
1730  }
1731 
1732  }
1733  //phys_unit_normal_ext[iquad] = -phys_unit_normal_int[iquad];//normal_ext / area_ext; Must use opposite normal to be consistent with explicit
1734 
1735  for (unsigned int idof=0; idof<n_soln_dofs_int; ++idof) {
1736  interpolation_operator_int[idof][iquad] = soln_int.finite_element.shape_value(idof,unit_quad_pts_int[iquad]);
1737  dealii::Tensor<1,dim,real> ref_shape_grad = soln_int.finite_element.shape_grad(idof,unit_quad_pts_int[iquad]);
1738  const Tensor1D phys_shape_grad = vmult(jac_inv_tran_int, ref_shape_grad);
1739  for (int d=0;d<dim;++d) {
1740  gradient_operator_int[d][idof][iquad] = phys_shape_grad[d];
1741  }
1742  }
1743  for (unsigned int idof=0; idof<n_soln_dofs_ext; ++idof) {
1744  interpolation_operator_ext[idof][iquad] = soln_ext.finite_element.shape_value(idof,unit_quad_pts_ext[iquad]);
1745  dealii::Tensor<1,dim,real> ref_shape_grad = soln_ext.finite_element.shape_grad(idof,unit_quad_pts_ext[iquad]);
1746  const Tensor1D phys_shape_grad = vmult(jac_inv_tran_ext, ref_shape_grad);
1747  for (int d=0;d<dim;++d) {
1748  gradient_operator_ext[d][idof][iquad] = phys_shape_grad[d];
1749  }
1750  }
1751 
1752  } else {
1753  for (unsigned int idof=0; idof<n_soln_dofs_int; ++idof) {
1754  interpolation_operator_int[idof][iquad] = soln_int.finite_element.shape_value(idof,unit_quad_pts_int[iquad]);
1755  }
1756  for (unsigned int idof=0; idof<n_soln_dofs_ext; ++idof) {
1757  interpolation_operator_ext[idof][iquad] = soln_ext.finite_element.shape_value(idof,unit_quad_pts_ext[iquad]);
1758  }
1759  for (int d=0;d<dim;++d) {
1760  for (unsigned int idof=0; idof<n_soln_dofs_int; ++idof) {
1761  const unsigned int istate = soln_int.finite_element.system_to_component_index(idof).first;
1762  gradient_operator_int[d][idof][iquad] = fe_values_int.shape_grad_component(idof, iquad, istate)[d];
1763  }
1764  for (unsigned int idof=0; idof<n_soln_dofs_ext; ++idof) {
1765  const unsigned int istate = soln_ext.finite_element.system_to_component_index(idof).first;
1766  gradient_operator_ext[d][idof][iquad] = fe_values_ext.shape_grad_component(idof, iquad, istate)[d];
1767  }
1768  }
1769  surface_jac_det_int = fe_values_int.JxW(iquad)/face_quadrature_int.weight(iquad);
1770  surface_jac_det_ext = fe_values_ext.JxW(iquad)/face_quadrature_ext.weight(iquad);
1771 
1772  phys_unit_normal_int[iquad] = fe_values_int.normal_vector(iquad);
1773  phys_unit_normal_ext[iquad] = -phys_unit_normal_int[iquad]; // Must use opposite normal to be consistent with explicit
1774  }
1775  // When the cells do not have the same coarseness, their surface Jacobians will not be the same.
1776  // Therefore, we must use the Jacobians coming from the smaller face since it accurately represents
1777  // the surface area being computed.
1778  //
1779  // Note that it is possible for the smaller cell to have larger surface Jacobians than the larger cell,
1780  // but not at the same physical location.
1781  if ( surface_jac_det_int > surface_jac_det_ext) {
1782  // Interior is the large face.
1783  // Exterior is the small face.
1784  surface_jac_det[iquad] = surface_jac_det_ext;
1785  //phys_unit_normal_ext[iquad] = -phys_unit_normal_int[iquad];
1786  } else {
1787  // Exterior is the large face.
1788  // Interior is the small face.
1789  surface_jac_det[iquad] = surface_jac_det_int;
1790  //phys_unit_normal_int[iquad] = -phys_unit_normal_ext[iquad];
1791  }
1792 
1793  faceJxW[iquad] = surface_jac_det[iquad] * face_quadrature_int.weight(iquad);
1794  }
1795 
1796 
1797  // Interpolate solution
1798  std::vector<State> soln_int_at_q = soln_int.evaluate_values(unit_quad_pts_int);
1799  std::vector<State> soln_ext_at_q = soln_ext.evaluate_values(unit_quad_pts_ext);
1800 
1801  // Interpolate solution gradient
1802  std::vector<DirectionalState> soln_grad_int(n_face_quad_pts), soln_grad_ext(n_face_quad_pts);
1803  for (unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
1804 
1805  for (int istate=0; istate<nstate; istate++) {
1806  soln_grad_int[iquad][istate] = 0;
1807  soln_grad_ext[iquad][istate] = 0;
1808  }
1809 
1810  for (unsigned int idof=0; idof<n_soln_dofs_int; ++idof) {
1811  const unsigned int istate = soln_int.finite_element.system_to_component_index(idof).first;
1812  for (int d=0;d<dim;++d) {
1813  soln_grad_int[iquad][istate][d] += soln_int.coefficients[idof] * gradient_operator_int[d][idof][iquad];
1814  }
1815  }
1816  for (unsigned int idof=0; idof<n_soln_dofs_ext; ++idof) {
1817  const unsigned int istate = soln_ext.finite_element.system_to_component_index(idof).first;
1818  for (int d=0;d<dim;++d) {
1819  soln_grad_ext[iquad][istate][d] += soln_ext.coefficients[idof] * gradient_operator_ext[d][idof][iquad];
1820  }
1821  }
1822  }
1823 
1824  // Assemble BR2 gradient correction right-hand side
1825 
1827  if (this->all_parameters->diss_num_flux_type == DissFlux::bassi_rebay_2) {
1828 
1829  const dealii::FiniteElement<dim> &base_fe_int = soln_int.finite_element.get_sub_fe(0,1);
1830  const dealii::FiniteElement<dim> &base_fe_ext = soln_ext.finite_element.get_sub_fe(0,1);
1831  const unsigned int n_base_dofs_int = base_fe_int.n_dofs_per_cell();
1832  const unsigned int n_base_dofs_ext = base_fe_ext.n_dofs_per_cell();
1833 
1834  // Obtain solution jump
1835  std::vector<DirectionalState> soln_jump_int(n_face_quad_pts);
1836  std::vector<DirectionalState> soln_jump_ext(n_face_quad_pts);
1837  for (unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
1838  for (int s=0; s<nstate; s++) {
1839  for (int d=0; d<dim; d++) {
1840  soln_jump_int[iquad][s][d] = (soln_int_at_q[iquad][s] - soln_ext_at_q[iquad][s]) * phys_unit_normal_int[iquad][d];
1841  soln_jump_ext[iquad][s][d] = (soln_ext_at_q[iquad][s] - soln_int_at_q[iquad][s]) * (-phys_unit_normal_int[iquad][d]);
1842  }
1843  }
1844  }
1845 
1846 
1847  // RHS of R lifting operator.
1848  std::vector<State> lifting_op_R_rhs_int(n_base_dofs_int);
1849  for (unsigned int idof_base=0; idof_base<n_base_dofs_int; ++idof_base) {
1850  for (int s=0; s<nstate; s++) {
1851 
1852  const unsigned int idof = soln_int.finite_element.component_to_system_index(s, idof_base);
1853  lifting_op_R_rhs_int[idof_base][s] = 0.0;
1854 
1855  for (unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
1856 
1857  for (int d=0; d<dim; ++d) {
1858  //const real2 basis_average = 0.5 * (gradient_operator_int[d][idof][iquad] + 0.0);
1859  const double basis_average = 0.5 * (interpolation_operator_int[idof][iquad] + 0.0);
1860  lifting_op_R_rhs_int[idof_base][s] -= soln_jump_int[iquad][s][d] * basis_average * faceJxW[iquad];
1861  }
1862  }
1863 
1864  }
1865  }
1866 
1867  std::vector<State> lifting_op_R_rhs_ext(n_base_dofs_ext);
1868  for (unsigned int idof_base=0; idof_base<n_base_dofs_ext; ++idof_base) {
1869  for (int s=0; s<nstate; s++) {
1870 
1871  const unsigned int idof = soln_ext.finite_element.component_to_system_index(s, idof_base);
1872  lifting_op_R_rhs_ext[idof_base][s] = 0.0;
1873 
1874  for (unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
1875 
1876  for (int d=0; d<dim; ++d) {
1877  //const real2 basis_average = 0.5 * ( 0.0 + gradient_operator_ext[d][idof][iquad] );
1878  const double basis_average = 0.5 * ( 0.0 + interpolation_operator_ext[idof][iquad] );
1879  lifting_op_R_rhs_ext[idof_base][s] -= soln_jump_ext[iquad][s][d] * basis_average * faceJxW[iquad];
1880  }
1881  }
1882 
1883  }
1884  }
1885 
1886  std::vector<State> soln_grad_corr_int(n_base_dofs_int), soln_grad_corr_ext(n_base_dofs_ext);
1887  compute_br2_correction<dim,nstate,real2>(soln_int.finite_element, metric_int, lifting_op_R_rhs_int, soln_grad_corr_int);
1888  compute_br2_correction<dim,nstate,real2>(soln_ext.finite_element, metric_ext, lifting_op_R_rhs_ext, soln_grad_corr_ext);
1889 
1890  correct_the_gradient<dim,nstate,real2>( soln_grad_corr_int, soln_int.finite_element, soln_jump_int, interpolation_operator_int, gradient_operator_int, soln_grad_int);
1891  correct_the_gradient<dim,nstate,real2>( soln_grad_corr_ext, soln_ext.finite_element, soln_jump_ext, interpolation_operator_ext, gradient_operator_ext, soln_grad_ext);
1892 
1893  }
1894 
1895 
1896  State conv_num_flux_dot_n;
1897  State diss_soln_num_flux; // u*
1898  State diss_auxi_num_flux_dot_n; // sigma*
1899 
1900  DirectionalState diss_flux_jump_int; // u*-u_int
1901  DirectionalState diss_flux_jump_ext; // u*-u_ext
1902 
1903  for (unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
1904 
1905  // Evaluate physical convective flux, physical dissipative flux, and source term
1906  conv_num_flux_dot_n = conv_num_flux.evaluate_flux(soln_int_at_q[iquad], soln_ext_at_q[iquad], phys_unit_normal_int[iquad]);
1907  diss_soln_num_flux = diss_num_flux.evaluate_solution_flux(soln_int_at_q[iquad], soln_ext_at_q[iquad], phys_unit_normal_int[iquad]);
1908 
1909  DirectionalState diss_soln_jump_int, diss_soln_jump_ext;
1910  for (int s=0; s<nstate; s++) {
1911  for (int d=0; d<dim; d++) {
1912  diss_soln_jump_int[s][d] = (diss_soln_num_flux[s] - soln_int_at_q[iquad][s]) * phys_unit_normal_int[iquad][d];
1913  diss_soln_jump_ext[s][d] = (diss_soln_num_flux[s] - soln_ext_at_q[iquad][s]) * phys_unit_normal_ext[iquad][d];
1914  }
1915  }
1916  diss_flux_jump_int = physics.dissipative_flux (soln_int_at_q[iquad], diss_soln_jump_int, current_cell_index);
1917  diss_flux_jump_ext = physics.dissipative_flux (soln_ext_at_q[iquad], diss_soln_jump_ext, neighbor_cell_index);
1918 
1920  const DirectionalState artificial_diss_flux_jump_int = DGBaseState<dim,nstate,real,MeshType>::artificial_dissip->calc_artificial_dissipation_flux(soln_int_at_q[iquad], diss_soln_jump_int,artificial_diss_coeff_at_q[iquad]);
1921  const DirectionalState artificial_diss_flux_jump_ext = DGBaseState<dim,nstate,real,MeshType>::artificial_dissip->calc_artificial_dissipation_flux(soln_ext_at_q[iquad], diss_soln_jump_ext,artificial_diss_coeff_at_q[iquad]);
1922  for (int s=0; s<nstate; s++) {
1923  diss_flux_jump_int[s] += artificial_diss_flux_jump_int[s];
1924  diss_flux_jump_ext[s] += artificial_diss_flux_jump_ext[s];
1925  }
1926  }
1927 
1928 
1929  diss_auxi_num_flux_dot_n = diss_num_flux.evaluate_auxiliary_flux(
1930  current_cell_index,
1931  neighbor_cell_index,
1932  artificial_diss_coeff_at_q[iquad],
1933  artificial_diss_coeff_at_q[iquad],
1934  soln_int_at_q[iquad], soln_ext_at_q[iquad],
1935  soln_grad_int[iquad], soln_grad_ext[iquad],
1936  phys_unit_normal_int[iquad], penalty);
1937 
1938  // From test functions associated with interior cell point of view
1939  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
1940  real2 rhs = 0.0;
1941  const unsigned int istate = soln_int.finite_element.system_to_component_index(itest_int).first;
1942 
1943  const real2 JxW_iquad = faceJxW[iquad];
1944  // Convection
1945  rhs = rhs - interpolation_operator_int[itest_int][iquad] * conv_num_flux_dot_n[istate] * JxW_iquad;
1946  // Diffusive
1947  rhs = rhs - interpolation_operator_int[itest_int][iquad] * diss_auxi_num_flux_dot_n[istate] * JxW_iquad;
1948  for (int d=0;d<dim;++d) {
1949  rhs = rhs + gradient_operator_int[d][itest_int][iquad] * diss_flux_jump_int[istate][d] * JxW_iquad;
1950  }
1951 
1952  rhs_int[itest_int] += rhs;
1953  dual_dot_residual += dual_int[itest_int]*rhs;
1954  }
1955 
1956  // From test functions associated with neighbor cell point of view
1957  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
1958  real2 rhs = 0.0;
1959  const unsigned int istate = soln_ext.finite_element.system_to_component_index(itest_ext).first;
1960 
1961  const real2 JxW_iquad = faceJxW[iquad];
1962  // Convection
1963  rhs = rhs - interpolation_operator_ext[itest_ext][iquad] * (-conv_num_flux_dot_n[istate]) * JxW_iquad;
1964  // Diffusive
1965  rhs = rhs - interpolation_operator_ext[itest_ext][iquad] * (-diss_auxi_num_flux_dot_n[istate]) * JxW_iquad;
1966  for (int d=0;d<dim;++d) {
1967  rhs = rhs + gradient_operator_ext[d][itest_ext][iquad] * diss_flux_jump_ext[istate][d] * JxW_iquad;
1968  }
1969 
1970  rhs_ext[itest_ext] += rhs;
1971  dual_dot_residual += dual_ext[itest_ext]*rhs;
1972  }
1973  } // Quadrature point loop
1974 
1975 }
1976 
1977 #ifdef FADFAD
1978 template <int dim, int nstate, typename real, typename MeshType>
1980  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
1981  const dealii::types::global_dof_index current_cell_index,
1982  const dealii::types::global_dof_index neighbor_cell_index,
1983  const std::pair<unsigned int, int> face_subface_int,
1984  const std::pair<unsigned int, int> face_subface_ext,
1985  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_int,
1986  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_ext,
1987  const dealii::FEFaceValuesBase<dim,dim> &fe_values_int,
1988  const dealii::FEFaceValuesBase<dim,dim> &fe_values_ext,
1989  const real penalty,
1990  const dealii::FESystem<dim,dim> &soln_int.finite_element,
1991  const dealii::FESystem<dim,dim> &soln_ext.finite_element,
1992  const dealii::Quadrature<dim-1> &face_quadrature,
1993  const std::vector<dealii::types::global_dof_index> &metric_dof_indices_int,
1994  const std::vector<dealii::types::global_dof_index> &metric_dof_indices_ext,
1995  const std::vector<dealii::types::global_dof_index> &soln_dof_indices_int,
1996  const std::vector<dealii::types::global_dof_index> &soln_dof_indices_ext,
1997  dealii::Vector<real> &local_rhs_int_cell,
1998  dealii::Vector<real> &local_rhs_ext_cell,
1999  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
2000 {
2001  (void) current_cell_index;
2002  (void) neighbor_cell_index;
2003  using adtype = FadFadType;
2004  using ADArray = std::array<adtype,nstate>;
2005  using ADArrayTensor1 = std::array< dealii::Tensor<1,dim,adtype>, nstate >;
2006 
2007  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
2008  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
2009  const unsigned int n_soln_dofs_int = soln_int.finite_element.dofs_per_cell;
2010  const unsigned int n_soln_dofs_ext = soln_ext.finite_element.dofs_per_cell;
2011 
2012  AssertDimension (n_soln_dofs_int, soln_dof_indices_int.size());
2013  AssertDimension (n_soln_dofs_ext, soln_dof_indices_ext.size());
2014 
2015  std::vector< adtype > coords_coeff_int(n_metric_dofs);
2016  std::vector< adtype > coords_coeff_ext(n_metric_dofs);
2017  std::vector< adtype > soln_int.coefficients(n_soln_dofs_int);
2018  std::vector< adtype > soln_ext.coefficients(n_soln_dofs_ext);
2019 
2020  // Current derivative ordering is: soln_int, soln_ext, metric_int, metric_ext
2021  unsigned int w_int_start, w_int_end, w_ext_start, w_ext_end,
2022  x_int_start, x_int_end, x_ext_start, x_ext_end;
2023  automatic_differentiation_indexing_2(
2024  compute_dRdW, compute_dRdX, compute_d2R,
2025  n_soln_dofs_int, n_soln_dofs_ext, n_metric_dofs,
2026  w_int_start, w_int_end, w_ext_start, w_ext_end,
2027  x_int_start, x_int_end, x_ext_start, x_ext_end);
2028 
2029  const unsigned int n_total_indep = x_ext_end;
2030  unsigned int i_derivative = 0;
2031 
2032  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2033  const real val = this->solution(soln_dof_indices_int[idof]);
2034  soln_int.coefficients[idof] = val;
2035  soln_int.coefficients[idof].val() = val;
2036 
2037  if (compute_dRdW || compute_d2R) soln_int.coefficients[idof].diff(i_derivative, n_total_indep);
2038  if (compute_d2R) soln_int.coefficients[idof].val().diff(i_derivative, n_total_indep);
2039  if (compute_dRdW || compute_d2R) i_derivative++;
2040  }
2041  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2042  const real val = this->solution(soln_dof_indices_ext[idof]);
2043  soln_ext.coefficients[idof] = val;
2044  soln_ext.coefficients[idof].val() = val;
2045 
2046  if (compute_dRdW || compute_d2R) soln_ext.coefficients[idof].diff(i_derivative, n_total_indep);
2047  if (compute_d2R) soln_ext.coefficients[idof].val().diff(i_derivative, n_total_indep);
2048  if (compute_dRdW || compute_d2R) i_derivative++;
2049  }
2050  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2051  const real val = this->high_order_grid->volume_nodes[metric_dof_indices_int[idof]];
2052  coords_coeff_int[idof] = val;
2053  coords_coeff_int[idof].val() = val;
2054 
2055  if (compute_dRdX || compute_d2R) coords_coeff_int[idof].diff(i_derivative, n_total_indep);
2056  if (compute_d2R) coords_coeff_int[idof].val().diff(i_derivative, n_total_indep);
2057  if (compute_dRdX || compute_d2R) i_derivative++;
2058  }
2059  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2060  const real val = this->high_order_grid->volume_nodes[metric_dof_indices_ext[idof]];
2061  coords_coeff_ext[idof] = val;
2062  coords_coeff_ext[idof].val() = val;
2063 
2064  if (compute_dRdX || compute_d2R) coords_coeff_ext[idof].diff(i_derivative, n_total_indep);
2065  if (compute_d2R) coords_coeff_ext[idof].val().diff(i_derivative, n_total_indep);
2066  if (compute_dRdX || compute_d2R) i_derivative++;
2067  }
2068  AssertDimension(i_derivative, n_total_indep);
2069 
2070  std::vector<double> dual_int(n_soln_dofs_int);
2071  std::vector<double> dual_ext(n_soln_dofs_ext);
2072 
2073  for (unsigned int itest=0; itest<n_soln_dofs_int; ++itest) {
2074  const unsigned int global_residual_row = soln_dof_indices_int[itest];
2075  dual_int[itest] = this->dual[global_residual_row];
2076  }
2077  for (unsigned int itest=0; itest<n_soln_dofs_ext; ++itest) {
2078  const unsigned int global_residual_row = soln_dof_indices_ext[itest];
2079  dual_ext[itest] = this->dual[global_residual_row];
2080  }
2081 
2082  std::vector<adtype> rhs_int(n_soln_dofs_int);
2083  std::vector<adtype> rhs_ext(n_soln_dofs_ext);
2084  adtype dual_dot_residual;
2085 
2087  const auto &conv_num_flux = *(DGBaseState<dim,nstate,real,MeshType>::conv_num_flux_fad_fad);
2088  const auto &diss_num_flux = *(DGBaseState<dim,nstate,real,MeshType>::diss_num_flux_fad_fad);
2090  cell,
2091  current_cell_index,
2092  neighbor_cell_index,
2093  soln_int.coefficients,
2094  soln_ext.coefficients,
2095  coords_coeff_int,
2096  coords_coeff_ext,
2097  dual_int,
2098  dual_ext,
2099  face_subface_int,
2100  face_subface_ext,
2101  face_data_set_int,
2102  face_data_set_ext,
2103  physics,
2104  conv_num_flux,
2105  diss_num_flux,
2106  fe_values_int,
2107  fe_values_ext,
2108  penalty,
2109  soln_int.finite_element,
2110  soln_ext.finite_element,
2111  fe_metric,
2112  face_quadrature_int,
2113  face_quadrature_ext,
2114  rhs_int,
2115  rhs_ext,
2116  dual_dot_residual,
2117  compute_dRdW, compute_dRdX, compute_d2R);
2118 
2119  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
2120  local_rhs_int_cell[itest_int] += rhs_int[itest_int].val().val();
2121  }
2122  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2123  local_rhs_ext_cell[itest_ext] += rhs_ext[itest_ext].val().val();
2124  }
2125 
2126  if (compute_dRdW) {
2127  std::vector<real> residual_derivatives(n_soln_dofs_int);
2128  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
2129  // dR_int_dW_int
2130  residual_derivatives.resize(n_soln_dofs_int);
2131  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2132  const unsigned int i_dx = idof+w_int_start;
2133  residual_derivatives[idof] = rhs_int[itest_int].dx(i_dx).val();
2134  }
2135  const bool elide_zero_values = false;
2136  this->system_matrix.add(soln_dof_indices_int[itest_int], soln_dof_indices_int, residual_derivatives, elide_zero_values);
2137 
2138  // dR_int_dW_ext
2139  residual_derivatives.resize(n_soln_dofs_ext);
2140  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2141  const unsigned int i_dx = idof+w_ext_start;
2142  residual_derivatives[idof] = rhs_int[itest_int].dx(i_dx).val();
2143  }
2144  this->system_matrix.add(soln_dof_indices_int[itest_int], soln_dof_indices_ext, residual_derivatives, elide_zero_values);
2145  }
2146 
2147  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2148  // dR_ext_dW_int
2149  residual_derivatives.resize(n_soln_dofs_int);
2150  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2151  const unsigned int i_dx = idof+w_int_start;
2152  residual_derivatives[idof] = rhs_ext[itest_ext].dx(i_dx).val();
2153  }
2154  const bool elide_zero_values = false;
2155  this->system_matrix.add(soln_dof_indices_ext[itest_ext], soln_dof_indices_int, residual_derivatives, elide_zero_values);
2156 
2157  // dR_ext_dW_ext
2158  residual_derivatives.resize(n_soln_dofs_ext);
2159  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2160  const unsigned int i_dx = idof+w_ext_start;
2161  residual_derivatives[idof] = rhs_ext[itest_ext].dx(i_dx).val();
2162  }
2163  this->system_matrix.add(soln_dof_indices_ext[itest_ext], soln_dof_indices_ext, residual_derivatives, elide_zero_values);
2164  }
2165  }
2166  if (compute_dRdX) {
2167  std::vector<real> residual_derivatives(n_metric_dofs);
2168  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
2169  // dR_int_dX_int
2170  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2171  const unsigned int i_dx = idof+x_int_start;
2172  residual_derivatives[idof] = rhs_int[itest_int].dx(i_dx).val();
2173  }
2174  this->dRdXv.add(soln_dof_indices_int[itest_int], metric_dof_indices_int, residual_derivatives);
2175 
2176  // dR_int_dX_ext
2177  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2178  const unsigned int i_dx = idof+x_ext_start;
2179  residual_derivatives[idof] = rhs_int[itest_int].dx(i_dx).val();
2180  }
2181  this->dRdXv.add(soln_dof_indices_int[itest_int], metric_dof_indices_ext, residual_derivatives);
2182  }
2183  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2184  // dR_ext_dX_int
2185  std::vector<real> residual_derivatives(n_metric_dofs);
2186  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2187  const unsigned int i_dx = idof+x_int_start;
2188  residual_derivatives[idof] = rhs_ext[itest_ext].dx(i_dx).val();
2189  }
2190  this->dRdXv.add(soln_dof_indices_ext[itest_ext], metric_dof_indices_int, residual_derivatives);
2191 
2192  // dR_ext_dX_ext
2193  // residual_derivatives.resize(n_metric_dofs);
2194  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2195  const unsigned int i_dx = idof+x_ext_start;
2196  residual_derivatives[idof] = rhs_ext[itest_ext].dx(i_dx).val();
2197  }
2198  this->dRdXv.add(soln_dof_indices_ext[itest_ext], metric_dof_indices_ext, residual_derivatives);
2199  }
2200  }
2201 
2202  if (compute_d2R) {
2203  std::vector<real> dWidWint(n_soln_dofs_int);
2204  std::vector<real> dWidWext(n_soln_dofs_ext);
2205  std::vector<real> dWidX(n_metric_dofs);
2206  std::vector<real> dXidX(n_metric_dofs);
2207  // dWint
2208  for (unsigned int idof=0; idof<n_soln_dofs_int; ++idof) {
2209 
2210  const unsigned int i_dx = idof+w_int_start;
2211  const FadType dWi = dual_dot_residual.dx(i_dx);
2212 
2213  // dWint_dWint
2214  for (unsigned int jdof=0; jdof<n_soln_dofs_int; ++jdof) {
2215  const unsigned int j_dx = jdof+w_int_start;
2216  dWidWint[jdof] = dWi.dx(j_dx);
2217  }
2218  this->d2RdWdW.add(soln_dof_indices_int[idof], soln_dof_indices_int, dWidWint);
2219 
2220  // dWint_dWext
2221  for (unsigned int jdof=0; jdof<n_soln_dofs_ext; ++jdof) {
2222  const unsigned int j_dx = jdof+w_ext_start;
2223  dWidWext[jdof] = dWi.dx(j_dx);
2224  }
2225  this->d2RdWdW.add(soln_dof_indices_int[idof], soln_dof_indices_ext, dWidWext);
2226 
2227  // dWint_dXint
2228  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2229  const unsigned int j_dx = jdof+x_int_start;
2230  dWidX[jdof] = dWi.dx(j_dx);
2231  }
2232  this->d2RdWdX.add(soln_dof_indices_int[idof], metric_dof_indices_int, dWidX);
2233 
2234  // dWint_dXext
2235  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2236  const unsigned int j_dx = jdof+x_ext_start;
2237  dWidX[jdof] = dWi.dx(j_dx);
2238  }
2239  this->d2RdWdX.add(soln_dof_indices_int[idof], metric_dof_indices_ext, dWidX);
2240  }
2241  // dWext
2242  for (unsigned int idof=0; idof<n_soln_dofs_ext; ++idof) {
2243 
2244  const unsigned int i_dx = idof+w_ext_start;
2245  const FadType dWi = dual_dot_residual.dx(i_dx);
2246 
2247  // dWext_dWint
2248  for (unsigned int jdof=0; jdof<n_soln_dofs_int; ++jdof) {
2249  const unsigned int j_dx = jdof+w_int_start;
2250  dWidWint[jdof] = dWi.dx(j_dx);
2251  }
2252  this->d2RdWdW.add(soln_dof_indices_ext[idof], soln_dof_indices_int, dWidWint);
2253 
2254  // dWext_dWext
2255  for (unsigned int jdof=0; jdof<n_soln_dofs_ext; ++jdof) {
2256  const unsigned int j_dx = jdof+w_ext_start;
2257  dWidWext[jdof] = dWi.dx(j_dx);
2258  }
2259  this->d2RdWdW.add(soln_dof_indices_ext[idof], soln_dof_indices_ext, dWidWext);
2260 
2261  // dWext_dXint
2262  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2263  const unsigned int j_dx = jdof+x_int_start;
2264  dWidX[jdof] = dWi.dx(j_dx);
2265  }
2266  this->d2RdWdX.add(soln_dof_indices_ext[idof], metric_dof_indices_int, dWidX);
2267 
2268  // dWext_dXext
2269  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2270  const unsigned int j_dx = jdof+x_ext_start;
2271  dWidX[jdof] = dWi.dx(j_dx);
2272  }
2273  this->d2RdWdX.add(soln_dof_indices_ext[idof], metric_dof_indices_ext, dWidX);
2274  }
2275 
2276  // dXint
2277  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
2278 
2279  const unsigned int i_dx = idof+x_int_start;
2280  const FadType dWi = dual_dot_residual.dx(i_dx);
2281 
2282  // dXint_dXint
2283  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2284  const unsigned int j_dx = jdof+x_int_start;
2285  dWidX[jdof] = dWi.dx(j_dx);
2286  }
2287  this->d2RdXdX.add(metric_dof_indices_int[idof], metric_dof_indices_int, dWidX);
2288 
2289  // dXint_dXext
2290  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2291  const unsigned int j_dx = jdof+x_ext_start;
2292  dWidX[jdof] = dWi.dx(j_dx);
2293  }
2294  this->d2RdXdX.add(metric_dof_indices_int[idof], metric_dof_indices_ext, dWidX);
2295  }
2296  // dXext
2297  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
2298 
2299  const unsigned int i_dx = idof+x_ext_start;
2300  const FadType dWi = dual_dot_residual.dx(i_dx);
2301 
2302  // dXext_dXint
2303  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2304  const unsigned int j_dx = jdof+x_int_start;
2305  dWidX[jdof] = dWi.dx(j_dx);
2306  }
2307  this->d2RdXdX.add(metric_dof_indices_ext[idof], metric_dof_indices_int, dWidX);
2308 
2309  // dXext_dXext
2310  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2311  const unsigned int j_dx = jdof+x_ext_start;
2312  dWidX[jdof] = dWi.dx(j_dx);
2313  }
2314  this->d2RdXdX.add(metric_dof_indices_ext[idof], metric_dof_indices_ext, dWidX);
2315  }
2316  }
2317 }
2318 #endif
2319 
2320 #ifndef FADFAD
2321 template <int dim, int nstate, typename real, typename MeshType>
2322 template <typename adtype>
2324  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
2325  const dealii::types::global_dof_index current_cell_index,
2326  const dealii::types::global_dof_index neighbor_cell_index,
2327  const std::pair<unsigned int, int> face_subface_int,
2328  const std::pair<unsigned int, int> face_subface_ext,
2329  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_int,
2330  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_ext,
2331  const dealii::FEFaceValuesBase<dim,dim> &fe_values_int,
2332  const dealii::FEFaceValuesBase<dim,dim> &fe_values_ext,
2333  const real penalty,
2334  const dealii::FESystem<dim,dim> &fe_int,
2335  const dealii::FESystem<dim,dim> &fe_ext,
2336  const dealii::Quadrature<dim-1> &face_quadrature,
2337  const std::vector<dealii::types::global_dof_index> &metric_dof_indices_int,
2338  const std::vector<dealii::types::global_dof_index> &metric_dof_indices_ext,
2339  const std::vector<dealii::types::global_dof_index> &soln_dof_indices_int,
2340  const std::vector<dealii::types::global_dof_index> &soln_dof_indices_ext,
2344  dealii::Vector<real> &local_rhs_int_cell,
2345  dealii::Vector<real> &local_rhs_ext_cell,
2346  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
2347 {
2348  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
2349  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
2350  const unsigned int n_soln_dofs_int = fe_int.dofs_per_cell;
2351  const unsigned int n_soln_dofs_ext = fe_ext.dofs_per_cell;
2352 
2353  AssertDimension (n_soln_dofs_int, soln_dof_indices_int.size());
2354  AssertDimension (n_soln_dofs_ext, soln_dof_indices_ext.size());
2355 
2356  LocalSolution<adtype, dim, nstate> soln_int(fe_int);
2357  LocalSolution<adtype, dim, nstate> soln_ext(fe_ext);
2358  LocalSolution<adtype, dim, dim> metric_int(fe_metric);
2359  LocalSolution<adtype, dim, dim> metric_ext(fe_metric);
2360 
2361  // Current derivative ordering is: soln_int, soln_ext, metric_int, metric_ext
2362  unsigned int w_int_start, w_int_end, w_ext_start, w_ext_end,
2363  x_int_start, x_int_end, x_ext_start, x_ext_end;
2364  automatic_differentiation_indexing_2(
2365  compute_dRdW, compute_dRdX, compute_d2R,
2366  n_soln_dofs_int, n_soln_dofs_ext, n_metric_dofs,
2367  w_int_start, w_int_end, w_ext_start, w_ext_end,
2368  x_int_start, x_int_end, x_ext_start, x_ext_end);
2369 
2370  using TH = codi::TapeHelper<adtype>;
2371  TH th;
2372  adtype::getGlobalTape();
2373  if (compute_dRdW || compute_dRdX || compute_d2R) {
2374  th.startRecording();
2375  }
2376  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2377  const real val = this->solution(soln_dof_indices_int[idof]);
2378  soln_int.coefficients[idof] = val;
2379  if (compute_dRdW || compute_d2R) {
2380  th.registerInput(soln_int.coefficients[idof]);
2381  } else {
2382  adtype::getGlobalTape().deactivateValue(soln_int.coefficients[idof]);
2383  }
2384  }
2385  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2386  const real val = this->solution(soln_dof_indices_ext[idof]);
2387  soln_ext.coefficients[idof] = val;
2388  if (compute_dRdW || compute_d2R) {
2389  th.registerInput(soln_ext.coefficients[idof]);
2390  } else {
2391  adtype::getGlobalTape().deactivateValue(soln_ext.coefficients[idof]);
2392  }
2393  }
2394  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2395  const real val = this->high_order_grid->volume_nodes[metric_dof_indices_int[idof]];
2396  metric_int.coefficients[idof] = val;
2397  if (compute_dRdX || compute_d2R) {
2398  th.registerInput(metric_int.coefficients[idof]);
2399  } else {
2400  adtype::getGlobalTape().deactivateValue(metric_int.coefficients[idof]);
2401  }
2402  }
2403  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2404  const real val = this->high_order_grid->volume_nodes[metric_dof_indices_ext[idof]];
2405  metric_ext.coefficients[idof] = val;
2406  if (compute_dRdX || compute_d2R) {
2407  th.registerInput(metric_ext.coefficients[idof]);
2408  } else {
2409  adtype::getGlobalTape().deactivateValue(metric_ext.coefficients[idof]);
2410  }
2411  }
2412 
2413  std::vector<double> dual_int(n_soln_dofs_int);
2414  std::vector<double> dual_ext(n_soln_dofs_ext);
2415 
2416  for (unsigned int itest=0; itest<n_soln_dofs_int; ++itest) {
2417  const unsigned int global_residual_row = soln_dof_indices_int[itest];
2418  dual_int[itest] = this->dual[global_residual_row];
2419  }
2420  for (unsigned int itest=0; itest<n_soln_dofs_ext; ++itest) {
2421  const unsigned int global_residual_row = soln_dof_indices_ext[itest];
2422  dual_ext[itest] = this->dual[global_residual_row];
2423  }
2424 
2425  std::vector<adtype> rhs_int(n_soln_dofs_int);
2426  std::vector<adtype> rhs_ext(n_soln_dofs_ext);
2427  adtype dual_dot_residual;
2428 
2430  cell,
2431  current_cell_index,
2432  neighbor_cell_index,
2433  soln_int, soln_ext, metric_int, metric_ext,
2434  dual_int,
2435  dual_ext,
2436  face_subface_int,
2437  face_subface_ext,
2438  face_data_set_int,
2439  face_data_set_ext,
2440  physics,
2441  conv_num_flux,
2442  diss_num_flux,
2443  fe_values_int,
2444  fe_values_ext,
2445  penalty,
2446  face_quadrature,
2447  rhs_int,
2448  rhs_ext,
2449  dual_dot_residual,
2450  compute_dRdW, compute_dRdX, compute_d2R);
2451 
2452  if (compute_dRdW || compute_dRdX) {
2453  for (unsigned int itest=0; itest<n_soln_dofs_int; ++itest) {
2454  th.registerOutput(rhs_int[itest]);
2455  }
2456  for (unsigned int itest=0; itest<n_soln_dofs_ext; ++itest) {
2457  th.registerOutput(rhs_ext[itest]);
2458  }
2459  } else if (compute_d2R) {
2460  th.registerOutput(dual_dot_residual);
2461  }
2462  if (compute_dRdW || compute_dRdX || compute_d2R) {
2463  th.stopRecording();
2464  //adtype::getGlobalTape().printStatistics();
2465  }
2466 
2467  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
2468  local_rhs_int_cell[itest_int] += getValue<adtype>(rhs_int[itest_int]);
2469  }
2470  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2471  local_rhs_ext_cell[itest_ext] += getValue<adtype>(rhs_ext[itest_ext]);
2472  }
2473 
2474  if (compute_dRdW || compute_dRdX) {
2475  typename TH::JacobianType& jac = th.createJacobian();
2476  th.evalJacobian(jac);
2477 
2478  if (compute_dRdW) {
2479  std::vector<real> residual_derivatives(n_soln_dofs_int);
2480 
2481  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
2482  int i_dependent = itest_int;
2483 
2484  // dR_int_dW_int
2485  residual_derivatives.resize(n_soln_dofs_int);
2486  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2487  const unsigned int i_dx = idof+w_int_start;
2488  residual_derivatives[idof] = jac(i_dependent,i_dx);
2489  }
2490  const bool elide_zero_values = false;
2491  this->system_matrix.add(soln_dof_indices_int[itest_int], soln_dof_indices_int, residual_derivatives, elide_zero_values);
2492 
2493  // dR_int_dW_ext
2494  residual_derivatives.resize(n_soln_dofs_ext);
2495  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2496  const unsigned int i_dx = idof+w_ext_start;
2497  residual_derivatives[idof] = jac(i_dependent,i_dx);
2498  }
2499  this->system_matrix.add(soln_dof_indices_int[itest_int], soln_dof_indices_ext, residual_derivatives, elide_zero_values);
2500  }
2501 
2502  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2503 
2504  int i_dependent = n_soln_dofs_int + itest_ext;
2505 
2506  // dR_ext_dW_int
2507  residual_derivatives.resize(n_soln_dofs_int);
2508  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2509  const unsigned int i_dx = idof+w_int_start;
2510  residual_derivatives[idof] = jac(i_dependent,i_dx);
2511  }
2512  const bool elide_zero_values = false;
2513  this->system_matrix.add(soln_dof_indices_ext[itest_ext], soln_dof_indices_int, residual_derivatives, elide_zero_values);
2514 
2515  // dR_ext_dW_ext
2516  residual_derivatives.resize(n_soln_dofs_ext);
2517  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2518  const unsigned int i_dx = idof+w_ext_start;
2519  residual_derivatives[idof] = jac(i_dependent,i_dx);
2520  }
2521  this->system_matrix.add(soln_dof_indices_ext[itest_ext], soln_dof_indices_ext, residual_derivatives, elide_zero_values);
2522  }
2523  }
2524 
2525  if (compute_dRdX) {
2526  std::vector<real> residual_derivatives(n_metric_dofs);
2527 
2528  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
2529 
2530  int i_dependent = itest_int;
2531 
2532  // dR_int_dX_int
2533  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2534  const unsigned int i_dx = idof+x_int_start;
2535  residual_derivatives[idof] = jac(i_dependent,i_dx);
2536  }
2537  this->dRdXv.add(soln_dof_indices_int[itest_int], metric_dof_indices_int, residual_derivatives);
2538 
2539  // dR_int_dX_ext
2540  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2541  const unsigned int i_dx = idof+x_ext_start;
2542  residual_derivatives[idof] = jac(i_dependent,i_dx);
2543  }
2544  this->dRdXv.add(soln_dof_indices_int[itest_int], metric_dof_indices_ext, residual_derivatives);
2545  }
2546 
2547  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2548 
2549  int i_dependent = n_soln_dofs_int + itest_ext;
2550 
2551  // dR_ext_dX_int
2552  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2553  const unsigned int i_dx = idof+x_int_start;
2554  residual_derivatives[idof] = jac(i_dependent,i_dx);
2555  }
2556  this->dRdXv.add(soln_dof_indices_ext[itest_ext], metric_dof_indices_int, residual_derivatives);
2557 
2558  // dR_ext_dX_ext
2559  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2560  const unsigned int i_dx = idof+x_ext_start;
2561  residual_derivatives[idof] = jac(i_dependent,i_dx);
2562  }
2563  this->dRdXv.add(soln_dof_indices_ext[itest_ext], metric_dof_indices_ext, residual_derivatives);
2564  }
2565  }
2566 
2567  th.deleteJacobian(jac);
2568  }
2569 
2570  if (compute_d2R) {
2571  typename TH::HessianType& hes = th.createHessian();
2572  th.evalHessian(hes);
2573 
2574  std::vector<real> dWidW(n_soln_dofs_int);
2575  std::vector<real> dWidX(n_metric_dofs);
2576  std::vector<real> dXidX(n_metric_dofs);
2577 
2578  int i_dependent = (compute_dRdW || compute_dRdX) ? n_soln_dofs_int + n_soln_dofs_ext : 0;
2579 
2580  for (unsigned int idof=0; idof<n_soln_dofs_int; ++idof) {
2581 
2582  const unsigned int i_dx = idof+w_int_start;
2583 
2584  // dWint_dWint
2585  for (unsigned int jdof=0; jdof<n_soln_dofs_int; ++jdof) {
2586  const unsigned int j_dx = jdof+w_int_start;
2587  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
2588  }
2589  this->d2RdWdW.add(soln_dof_indices_int[idof], soln_dof_indices_int, dWidW);
2590 
2591  // dWint_dWext
2592  for (unsigned int jdof=0; jdof<n_soln_dofs_ext; ++jdof) {
2593  const unsigned int j_dx = jdof+w_ext_start;
2594  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
2595  }
2596  this->d2RdWdW.add(soln_dof_indices_int[idof], soln_dof_indices_ext, dWidW);
2597 
2598  // dWint_dXint
2599  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2600  const unsigned int j_dx = jdof+x_int_start;
2601  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
2602  }
2603  this->d2RdWdX.add(soln_dof_indices_int[idof], metric_dof_indices_int, dWidX);
2604 
2605  // dWint_dXext
2606  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2607  const unsigned int j_dx = jdof+x_ext_start;
2608  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
2609  }
2610  this->d2RdWdX.add(soln_dof_indices_int[idof], metric_dof_indices_ext, dWidX);
2611  }
2612 
2613  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
2614 
2615  const unsigned int i_dx = idof+x_int_start;
2616 
2617  // dXint_dXint
2618  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2619  const unsigned int j_dx = jdof+x_int_start;
2620  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
2621  }
2622  this->d2RdXdX.add(metric_dof_indices_int[idof], metric_dof_indices_int, dXidX);
2623 
2624  // dXint_dXext
2625  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2626  const unsigned int j_dx = jdof+x_ext_start;
2627  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
2628  }
2629  this->d2RdXdX.add(metric_dof_indices_int[idof], metric_dof_indices_ext, dXidX);
2630  }
2631 
2632  dWidW.resize(n_soln_dofs_ext);
2633 
2634  for (unsigned int idof=0; idof<n_soln_dofs_ext; ++idof) {
2635 
2636  const unsigned int i_dx = idof+w_ext_start;
2637 
2638  // dWext_dWint
2639  for (unsigned int jdof=0; jdof<n_soln_dofs_int; ++jdof) {
2640  const unsigned int j_dx = jdof+w_int_start;
2641  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
2642  }
2643  this->d2RdWdW.add(soln_dof_indices_ext[idof], soln_dof_indices_int, dWidW);
2644 
2645  // dWext_dWext
2646  for (unsigned int jdof=0; jdof<n_soln_dofs_ext; ++jdof) {
2647  const unsigned int j_dx = jdof+w_ext_start;
2648  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
2649  }
2650  this->d2RdWdW.add(soln_dof_indices_ext[idof], soln_dof_indices_ext, dWidW);
2651 
2652  // dWext_dXint
2653  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2654  const unsigned int j_dx = jdof+x_int_start;
2655  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
2656  }
2657  this->d2RdWdX.add(soln_dof_indices_ext[idof], metric_dof_indices_int, dWidX);
2658 
2659  // dWext_dXext
2660  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2661  const unsigned int j_dx = jdof+x_ext_start;
2662  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
2663  }
2664  this->d2RdWdX.add(soln_dof_indices_ext[idof], metric_dof_indices_ext, dWidX);
2665  }
2666 
2667  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
2668 
2669  const unsigned int i_dx = idof+x_ext_start;
2670 
2671  // dXint_dXint
2672  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2673  const unsigned int j_dx = jdof+x_int_start;
2674  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
2675  }
2676  this->d2RdXdX.add(metric_dof_indices_ext[idof], metric_dof_indices_int, dXidX);
2677 
2678  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
2679  const unsigned int j_dx = jdof+x_ext_start;
2680  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
2681  }
2682  this->d2RdXdX.add(metric_dof_indices_ext[idof], metric_dof_indices_ext, dXidX);
2683  }
2684 
2685  th.deleteHessian(hes);
2686  }
2687 
2688  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2689  adtype::getGlobalTape().deactivateValue(soln_int.coefficients[idof]);
2690  }
2691  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2692  adtype::getGlobalTape().deactivateValue(soln_ext.coefficients[idof]);
2693  }
2694  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2695  adtype::getGlobalTape().deactivateValue(metric_int.coefficients[idof]);
2696  }
2697  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2698  adtype::getGlobalTape().deactivateValue(metric_ext.coefficients[idof]);
2699  }
2700 
2701 }
2702 
2703 template <int dim, int nstate, typename real, typename MeshType>
2705  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
2706  const dealii::types::global_dof_index current_cell_index,
2707  const dealii::types::global_dof_index neighbor_cell_index,
2708  const std::pair<unsigned int, int> face_subface_int,
2709  const std::pair<unsigned int, int> face_subface_ext,
2710  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_int,
2711  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_ext,
2712  const dealii::FEFaceValuesBase<dim,dim> &fe_values_int,
2713  const dealii::FEFaceValuesBase<dim,dim> &fe_values_ext,
2714  const real penalty,
2715  const dealii::FESystem<dim,dim> &fe_int,
2716  const dealii::FESystem<dim,dim> &fe_ext,
2717  const dealii::Quadrature<dim-1> &face_quadrature,
2718  const std::vector<dealii::types::global_dof_index> &metric_dof_indices_int,
2719  const std::vector<dealii::types::global_dof_index> &metric_dof_indices_ext,
2720  const std::vector<dealii::types::global_dof_index> &soln_dof_indices_int,
2721  const std::vector<dealii::types::global_dof_index> &soln_dof_indices_ext,
2725  dealii::Vector<real> &local_rhs_int_cell,
2726  dealii::Vector<real> &local_rhs_ext_cell,
2727  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
2728 {
2729  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
2730  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
2731  const unsigned int n_soln_dofs_int = fe_int.dofs_per_cell;
2732  const unsigned int n_soln_dofs_ext = fe_ext.dofs_per_cell;
2733 
2734  AssertDimension (n_soln_dofs_int, soln_dof_indices_int.size());
2735  AssertDimension (n_soln_dofs_ext, soln_dof_indices_ext.size());
2736 
2737  LocalSolution<real, dim, nstate> soln_int(fe_int);
2738  LocalSolution<real, dim, nstate> soln_ext(fe_ext);
2739  LocalSolution<real, dim, dim> metric_int(fe_metric);
2740  LocalSolution<real, dim, dim> metric_ext(fe_metric);
2741 
2742  for (unsigned int idof = 0; idof < n_soln_dofs_int; ++idof) {
2743  const real val = this->solution(soln_dof_indices_int[idof]);
2744  soln_int.coefficients[idof] = val;
2745  }
2746  for (unsigned int idof = 0; idof < n_soln_dofs_ext; ++idof) {
2747  const real val = this->solution(soln_dof_indices_ext[idof]);
2748  soln_ext.coefficients[idof] = val;
2749  }
2750  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2751  const real val = this->high_order_grid->volume_nodes[metric_dof_indices_int[idof]];
2752  metric_int.coefficients[idof] = val;
2753  }
2754  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
2755  const real val = this->high_order_grid->volume_nodes[metric_dof_indices_ext[idof]];
2756  metric_ext.coefficients[idof] = val;
2757  }
2758 
2759  std::vector<double> dual_int(n_soln_dofs_int);
2760  std::vector<double> dual_ext(n_soln_dofs_ext);
2761 
2762  for (unsigned int itest=0; itest<n_soln_dofs_int; ++itest) {
2763  const unsigned int global_residual_row = soln_dof_indices_int[itest];
2764  dual_int[itest] = this->dual[global_residual_row];
2765  }
2766  for (unsigned int itest=0; itest<n_soln_dofs_ext; ++itest) {
2767  const unsigned int global_residual_row = soln_dof_indices_ext[itest];
2768  dual_ext[itest] = this->dual[global_residual_row];
2769  }
2770 
2771  std::vector<real> rhs_int(n_soln_dofs_int);
2772  std::vector<real> rhs_ext(n_soln_dofs_ext);
2773  real dual_dot_residual;
2774 
2776  cell,
2777  current_cell_index,
2778  neighbor_cell_index,
2779  soln_int, soln_ext, metric_int, metric_ext,
2780  dual_int,
2781  dual_ext,
2782  face_subface_int,
2783  face_subface_ext,
2784  face_data_set_int,
2785  face_data_set_ext,
2786  physics,
2787  conv_num_flux,
2788  diss_num_flux,
2789  fe_values_int,
2790  fe_values_ext,
2791  penalty,
2792  face_quadrature,
2793  rhs_int,
2794  rhs_ext,
2795  dual_dot_residual,
2796  compute_dRdW, compute_dRdX, compute_d2R);
2797 
2798  for (unsigned int itest_int=0; itest_int<n_soln_dofs_int; ++itest_int) {
2799  local_rhs_int_cell[itest_int] += getValue<real>(rhs_int[itest_int]);
2800  }
2801  for (unsigned int itest_ext=0; itest_ext<n_soln_dofs_ext; ++itest_ext) {
2802  local_rhs_ext_cell[itest_ext] += getValue<real>(rhs_ext[itest_ext]);
2803  }
2804 
2805 }
2806 #endif
2807 
2808 template <int dim, int nstate, typename real, typename MeshType>
2809 template <typename real2>
2811  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
2812  const dealii::types::global_dof_index current_cell_index,
2813  const LocalSolution<real2, dim, nstate> &local_solution,
2814  const LocalSolution<real2, dim, dim> &local_metric,
2815  const std::vector<real> &local_dual,
2816  const dealii::Quadrature<dim> &quadrature,
2818  std::vector<real2> &rhs, real2 &dual_dot_residual,
2819  const bool compute_metric_derivatives,
2820  const dealii::FEValues<dim,dim> &fe_values_vol)
2821 {
2822  (void) current_cell_index;
2823  using State = State<real2, nstate>;
2824  using DirectionalState = DirectionalState<real2, dim, nstate>;
2825  using Tensor2D = dealii::Tensor<2,dim,real2>;
2826 
2827  const unsigned int n_quad_pts = quadrature.size();
2828  const unsigned int n_soln_dofs = local_solution.finite_element.dofs_per_cell;
2829 
2830  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
2831  rhs[itest] = 0;
2832  }
2833  dual_dot_residual = 0.0;
2834 
2835  const std::vector<dealii::Point<dim>> &points = quadrature.get_points ();
2836 
2837  const unsigned int n_metric_dofs = local_metric.finite_element.dofs_per_cell;
2838 
2839  // Evaluate metric terms
2840  std::vector<Tensor2D> metric_jacobian;
2841  if (compute_metric_derivatives) metric_jacobian = evaluate_metric_jacobian ( points, local_metric);
2842  std::vector<real2> jac_det(n_quad_pts);
2843  std::vector<Tensor2D> jac_inv_tran(n_quad_pts);
2844  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
2845 
2846  if (compute_metric_derivatives) {
2847  const real2 jacobian_determinant = dealii::determinant(metric_jacobian[iquad]);
2848  jac_det[iquad] = jacobian_determinant;
2849 
2850  const Tensor2D jacobian_transpose_inverse = dealii::transpose(dealii::invert(metric_jacobian[iquad]));
2851  jac_inv_tran[iquad] = jacobian_transpose_inverse;
2852  } else {
2853  jac_det[iquad] = fe_values_vol.JxW(iquad) / quadrature.weight(iquad);
2854  }
2855  }
2856 #ifdef KOPRIVA_METRICS_VOL
2857  auto old_jac_inv_tran = jac_inv_tran;
2858  auto old_jac_det = jac_det;
2859  if constexpr (dim != 1) {
2860  evaluate_covariant_metric_jacobian<dim,real2> ( quadrature, local_metric, jac_inv_tran, jac_det);
2861  }
2862  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
2863  if (abs(old_jac_det[iquad] - jac_det[iquad])/abs(old_jac_det[iquad]) > 1e-10) {
2864  std::cout << std::setprecision(std::numeric_limits<long double>::digits10 + 1);
2865  std::cout << "Not the same jac det, iquad " << iquad << std::endl;
2866  std::cout << old_jac_det[iquad] << std::endl;
2867  std::cout << jac_det[iquad] << std::endl;
2868  }
2869  }
2870 #endif
2871 
2872  // Build operators.
2873  const std::vector<dealii::Point<dim,double>> &unit_quad_pts = quadrature.get_points();
2874  dealii::FullMatrix<real> interpolation_operator(n_soln_dofs,n_quad_pts);
2875  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
2876  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
2877  interpolation_operator[idof][iquad] = local_solution.finite_element.shape_value(idof,unit_quad_pts[iquad]);
2878  }
2879  }
2880  // Might want to have the dimension as the innermost index
2881  // Need a contiguous 2d-array structure
2882  // std::array<dealii::FullMatrix<real2>,dim> gradient_operator;
2883  // for (int d=0;d<dim;++d) {
2884  // gradient_operator[d].reinit(n_soln_dofs, n_quad_pts);
2885  // }
2886  std::array<dealii::FullMatrix<real2>,dim> gradient_operator;
2887  for (int d=0;d<dim;++d) {
2888  gradient_operator[d].reinit(dealii::TableIndices<2>(n_soln_dofs, n_quad_pts));
2889  }
2890  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
2891  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
2892  if (compute_metric_derivatives) {
2893  //const dealii::Tensor<1,dim,real2> phys_shape_grad = dealii::contract<1,0>(jac_inv_tran[iquad], fe_soln.shape_grad(idof,points[iquad]));
2894  const dealii::Tensor<1,dim,real2> ref_shape_grad = local_solution.finite_element.shape_grad(idof,points[iquad]);
2895  dealii::Tensor<1,dim,real2> phys_shape_grad;
2896  for (int dr=0;dr<dim;++dr) {
2897  phys_shape_grad[dr] = 0.0;
2898  for (int dc=0;dc<dim;++dc) {
2899  phys_shape_grad[dr] += jac_inv_tran[iquad][dr][dc] * ref_shape_grad[dc];
2900  }
2901  }
2902  for (int d=0;d<dim;++d) {
2903  gradient_operator[d][idof][iquad] = phys_shape_grad[d];
2904  }
2905 
2906  // Exact mapping
2907  // for (int d=0;d<dim;++d) {
2908  // const unsigned int istate = fe_soln.system_to_component_index(idof).first;
2909  // gradient_operator[d][idof][iquad] = fe_values_vol.shape_grad_component(idof, iquad, istate)[d];
2910  // }
2911  } else {
2912  for (int d=0;d<dim;++d) {
2913  const unsigned int istate = local_solution.finite_element.system_to_component_index(idof).first;
2914  gradient_operator[d][idof][iquad] = fe_values_vol.shape_grad_component(idof, iquad, istate)[d];
2915  }
2916  }
2917  }
2918  }
2919 
2920 
2921 
2922  //const real2 cell_diameter = fe_values_.get_cell()->diameter();
2923  // real2 cell_volume = 0.0;
2924  // for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
2925 
2926  // const real2 JxW_iquad = jac_det[iquad] * quadrature.weight(iquad);
2927 
2928  // cell_volume = cell_volume + JxW_iquad;
2929  // }
2930  //const real2 cell_diameter = pow(cell_volume,1.0/dim);
2931  //const real2 artificial_diss_coeff = this->all_parameters->artificial_dissipation_param.add_artificial_dissipation ?
2932  // this->discontinuity_sensor(cell_diameter, soln_coeff, fe_soln)
2933  // : 0.0;
2934  const real2 artificial_diss_coeff = this->all_parameters->artificial_dissipation_param.add_artificial_dissipation ?
2935  this->artificial_dissipation_coeffs[current_cell_index]
2936  : 0.0;
2937  (void) artificial_diss_coeff;
2938 
2939  typename dealii::DoFHandler<dim>::active_cell_iterator artificial_dissipation_cell(
2940  this->triangulation.get(), cell->level(), cell->index(), &(this->dof_handler_artificial_dissipation));
2941  const unsigned int n_dofs_arti_diss = this->fe_q_artificial_dissipation.dofs_per_cell;
2942  std::vector<dealii::types::global_dof_index> dof_indices_artificial_dissipation(n_dofs_arti_diss);
2943  artificial_dissipation_cell->get_dof_indices (dof_indices_artificial_dissipation);
2944 /*
2945  std::vector<real> artificial_diss_coeff_at_q(n_quad_pts);
2946  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
2947  artificial_diss_coeff_at_q[iquad] = 0.0;
2948 
2949  if ( this->all_parameters->artificial_dissipation_param.add_artificial_dissipation ) {
2950  const dealii::Point<dim,real> point = unit_quad_pts[iquad];
2951  for (unsigned int idof=0; idof<n_dofs_arti_diss; ++idof) {
2952  const unsigned int index = dof_indices_artificial_dissipation[idof];
2953  artificial_diss_coeff_at_q[iquad] += this->artificial_dissipation_c0[index] * this->fe_q_artificial_dissipation.shape_value(idof, point);
2954  }
2955  }
2956  }
2957 
2958 */
2959 
2960  std::vector<real2> artificial_diss_coeff_at_q(n_quad_pts);
2961  real2 arti_diss = this->discontinuity_sensor(quadrature, local_solution.coefficients, local_solution.finite_element, jac_det);
2962  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad)
2963  {
2964  artificial_diss_coeff_at_q[iquad] = arti_diss;
2965  /* dealii::Point<dim,real> point = unit_quad_pts[iquad];
2966  // Rescale over -1,1
2967  for (int d=0; d<dim; ++d)
2968  {
2969  point[d] = point[d]*2 - 1.0;
2970  }
2971  double gegenbauer_factor = 0.1;
2972  double gegenbauer = 1.0;
2973  for (int d=0; d<dim; ++d)
2974  {
2975  gegenbauer *= std::pow(1-point[d]*point[d], gegenbauer_factor);
2976  }
2977  artificial_diss_coeff_at_q[iquad] = arti_diss * gegenbauer;*/
2978  }
2979 
2980  std::vector<State> soln_at_q(n_quad_pts);
2981  std::vector<DirectionalState> soln_grad_at_q(n_quad_pts); // Tensor initialize with zeros
2982 
2983  std::vector<DirectionalState> conv_phys_flux_at_q(n_quad_pts);
2984  std::vector<DirectionalState> diss_phys_flux_at_q(n_quad_pts);
2985  std::vector<State> source_at_q;
2986  std::vector<State> physical_source_at_q;
2987 
2988  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
2989  for (int istate=0; istate<nstate; istate++) {
2990  soln_at_q[iquad][istate] = 0;
2991  soln_grad_at_q[iquad][istate] = 0;
2992  }
2993  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
2994  const unsigned int istate = local_solution.finite_element.system_to_component_index(idof).first;
2995  soln_at_q[iquad][istate] += local_solution.coefficients[idof] * interpolation_operator[idof][iquad];
2996  for (int d=0;d<dim;++d) {
2997  soln_grad_at_q[iquad][istate][d] += local_solution.coefficients[idof] * gradient_operator[d][idof][iquad];
2998  }
2999  }
3000  conv_phys_flux_at_q[iquad] = physics.convective_flux (soln_at_q[iquad]);
3001  diss_phys_flux_at_q[iquad] = physics.dissipative_flux (soln_at_q[iquad], soln_grad_at_q[iquad], current_cell_index);
3002 
3003  if(physics.has_nonzero_physical_source){
3004  physical_source_at_q.resize(n_quad_pts);
3005  dealii::Point<dim,real2> ad_points;
3006  for (int d=0;d<dim;++d) { ad_points[d] = 0.0;}
3007  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
3008  const int iaxis = local_metric.finite_element.system_to_component_index(idof).first;
3009  ad_points[iaxis] += local_metric.coefficients[idof] * local_metric.finite_element.shape_value(idof,unit_quad_pts[iquad]);
3010  }
3011  physical_source_at_q[iquad] = physics.physical_source_term (ad_points, soln_at_q[iquad], soln_grad_at_q[iquad], current_cell_index);
3012  }
3013 
3015  DirectionalState artificial_diss_phys_flux_at_q;
3016  //artificial_diss_phys_flux_at_q = physics.artificial_dissipative_flux (artificial_diss_coeff, soln_at_q[iquad], soln_grad_at_q[iquad]);
3017  artificial_diss_phys_flux_at_q = this->artificial_dissip->calc_artificial_dissipation_flux(soln_at_q[iquad], soln_grad_at_q[iquad],artificial_diss_coeff_at_q[iquad]);
3018  for (int s=0; s<nstate; s++) {
3019  diss_phys_flux_at_q[iquad][s] += artificial_diss_phys_flux_at_q[s];
3020  }
3021  }
3022 
3024  source_at_q.resize(n_quad_pts);
3025  dealii::Point<dim,real2> ad_point;
3026  for (int d=0;d<dim;++d) { ad_point[d] = 0.0;}
3027  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
3028  const int iaxis = local_metric.finite_element.system_to_component_index(idof).first;
3029  ad_point[iaxis] += local_metric.coefficients[idof] * local_metric.finite_element.shape_value(idof,unit_quad_pts[iquad]);
3030  }
3031  source_at_q[iquad] = physics.source_term (ad_point, soln_at_q[iquad], this->current_time, current_cell_index);
3032  }
3033  }
3034 
3035  // Weak form
3036  // The right-hand side sends all the term to the side of the source term
3037  // Therefore,
3038  // \divergence ( Fconv + Fdiss ) = source
3039  // has the right-hand side
3040  // rhs = - \divergence( Fconv + Fdiss ) + source
3041  // Since we have done an integration by parts, the volume term resulting from the divergence of Fconv and Fdiss
3042  // is negative. Therefore, negative of negative means we add that volume term to the right-hand-side
3043  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3044 
3045  const unsigned int istate = local_solution.finite_element.system_to_component_index(itest).first;
3046 
3047  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
3048 
3049  const real2 JxW_iquad = jac_det[iquad] * quadrature.weight(iquad);
3050 
3051  for (int d=0;d<dim;++d) {
3052  // Convective
3053  rhs[itest] = rhs[itest] + gradient_operator[d][itest][iquad] * conv_phys_flux_at_q[iquad][istate][d] * JxW_iquad;
3056  rhs[itest] = rhs[itest] + gradient_operator[d][itest][iquad] * diss_phys_flux_at_q[iquad][istate][d] * JxW_iquad;
3057  }
3058  // Physical source
3059  if(physics.has_nonzero_physical_source){
3060  rhs[itest] = rhs[itest] + interpolation_operator[itest][iquad]* physical_source_at_q[iquad][istate] * JxW_iquad;
3061  }
3062  // Source
3064  rhs[itest] = rhs[itest] + interpolation_operator[itest][iquad]* source_at_q[iquad][istate] * JxW_iquad;
3065  }
3066  }
3067  dual_dot_residual += local_dual[itest]*rhs[itest];
3068  }
3069 }
3070 
3071 #ifdef FADFAD
3072 template <int dim, int nstate, typename real, typename MeshType>
3074  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
3075  const dealii::types::global_dof_index current_cell_index,
3076  const dealii::FEValues<dim,dim> &fe_values_vol,
3077  const dealii::FESystem<dim,dim> &fe_soln,
3078  const dealii::Quadrature<dim> &quadrature,
3079  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
3080  const std::vector<dealii::types::global_dof_index> &soln_dof_indices,
3081  dealii::Vector<real> &local_rhs_cell,
3082  const dealii::FEValues<dim,dim> &/*fe_values_lagrange*/,
3083  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3084 {
3085  (void) current_cell_index;
3086 
3087  using ADArray = std::array<FadFadType,nstate>;
3088  using ADArrayTensor1 = std::array< dealii::Tensor<1,dim,FadFadType>, nstate >;
3089 
3090  const unsigned int n_soln_dofs = fe_soln.dofs_per_cell;
3091 
3092  AssertDimension (n_soln_dofs, soln_dof_indices.size());
3093 
3094  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
3095  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
3096 
3097  std::vector<FadFadType> coords_coeff(n_metric_dofs);
3098  std::vector<FadFadType> soln_coeff(n_soln_dofs);
3099 
3100  std::vector<real> local_dual(n_soln_dofs);
3101  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3102  const unsigned int global_residual_row = soln_dof_indices[itest];
3103  local_dual[itest] = this->dual[global_residual_row];
3104  }
3105 
3106  (void) compute_dRdW; (void) compute_dRdX; (void) compute_d2R;
3107  const bool compute_metric_derivatives = true;//(!compute_dRdX && !compute_d2R) ? false : true;
3108 
3109  unsigned int w_start, w_end, x_start, x_end;
3110  automatic_differentiation_indexing_1( compute_dRdW, compute_dRdX, compute_d2R,
3111  n_soln_dofs, n_metric_dofs,
3112  w_start, w_end, x_start, x_end );
3113 
3114  unsigned int i_derivative = 0;
3115  const unsigned int n_total_indep = x_end;
3116 
3117  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
3118  const real val = this->solution(soln_dof_indices[idof]);
3119  soln_coeff[idof] = val;
3120  soln_coeff[idof].val() = val;
3121 
3122  if (compute_dRdW || compute_d2R) soln_coeff[idof].diff(i_derivative, n_total_indep);
3123  if (compute_d2R) soln_coeff[idof].val().diff(i_derivative, n_total_indep);
3124 
3125  if (compute_dRdW || compute_d2R) i_derivative++;
3126  }
3127  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
3128  const real val = this->high_order_grid->volume_nodes[metric_dof_indices[idof]];
3129  coords_coeff[idof] = val;
3130  coords_coeff[idof].val() = val;
3131 
3132  if (compute_dRdX || compute_d2R) coords_coeff[idof].diff(i_derivative, n_total_indep);
3133  if (compute_d2R) coords_coeff[idof].val().diff(i_derivative, n_total_indep);
3134 
3135  if (compute_dRdX || compute_d2R) i_derivative++;
3136  }
3137 
3138  AssertDimension(i_derivative, n_total_indep);
3139 
3140  FadFadType dual_dot_residual = 0.0;
3141  std::vector<FadFadType> rhs(n_soln_dofs);
3142  assemble_volume_term<FadFadType>(
3143  cell,
3144  current_cell_index,
3145  soln_coeff, coords_coeff, local_dual,
3146  fe_soln, fe_metric, quadrature,
3148  rhs, dual_dot_residual,
3149  compute_metric_derivatives, fe_values_vol);
3150 
3151  // Weak form
3152  // The right-hand side sends all the term to the side of the source term
3153  // Therefore,
3154  // \divergence ( Fconv + Fdiss ) = source
3155  // has the right-hand side
3156  // rhs = - \divergence( Fconv + Fdiss ) + source
3157  // Since we have done an integration by parts, the volume term resulting from the divergence of Fconv and Fdiss
3158  // is negative. Therefore, negative of negative means we add that volume term to the right-hand-side
3159  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3160 
3161  if (compute_dRdW) {
3162  std::vector<real> residual_derivatives(n_soln_dofs);
3163  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
3164  const unsigned int i_dx = idof+w_start;
3165  residual_derivatives[idof] = rhs[itest].dx(i_dx).val();
3166  AssertIsFinite(residual_derivatives[idof]);
3167  }
3168  const bool elide_zero_values = false;
3169  this->system_matrix.add(soln_dof_indices[itest], soln_dof_indices, residual_derivatives, elide_zero_values);
3170  }
3171  if (compute_dRdX) {
3172  std::vector<real> residual_derivatives(n_metric_dofs);
3173  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
3174  const unsigned int i_dx = idof+x_start;
3175  residual_derivatives[idof] = rhs[itest].dx(i_dx).val();
3176  }
3177  this->dRdXv.add(soln_dof_indices[itest], metric_dof_indices, residual_derivatives);
3178  }
3179  //if (compute_d2R) {
3180  // const unsigned int global_residual_row = soln_dof_indices[itest];
3181  // dual_dot_residual += this->dual[global_residual_row]*rhs[itest];
3182  //}
3183 
3184  local_rhs_cell(itest) += rhs[itest].val().val();
3185  AssertIsFinite(local_rhs_cell(itest));
3186 
3187  }
3188 
3189 
3190  if (compute_d2R) {
3191 
3192  std::vector<real> dWidW(n_soln_dofs);
3193  std::vector<real> dWidX(n_metric_dofs);
3194  std::vector<real> dXidX(n_metric_dofs);
3195 
3196  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
3197 
3198  const unsigned int i_dx = idof+w_start;
3199  const FadType dWi = dual_dot_residual.dx(i_dx);
3200 
3201  for (unsigned int jdof=0; jdof<n_soln_dofs; ++jdof) {
3202  const unsigned int j_dx = jdof+w_start;
3203  dWidW[jdof] = dWi.dx(j_dx);
3204  }
3205  this->d2RdWdW.add(soln_dof_indices[idof], soln_dof_indices, dWidW);
3206 
3207  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
3208  const unsigned int j_dx = jdof+x_start;
3209  dWidX[jdof] = dWi.dx(j_dx);
3210  }
3211  this->d2RdWdX.add(soln_dof_indices[idof], metric_dof_indices, dWidX);
3212  }
3213 
3214  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
3215 
3216  const unsigned int i_dx = idof+x_start;
3217  const FadType dXi = dual_dot_residual.dx(i_dx);
3218 
3219  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
3220  const unsigned int j_dx = jdof+x_start;
3221  dXidX[jdof] = dXi.dx(j_dx);
3222  }
3223  this->d2RdXdX.add(metric_dof_indices[idof], metric_dof_indices, dXidX);
3224  }
3225  }
3226 
3227 }
3228 #endif
3229 #ifndef FADFAD
3230 template <int dim, int nstate, typename real, typename MeshType>
3231 template <typename real2>
3233  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
3234  const dealii::types::global_dof_index current_cell_index,
3235  const dealii::FEValues<dim,dim> &fe_values_vol,
3236  const dealii::FESystem<dim,dim> &fe_soln,
3237  const dealii::Quadrature<dim> &quadrature,
3238  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
3239  const std::vector<dealii::types::global_dof_index> &soln_dof_indices,
3240  dealii::Vector<real> &local_rhs_cell,
3241  const dealii::FEValues<dim,dim> &fe_values_lagrange,
3243  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3244 {
3245  (void) fe_values_lagrange;
3246 
3247  using adtype = real2;
3248 
3249  const unsigned int n_soln_dofs = fe_soln.dofs_per_cell;
3250 
3251  AssertDimension (n_soln_dofs, soln_dof_indices.size());
3252 
3253  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
3254  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
3255 
3256  LocalSolution<adtype, dim, nstate> local_solution(fe_soln);
3257  LocalSolution<adtype, dim, dim> local_metric(fe_metric);
3258 
3259  std::vector<real> local_dual(n_soln_dofs);
3260  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3261  const unsigned int global_residual_row = soln_dof_indices[itest];
3262  local_dual[itest] = this->dual[global_residual_row];
3263  }
3264 
3265  (void) compute_dRdW; (void) compute_dRdX; (void) compute_d2R;
3266  const bool compute_metric_derivatives = true;//(!compute_dRdX && !compute_d2R) ? false : true;
3267 
3268  unsigned int w_start, w_end, x_start, x_end;
3269  automatic_differentiation_indexing_1( compute_dRdW, compute_dRdX, compute_d2R,
3270  n_soln_dofs, n_metric_dofs,
3271  w_start, w_end, x_start, x_end );
3272 
3273  using TH = codi::TapeHelper<adtype>;
3274  TH th;
3275  adtype::getGlobalTape();
3276  if (compute_dRdW || compute_dRdX || compute_d2R) {
3277  th.startRecording();
3278  }
3279  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
3280  const real val = this->solution(soln_dof_indices[idof]);
3281  local_solution.coefficients[idof] = val;
3282 
3283  if (compute_dRdW || compute_d2R) {
3284  th.registerInput(local_solution.coefficients[idof]);
3285  } else {
3286  adtype::getGlobalTape().deactivateValue(local_solution.coefficients[idof]);
3287  }
3288  }
3289  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
3290  const real val = this->high_order_grid->volume_nodes[metric_dof_indices[idof]];
3291  local_metric.coefficients[idof] = val;
3292 
3293  if (compute_dRdX || compute_d2R) {
3294  th.registerInput(local_metric.coefficients[idof]);
3295  } else {
3296  adtype::getGlobalTape().deactivateValue(local_metric.coefficients[idof]);
3297  }
3298  }
3299 
3300  adtype dual_dot_residual = 0.0;
3301  std::vector<adtype> rhs(n_soln_dofs);
3302  assemble_volume_term<adtype>(
3303  cell,
3304  current_cell_index,
3305  local_solution, local_metric,
3306  local_dual,
3307  quadrature,
3308  physics,
3309  rhs, dual_dot_residual,
3310  compute_metric_derivatives, fe_values_vol);
3311 
3312  if (compute_dRdW || compute_dRdX) {
3313  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3314  th.registerOutput(rhs[itest]);
3315  }
3316  } else if (compute_d2R) {
3317  th.registerOutput(dual_dot_residual);
3318  }
3319  if (compute_dRdW || compute_dRdX || compute_d2R) {
3320  th.stopRecording();
3321  }
3322 
3323  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3324  local_rhs_cell(itest) += getValue<adtype>(rhs[itest]);
3325  AssertIsFinite(local_rhs_cell(itest));
3326  }
3327 
3328  if (compute_dRdW) {
3329  typename TH::JacobianType& jac = th.createJacobian();
3330  th.evalJacobian(jac);
3331  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3332 
3333  std::vector<real> residual_derivatives(n_soln_dofs);
3334  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
3335  const unsigned int i_dx = idof+w_start;
3336  residual_derivatives[idof] = jac(itest,i_dx);
3337  AssertIsFinite(residual_derivatives[idof]);
3338  }
3339  const bool elide_zero_values = false;
3340  this->system_matrix.add(soln_dof_indices[itest], soln_dof_indices, residual_derivatives, elide_zero_values);
3341  }
3342  th.deleteJacobian(jac);
3343 
3344  }
3345 
3346  if (compute_dRdX) {
3347  typename TH::JacobianType& jac = th.createJacobian();
3348  th.evalJacobian(jac);
3349  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3350  std::vector<real> residual_derivatives(n_metric_dofs);
3351  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
3352  const unsigned int i_dx = idof+x_start;
3353  residual_derivatives[idof] = jac(itest,i_dx);
3354  }
3355  this->dRdXv.add(soln_dof_indices[itest], metric_dof_indices, residual_derivatives);
3356  }
3357  th.deleteJacobian(jac);
3358  }
3359 
3360 
3361  if (compute_d2R) {
3362  typename TH::HessianType& hes = th.createHessian();
3363  th.evalHessian(hes);
3364 
3365  int i_dependent = (compute_dRdW || compute_dRdX) ? n_soln_dofs : 0;
3366 
3367  std::vector<real> dWidW(n_soln_dofs);
3368  std::vector<real> dWidX(n_metric_dofs);
3369  std::vector<real> dXidX(n_metric_dofs);
3370 
3371  for (unsigned int idof=0; idof<n_soln_dofs; ++idof) {
3372 
3373  const unsigned int i_dx = idof+w_start;
3374 
3375  for (unsigned int jdof=0; jdof<n_soln_dofs; ++jdof) {
3376  const unsigned int j_dx = jdof+w_start;
3377  dWidW[jdof] = hes(i_dependent,i_dx,j_dx);
3378  }
3379  this->d2RdWdW.add(soln_dof_indices[idof], soln_dof_indices, dWidW);
3380 
3381  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
3382  const unsigned int j_dx = jdof+x_start;
3383  dWidX[jdof] = hes(i_dependent,i_dx,j_dx);
3384  }
3385  this->d2RdWdX.add(soln_dof_indices[idof], metric_dof_indices, dWidX);
3386  }
3387 
3388  for (unsigned int idof=0; idof<n_metric_dofs; ++idof) {
3389 
3390  const unsigned int i_dx = idof+x_start;
3391 
3392  for (unsigned int jdof=0; jdof<n_metric_dofs; ++jdof) {
3393  const unsigned int j_dx = jdof+x_start;
3394  dXidX[jdof] = hes(i_dependent,i_dx,j_dx);
3395  }
3396  this->d2RdXdX.add(metric_dof_indices[idof], metric_dof_indices, dXidX);
3397  }
3398 
3399  th.deleteHessian(hes);
3400  }
3401 
3402  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
3403  adtype::getGlobalTape().deactivateValue(local_solution.coefficients[idof]);
3404  }
3405  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
3406  adtype::getGlobalTape().deactivateValue(local_metric.coefficients[idof]);
3407  }
3408 
3409 }
3410 
3411 template <int dim, int nstate, typename real, typename MeshType>
3413  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
3414  const dealii::types::global_dof_index current_cell_index,
3415  const dealii::FEValues<dim,dim> &fe_values_vol,
3416  const dealii::FESystem<dim,dim> &fe_soln,
3417  const dealii::Quadrature<dim> &quadrature,
3418  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
3419  const std::vector<dealii::types::global_dof_index> &soln_dof_indices,
3420  dealii::Vector<real> &local_rhs_cell,
3421  const dealii::FEValues<dim,dim> &fe_values_lagrange,
3423  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3424 {
3425  (void) fe_values_lagrange;
3426  (void) compute_dRdW;
3427  (void) compute_dRdX;
3428  (void) compute_d2R;
3429  assert( !compute_dRdW && !compute_dRdX && !compute_d2R);
3430  (void) compute_dRdW; (void) compute_dRdX; (void) compute_d2R;
3431  const bool compute_metric_derivatives = true;//(!compute_dRdX && !compute_d2R) ? false : true;
3432 
3433  const dealii::FESystem<dim> &fe_metric = this->high_order_grid->fe_system;
3434  const unsigned int n_metric_dofs = fe_metric.dofs_per_cell;
3435  const unsigned int n_soln_dofs = fe_soln.dofs_per_cell;
3436 
3437  AssertDimension (n_soln_dofs, soln_dof_indices.size());
3438 
3439  LocalSolution<double, dim, nstate> local_solution(fe_soln);
3440  LocalSolution<double, dim, dim> local_metric(fe_metric);
3441 
3442  std::vector<real> local_dual(n_soln_dofs);
3443  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3444  const unsigned int global_residual_row = soln_dof_indices[itest];
3445  local_dual[itest] = this->dual[global_residual_row];
3446  }
3447 
3448  for (unsigned int idof = 0; idof < n_soln_dofs; ++idof) {
3449  const real val = this->solution(soln_dof_indices[idof]);
3450  local_solution.coefficients[idof] = val;
3451  }
3452  for (unsigned int idof = 0; idof < n_metric_dofs; ++idof) {
3453  const real val = this->high_order_grid->volume_nodes[metric_dof_indices[idof]];
3454  local_metric.coefficients[idof] = val;
3455  }
3456 
3457  double dual_dot_residual = 0.0;
3458  std::vector<double> rhs(n_soln_dofs);
3459  assemble_volume_term<double>(
3460  cell,
3461  current_cell_index,
3462  local_solution, local_metric, local_dual,
3463  quadrature,
3464  physics,
3465  rhs, dual_dot_residual,
3466  compute_metric_derivatives, fe_values_vol);
3467 
3468  for (unsigned int itest=0; itest<n_soln_dofs; ++itest) {
3469  local_rhs_cell(itest) += getValue<double>(rhs[itest]);
3470  AssertIsFinite(local_rhs_cell(itest));
3471  }
3472 }
3473 
3474 template <int dim, int nstate, typename real, typename MeshType>
3476  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
3477  const dealii::types::global_dof_index current_cell_index,
3478  const dealii::FEValues<dim,dim> &fe_values_vol,
3479  const dealii::FESystem<dim,dim> &fe_soln,
3480  const dealii::Quadrature<dim> &quadrature,
3481  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
3482  const std::vector<dealii::types::global_dof_index> &soln_dof_indices,
3483  dealii::Vector<real> &local_rhs_cell,
3484  const dealii::FEValues<dim,dim> &fe_values_lagrange,
3485  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3486 {
3487  (void) current_cell_index;
3488  (void) fe_values_lagrange;
3489  if (compute_d2R) {
3490  assemble_volume_codi_taped_derivatives<codi_HessianComputationType>(
3491  cell,
3492  current_cell_index,
3493  fe_values_vol,
3494  fe_soln, quadrature,
3495  metric_dof_indices, soln_dof_indices,
3496  local_rhs_cell,
3497  fe_values_lagrange,
3499  compute_dRdW, compute_dRdX, compute_d2R);
3500  } else if (compute_dRdW || compute_dRdX) {
3501  assemble_volume_codi_taped_derivatives<codi_JacobianComputationType>(
3502  cell,
3503  current_cell_index,
3504  fe_values_vol,
3505  fe_soln, quadrature,
3506  metric_dof_indices, soln_dof_indices,
3507  local_rhs_cell,
3508  fe_values_lagrange,
3510  compute_dRdW, compute_dRdX, compute_d2R);
3511  } else {
3513  cell,
3514  current_cell_index,
3515  fe_values_vol,
3516  fe_soln, quadrature,
3517  metric_dof_indices, soln_dof_indices,
3518  local_rhs_cell,
3519  fe_values_lagrange,
3521  compute_dRdW, compute_dRdX, compute_d2R);
3522  }
3523 }
3524 
3525 template <int dim, int nstate, typename real, typename MeshType>
3527  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
3528  const dealii::types::global_dof_index current_cell_index,
3529  const dealii::types::global_dof_index neighbor_cell_index,
3530  const std::pair<unsigned int, int> face_subface_int,
3531  const std::pair<unsigned int, int> face_subface_ext,
3532  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_int,
3533  const typename dealii::QProjector<dim>::DataSetDescriptor face_data_set_ext,
3534  const dealii::FEFaceValuesBase<dim,dim> &fe_values_int,
3535  const dealii::FEFaceValuesBase<dim,dim> &fe_values_ext,
3536  const real penalty,
3537  const dealii::FESystem<dim,dim> &fe_int,
3538  const dealii::FESystem<dim,dim> &fe_ext,
3539  const dealii::Quadrature<dim-1> &face_quadrature,
3540  const std::vector<dealii::types::global_dof_index> &metric_dof_indices_int,
3541  const std::vector<dealii::types::global_dof_index> &metric_dof_indices_ext,
3542  const std::vector<dealii::types::global_dof_index> &soln_dof_indices_int,
3543  const std::vector<dealii::types::global_dof_index> &soln_dof_indices_ext,
3544  dealii::Vector<real> &local_rhs_int_cell,
3545  dealii::Vector<real> &local_rhs_ext_cell,
3546  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3547 {
3548  (void) current_cell_index;
3549  (void) neighbor_cell_index;
3550  if (compute_d2R) {
3551  assemble_face_codi_taped_derivatives<codi_HessianComputationType>(
3552  cell,
3553  current_cell_index,
3554  neighbor_cell_index,
3555  face_subface_int,
3556  face_subface_ext,
3557  face_data_set_int,
3558  face_data_set_ext,
3559  fe_values_int,
3560  fe_values_ext,
3561  penalty,
3562  fe_int,
3563  fe_ext,
3564  face_quadrature,
3565  metric_dof_indices_int,
3566  metric_dof_indices_ext,
3567  soln_dof_indices_int,
3568  soln_dof_indices_ext,
3572  local_rhs_int_cell,
3573  local_rhs_ext_cell,
3574  compute_dRdW, compute_dRdX, compute_d2R);
3575  } else if (compute_dRdW || compute_dRdX) {
3576  assemble_face_codi_taped_derivatives<codi_JacobianComputationType>(
3577  cell,
3578  current_cell_index,
3579  neighbor_cell_index,
3580  face_subface_int,
3581  face_subface_ext,
3582  face_data_set_int,
3583  face_data_set_ext,
3584  fe_values_int,
3585  fe_values_ext,
3586  penalty,
3587  fe_int,
3588  fe_ext,
3589  face_quadrature,
3590  metric_dof_indices_int,
3591  metric_dof_indices_ext,
3592  soln_dof_indices_int,
3593  soln_dof_indices_ext,
3597  local_rhs_int_cell,
3598  local_rhs_ext_cell,
3599  compute_dRdW, compute_dRdX, compute_d2R);
3600  } else {
3602  cell,
3603  current_cell_index,
3604  neighbor_cell_index,
3605  face_subface_int,
3606  face_subface_ext,
3607  face_data_set_int,
3608  face_data_set_ext,
3609  fe_values_int,
3610  fe_values_ext,
3611  penalty,
3612  fe_int,
3613  fe_ext,
3614  face_quadrature,
3615  metric_dof_indices_int,
3616  metric_dof_indices_ext,
3617  soln_dof_indices_int,
3618  soln_dof_indices_ext,
3622  local_rhs_int_cell,
3623  local_rhs_ext_cell,
3624  compute_dRdW, compute_dRdX, compute_d2R);
3625  }
3626 }
3627 #endif
3628 
3629 
3630 template <int dim, int nstate, typename real, typename MeshType>
3632  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
3633  const dealii::types::global_dof_index current_cell_index,
3634  const std::vector<dealii::types::global_dof_index> &cell_dofs_indices,
3635  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
3636  const unsigned int poly_degree,
3637  const unsigned int grid_degree,
3640  OPERATOR::local_basis_stiffness<dim,2*dim,real> &/*flux_basis_stiffness*/,
3641  OPERATOR::vol_projection_operator<dim,2*dim,real> &/*soln_basis_projection_oper_int*/,
3642  OPERATOR::vol_projection_operator<dim,2*dim,real> &/*soln_basis_projection_oper_ext*/,
3645  std::array<std::vector<real>,dim> &/*mapping_support_points*/,
3646  dealii::hp::FEValues<dim,dim> &fe_values_collection_volume,
3647  dealii::hp::FEValues<dim,dim> &fe_values_collection_volume_lagrange,
3648  const dealii::FESystem<dim,dim> &current_fe_ref,
3649  dealii::Vector<real> &local_rhs_int_cell,
3650  std::vector<dealii::Tensor<1,dim,real>> &/*local_auxiliary_RHS*/,
3651  const bool /*compute_auxiliary_right_hand_side*/,
3652  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3653 {
3654  // Current reference element related to this physical cell
3655  const int i_fele = cell->active_fe_index();
3656  const int i_quad = i_fele;
3657  const int i_mapp = 0;
3658  fe_values_collection_volume.reinit (cell, i_quad, i_mapp, i_fele);
3659  dealii::TriaIterator<dealii::CellAccessor<dim,dim>> cell_iterator = static_cast<dealii::TriaIterator<dealii::CellAccessor<dim,dim>> > (cell);
3660  fe_values_collection_volume_lagrange.reinit (cell_iterator, i_quad, i_mapp, i_fele);
3661 
3662  const dealii::FEValues<dim,dim> &fe_values_volume = fe_values_collection_volume.get_present_fe_values();
3663  const dealii::FEValues<dim,dim> &fe_values_lagrange = fe_values_collection_volume_lagrange.get_present_fe_values();
3664  //Note the explicit is called first to set the max_dt_cell to a non-zero value.
3666  cell,
3667  current_cell_index,
3668  fe_values_volume,
3669  cell_dofs_indices,
3670  metric_dof_indices,
3671  poly_degree, grid_degree,
3672  local_rhs_int_cell,
3673  fe_values_lagrange);
3674  //set current rhs to zero since the explicit call was just to set the max_dt_cell.
3675  local_rhs_int_cell*=0.0;
3676 
3678  cell,
3679  current_cell_index,
3680  fe_values_volume, current_fe_ref, this->volume_quadrature_collection[i_quad],
3681  metric_dof_indices, cell_dofs_indices,
3682  local_rhs_int_cell, fe_values_lagrange,
3683  compute_dRdW, compute_dRdX, compute_d2R);
3684 }
3685 
3686 template <int dim, int nstate, typename real, typename MeshType>
3688  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
3689  const dealii::types::global_dof_index current_cell_index,
3690  const unsigned int iface,
3691  const unsigned int boundary_id,
3692  const real penalty,
3693  const std::vector<dealii::types::global_dof_index> &cell_dofs_indices,
3694  const std::vector<dealii::types::global_dof_index> &metric_dof_indices,
3695  const unsigned int /*poly_degree*/,
3696  const unsigned int /*grid_degree*/,
3699  OPERATOR::local_basis_stiffness<dim,2*dim,real> &/*flux_basis_stiffness*/,
3700  OPERATOR::vol_projection_operator<dim,2*dim,real> &/*soln_basis_projection_oper_int*/,
3701  OPERATOR::vol_projection_operator<dim,2*dim,real> &/*soln_basis_projection_oper_ext*/,
3704  std::array<std::vector<real>,dim> &/*mapping_support_points*/,
3705  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_int,
3706  const dealii::FESystem<dim,dim> &current_fe_ref,
3707  dealii::Vector<real> &local_rhs_int_cell,
3708  std::vector<dealii::Tensor<1,dim,real>> &/*local_auxiliary_RHS*/,
3709  const bool /*compute_auxiliary_right_hand_side*/,
3710  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3711 {
3712  // Current reference element related to this physical cell
3713  const int i_fele = cell->active_fe_index();
3714  const int i_quad = i_fele;
3715  const int i_mapp = 0;
3716 
3717  fe_values_collection_face_int.reinit (cell, iface, i_quad, i_mapp, i_fele);
3718  const dealii::FEFaceValues<dim,dim> &fe_values_face_int = fe_values_collection_face_int.get_present_fe_values();
3719  const dealii::Quadrature<dim-1> face_quadrature = this->face_quadrature_collection[i_quad];
3721  cell,
3722  current_cell_index,
3723  iface, boundary_id, fe_values_face_int, penalty,
3724  current_fe_ref, face_quadrature,
3725  metric_dof_indices, cell_dofs_indices, local_rhs_int_cell,
3726  compute_dRdW, compute_dRdX, compute_d2R);
3727 }
3728 
3729 template <int dim, int nstate, typename real, typename MeshType>
3731  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
3732  typename dealii::DoFHandler<dim>::active_cell_iterator neighbor_cell,
3733  const dealii::types::global_dof_index current_cell_index,
3734  const dealii::types::global_dof_index neighbor_cell_index,
3735  const unsigned int iface,
3736  const unsigned int neighbor_iface,
3737  const real penalty,
3738  const std::vector<dealii::types::global_dof_index> &current_dofs_indices,
3739  const std::vector<dealii::types::global_dof_index> &neighbor_dofs_indices,
3740  const std::vector<dealii::types::global_dof_index> &current_metric_dofs_indices,
3741  const std::vector<dealii::types::global_dof_index> &neighbor_metric_dofs_indices,
3742  const unsigned int /*poly_degree_int*/,
3743  const unsigned int /*poly_degree_ext*/,
3744  const unsigned int /*grid_degree_int*/,
3745  const unsigned int /*grid_degree_ext*/,
3746  OPERATOR::basis_functions<dim,2*dim,real> &/*soln_basis_int*/,
3747  OPERATOR::basis_functions<dim,2*dim,real> &/*soln_basis_ext*/,
3748  OPERATOR::basis_functions<dim,2*dim,real> &/*flux_basis_int*/,
3749  OPERATOR::basis_functions<dim,2*dim,real> &/*flux_basis_ext*/,
3750  OPERATOR::local_basis_stiffness<dim,2*dim,real> &/*flux_basis_stiffness*/,
3751  OPERATOR::vol_projection_operator<dim,2*dim,real> &/*soln_basis_projection_oper_int*/,
3752  OPERATOR::vol_projection_operator<dim,2*dim,real> &/*soln_basis_projection_oper_ext*/,
3753  OPERATOR::metric_operators<real,dim,2*dim> &/*metric_oper_int*/,
3754  OPERATOR::metric_operators<real,dim,2*dim> &/*metric_oper_ext*/,
3756  std::array<std::vector<real>,dim> &/*mapping_support_points*/,
3757  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_int,
3758  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_ext,
3759  dealii::Vector<real> &current_cell_rhs,
3760  dealii::Vector<real> &neighbor_cell_rhs,
3761  std::vector<dealii::Tensor<1,dim,real>> &/*current_cell_rhs_aux*/,
3762  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
3763  std::array<dealii::LinearAlgebra::distributed::Vector<double>,dim> &/*rhs_aux*/,
3764  const bool /*compute_auxiliary_right_hand_side*/,
3765  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3766 {
3767  // Current reference element related to this physical cell
3768  const int i_fele = cell->active_fe_index();
3769  const int i_quad = i_fele;
3770  const int i_mapp = 0;
3771  const int i_fele_n = neighbor_cell->active_fe_index(), i_quad_n = i_fele_n, i_mapp_n = 0;
3772 
3773  fe_values_collection_face_int.reinit (cell, iface, i_quad, i_mapp, i_fele);
3774  fe_values_collection_face_ext.reinit (neighbor_cell, neighbor_iface, i_quad_n, i_mapp_n, i_fele_n);
3775 
3776  //only need to compute fevalues for the weak form.
3777  const dealii::FEFaceValues<dim,dim> &fe_values_face_int = fe_values_collection_face_int.get_present_fe_values();
3778  const dealii::FEFaceValues<dim,dim> &fe_values_face_ext = fe_values_collection_face_ext.get_present_fe_values();
3779  const dealii::Quadrature<dim-1> &used_face_quadrature = this->face_quadrature_collection[(i_quad_n > i_quad) ? i_quad_n : i_quad]; // Use larger quadrature order on the face
3780 
3781  std::pair<unsigned int, int> face_subface_int = std::make_pair(iface, -1);
3782  std::pair<unsigned int, int> face_subface_ext = std::make_pair(neighbor_iface, -1);
3783  const auto face_data_set_int = dealii::QProjector<dim>::DataSetDescriptor::face (
3784  dealii::ReferenceCell::get_hypercube(dim),
3785  iface,
3786  cell->face_orientation(iface),
3787  cell->face_flip(iface),
3788  cell->face_rotation(iface),
3789  used_face_quadrature.size());
3790  const auto face_data_set_ext = dealii::QProjector<dim>::DataSetDescriptor::face (
3791  dealii::ReferenceCell::get_hypercube(dim),
3792  neighbor_iface,
3793  neighbor_cell->face_orientation(neighbor_iface),
3794  neighbor_cell->face_flip(neighbor_iface),
3795  neighbor_cell->face_rotation(neighbor_iface),
3796  used_face_quadrature.size());
3797 
3799  cell,
3800  current_cell_index,
3801  neighbor_cell_index,
3802  face_subface_int, face_subface_ext,
3803  face_data_set_int,
3804  face_data_set_ext,
3805  fe_values_face_int, fe_values_face_ext,
3806  penalty,
3807  this->fe_collection[i_fele], this->fe_collection[i_fele_n],
3808  used_face_quadrature,
3809  current_metric_dofs_indices, neighbor_metric_dofs_indices,
3810  current_dofs_indices, neighbor_dofs_indices,
3811  current_cell_rhs, neighbor_cell_rhs,
3812  compute_dRdW, compute_dRdX, compute_d2R);
3813 
3814  // Add local contribution from neighbor cell to global vector
3815  const unsigned int n_dofs_neigh_cell = this->fe_collection[neighbor_cell->active_fe_index()].n_dofs_per_cell();
3816  for (unsigned int i=0; i<n_dofs_neigh_cell; ++i) {
3817  rhs[neighbor_dofs_indices[i]] += neighbor_cell_rhs[i];
3818  }
3819 }
3820 
3821 template <int dim, int nstate, typename real, typename MeshType>
3823  typename dealii::DoFHandler<dim>::active_cell_iterator cell,
3824  typename dealii::DoFHandler<dim>::active_cell_iterator neighbor_cell,
3825  const dealii::types::global_dof_index current_cell_index,
3826  const dealii::types::global_dof_index neighbor_cell_index,
3827  const unsigned int iface,
3828  const unsigned int neighbor_iface,
3829  const unsigned int neighbor_i_subface,
3830  const real penalty,
3831  const std::vector<dealii::types::global_dof_index> &current_dofs_indices,
3832  const std::vector<dealii::types::global_dof_index> &neighbor_dofs_indices,
3833  const std::vector<dealii::types::global_dof_index> &current_metric_dofs_indices,
3834  const std::vector<dealii::types::global_dof_index> &neighbor_metric_dofs_indices,
3835  const unsigned int /*poly_degree_int*/,
3836  const unsigned int /*poly_degree_ext*/,
3837  const unsigned int /*grid_degree_int*/,
3838  const unsigned int /*grid_degree_ext*/,
3839  OPERATOR::basis_functions<dim,2*dim,real> &/*soln_basis_int*/,
3840  OPERATOR::basis_functions<dim,2*dim,real> &/*soln_basis_ext*/,
3841  OPERATOR::basis_functions<dim,2*dim,real> &/*flux_basis_int*/,
3842  OPERATOR::basis_functions<dim,2*dim,real> &/*flux_basis_ext*/,
3843  OPERATOR::local_basis_stiffness<dim,2*dim,real> &/*flux_basis_stiffness*/,
3844  OPERATOR::vol_projection_operator<dim,2*dim,real> &/*soln_basis_projection_oper_int*/,
3845  OPERATOR::vol_projection_operator<dim,2*dim,real> &/*soln_basis_projection_oper_ext*/,
3846  OPERATOR::metric_operators<real,dim,2*dim> &/*metric_oper_int*/,
3847  OPERATOR::metric_operators<real,dim,2*dim> &/*metric_oper_ext*/,
3849  std::array<std::vector<real>,dim> &/*mapping_support_points*/,
3850  dealii::hp::FEFaceValues<dim,dim> &fe_values_collection_face_int,
3851  dealii::hp::FESubfaceValues<dim,dim> &fe_values_collection_subface,
3852  dealii::Vector<real> &current_cell_rhs,
3853  dealii::Vector<real> &neighbor_cell_rhs,
3854  std::vector<dealii::Tensor<1,dim,real>> &/*current_cell_rhs_aux*/,
3855  dealii::LinearAlgebra::distributed::Vector<double> &rhs,
3856  std::array<dealii::LinearAlgebra::distributed::Vector<double>,dim> &/*rhs_aux*/,
3857  const bool /*compute_auxiliary_right_hand_side*/,
3858  const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
3859 {
3860  // Current reference element related to this physical cell
3861  const int i_fele = cell->active_fe_index();
3862  const int i_quad = i_fele;
3863  const int i_mapp = 0;
3864  const int i_fele_n = neighbor_cell->active_fe_index(), i_quad_n = i_fele_n, i_mapp_n = 0;
3865 
3866  fe_values_collection_face_int.reinit (cell, iface, i_quad, i_mapp, i_fele);
3867  fe_values_collection_subface.reinit (neighbor_cell, neighbor_iface, neighbor_i_subface, i_quad_n, i_mapp_n, i_fele_n);
3868 
3869  const dealii::FEFaceValues<dim,dim> &fe_values_face_int = fe_values_collection_face_int.get_present_fe_values();
3870  const dealii::FESubfaceValues<dim,dim> &fe_values_face_ext = fe_values_collection_subface.get_present_fe_values();
3871  const dealii::Quadrature<dim-1> &used_face_quadrature = this->face_quadrature_collection[(i_quad_n > i_quad) ? i_quad_n : i_quad]; // Use larger quadrature order on the face
3872  std::pair<unsigned int, int> face_subface_int = std::make_pair(iface, -1);
3873  std::pair<unsigned int, int> face_subface_ext = std::make_pair(neighbor_iface, (int)neighbor_i_subface);
3874 
3875  const auto face_data_set_int = dealii::QProjector<dim>::DataSetDescriptor::face(
3876  dealii::ReferenceCell::get_hypercube(dim),
3877  iface,
3878  cell->face_orientation(iface),
3879  cell->face_flip(iface),
3880  cell->face_rotation(iface),
3881  used_face_quadrature.size());
3882  const auto face_data_set_ext = dealii::QProjector<dim>::DataSetDescriptor::subface (
3883  dealii::ReferenceCell::get_hypercube(dim),
3884  neighbor_iface,
3885  neighbor_i_subface,
3886  neighbor_cell->face_orientation(neighbor_iface),
3887  neighbor_cell->face_flip(neighbor_iface),
3888  neighbor_cell->face_rotation(neighbor_iface),
3889  used_face_quadrature.size(),
3890  neighbor_cell->subface_case(neighbor_iface));
3891 
3893  cell,
3894  current_cell_index,
3895  neighbor_cell_index,
3896  face_subface_int, face_subface_ext,
3897  face_data_set_int,
3898  face_data_set_ext,
3899  fe_values_face_int, fe_values_face_ext,
3900  penalty,
3901  this->fe_collection[i_fele], this->fe_collection[i_fele_n],
3902  used_face_quadrature,
3903  current_metric_dofs_indices, neighbor_metric_dofs_indices,
3904  current_dofs_indices, neighbor_dofs_indices,
3905  current_cell_rhs, neighbor_cell_rhs,
3906  compute_dRdW, compute_dRdX, compute_d2R);
3907 
3908  // Add local contribution from neighbor cell to global vector
3909  const unsigned int n_dofs_neigh_cell = this->fe_collection[neighbor_cell->active_fe_index()].n_dofs_per_cell();
3910  for (unsigned int i=0; i<n_dofs_neigh_cell; ++i) {
3911  rhs[neighbor_dofs_indices[i]] += neighbor_cell_rhs[i];
3912  }
3913 
3914 }
3915 
3916 template <int dim, int nstate, typename real, typename MeshType>
3918 {
3919  //Do Nothing.
3920 }
3921 
3922 template <int dim, int nstate, typename real, typename MeshType>
3924 {
3925  this->dual.reinit(this->locally_owned_dofs, this->ghost_dofs, this->mpi_communicator);
3926 }
3927 
3928 // using default MeshType = Triangulation
3929 // 1D: dealii::Triangulation<dim>;
3930 // Otherwise: dealii::parallel::distributed::Triangulation<dim>;
3937 
3944 
3945 #if PHILIP_DIM!=1
3952 #endif
3953 
3954 } // PHiLiP namespace
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:2932
void assemble_face_term_derivatives(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const dealii::types::global_dof_index neighbor_cell_index, const std::pair< unsigned int, int > face_subface_int, const std::pair< unsigned int, int > face_subface_ext, const typename dealii::QProjector< dim >::DataSetDescriptor face_data_set_int, const typename dealii::QProjector< dim >::DataSetDescriptor face_data_set_ext, const dealii::FEFaceValuesBase< dim, dim > &, const dealii::FEFaceValuesBase< dim, dim > &, const real penalty, const dealii::FESystem< dim, dim > &fe_int, const dealii::FESystem< dim, dim > &fe_ext, const dealii::Quadrature< dim-1 > &face_quadrature, const std::vector< dealii::types::global_dof_index > &metric_dof_indices_int, const std::vector< dealii::types::global_dof_index > &metric_dof_indices_ext, const std::vector< dealii::types::global_dof_index > &soln_dof_indices_int, const std::vector< dealii::types::global_dof_index > &soln_dof_indices_ext, dealii::Vector< real > &local_rhs_int_cell, dealii::Vector< real > &local_rhs_ext_cell, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Evaluate the integral over the internal cell edges and its specified derivatives. ...
Definition: weak_dg.cpp:3526
dealii::Vector< double > artificial_dissipation_coeffs
Artificial dissipation in each cell.
Definition: dg_base.hpp:462
Sacado::Fad::DFad< FadType > FadFadType
Sacado AD type that allows 2nd derivatives.
Definition: ADTypes.hpp:12
dealii::LinearAlgebra::distributed::Vector< double > artificial_dissipation_c0
Artificial dissipation coefficients.
Definition: dg_base.hpp:673
virtual std::array< real, nstate > evaluate_solution_flux(const std::array< real, nstate > &soln_int, const std::array< real, nstate > &soln_ext, const dealii::Tensor< 1, dim, real > &normal_int) const =0
Solution flux at the interface.
Sacado::Fad::DFad< double > FadType
Sacado AD type for first derivatives.
Definition: ADTypes.hpp:11
dealii::TrilinosWrappers::SparseMatrix dRdXv
Definition: dg_base.hpp:356
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
Definition: dg_base.hpp:91
Base class from which Advection, Diffusion, ConvectionDiffusion, and Euler is derived.
Definition: physics.h:34
dealii::LinearAlgebra::distributed::Vector< real > dual
Current optimization dual variables corresponding to the residual constraints also known as the adjoi...
Definition: dg_base.hpp:479
Class to store local solution coefficients and provide evaluation functions.
std::shared_ptr< Triangulation > triangulation
Mesh.
Definition: dg_base.hpp:160
Base class of numerical flux associated with dissipation.
Files for the baseline physics.
Definition: ADTypes.hpp:10
ManufacturedSolutionParam manufactured_solution_param
Associated manufactured solution parameters.
void assemble_boundary_term(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const LocalSolution< real2, dim, nstate > &local_solution, const LocalSolution< real2, dim, dim > &local_metric, const std::vector< real > &local_dual, const unsigned int face_number, const unsigned int boundary_id, const Physics::PhysicsBase< dim, nstate, real2 > &physics, const NumericalFlux::NumericalFluxConvective< dim, nstate, real2 > &conv_num_flux, const NumericalFlux::NumericalFluxDissipative< dim, nstate, real2 > &diss_num_flux, const dealii::FEFaceValuesBase< dim, dim > &fe_values_boundary, const real penalty, const dealii::Quadrature< dim-1 > &quadrature, std::vector< real2 > &rhs, real2 &dual_dot_residual, const bool compute_metric_derivatives)
Main function responsible for evaluating the boundary integral and the specified derivatives.
Definition: weak_dg.cpp:647
virtual void boundary_face_values(const int, const dealii::Point< dim, real > &, const dealii::Tensor< 1, dim, real > &, const std::array< real, nstate > &, const std::array< dealii::Tensor< 1, dim, real >, nstate > &, std::array< real, nstate > &, std::array< dealii::Tensor< 1, dim, real >, nstate > &) const =0
Evaluates boundary values and gradients on the other side of the face.
DGWeak class templated on the number of state variables.
Definition: weak_dg.hpp:17
dealii::TrilinosWrappers::SparseMatrix d2RdWdW
Definition: dg_base.hpp:360
MPI_Comm mpi_communicator
MPI communicator.
Definition: dg_base.hpp:893
dealii::Vector< double > max_dt_cell
Time it takes for the maximum wavespeed to cross the cell domain.
Definition: dg_base.hpp:457
Main parameter class that contains the various other sub-parameter classes.
std::vector< std::array< real, n_components > > evaluate_values(const std::vector< dealii::Point< dim >> &unit_points) const
Obtain values at unit points.
void assemble_auxiliary_residual()
Assembles the auxiliary equations&#39; residuals and solves for the auxiliary variables.
Definition: weak_dg.cpp:3917
dealii::LinearAlgebra::distributed::Vector< double > solution
Current modal coefficients of the solution.
Definition: dg_base.hpp:409
virtual void assemble_volume_term_derivatives(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const dealii::FEValues< dim, dim > &, const dealii::FESystem< dim, dim > &fe, const dealii::Quadrature< dim > &quadrature, const std::vector< dealii::types::global_dof_index > &metric_dof_indices, const std::vector< dealii::types::global_dof_index > &soln_dof_indices, dealii::Vector< real > &local_rhs_cell, const dealii::FEValues< dim, dim > &, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Evaluate the integral over the cell volume and the specified derivatives.
Definition: weak_dg.cpp:3475
ManufacturedConvergenceStudyParam manufactured_convergence_study_param
Contains parameters for manufactured convergence study.
void allocate_dual_vector()
Allocate the dual vector for optimization.
Definition: weak_dg.cpp:3923
const int nstate
Number of state variables.
Definition: dg_base.hpp:96
dealii::DoFHandler< dim > dof_handler_artificial_dissipation
Degrees of freedom handler for C0 artificial dissipation.
Definition: dg_base.hpp:670
void assemble_face_residual(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const dealii::types::global_dof_index neighbor_cell_index, const std::pair< unsigned int, int > face_subface_int, const std::pair< unsigned int, int > face_subface_ext, const typename dealii::QProjector< dim >::DataSetDescriptor face_data_set_int, const typename dealii::QProjector< dim >::DataSetDescriptor face_data_set_ext, const dealii::FEFaceValuesBase< dim, dim > &, const dealii::FEFaceValuesBase< dim, dim > &, const real penalty, const dealii::FESystem< dim, dim > &fe_int, const dealii::FESystem< dim, dim > &fe_ext, const dealii::Quadrature< dim-1 > &face_quadrature, const std::vector< dealii::types::global_dof_index > &metric_dof_indices_int, const std::vector< dealii::types::global_dof_index > &metric_dof_indices_ext, const std::vector< dealii::types::global_dof_index > &soln_dof_indices_int, const std::vector< dealii::types::global_dof_index > &soln_dof_indices_ext, const Physics::PhysicsBase< dim, nstate, real > &physics, const NumericalFlux::NumericalFluxConvective< dim, nstate, real > &conv_num_flux, const NumericalFlux::NumericalFluxDissipative< dim, nstate, real > &diss_num_flux, dealii::Vector< real > &local_rhs_int_cell, dealii::Vector< real > &local_rhs_ext_cell, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Evaluate the integral over the internal face.
Definition: weak_dg.cpp:2704
void assemble_volume_term_and_build_operators(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 > &cell_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, real > &, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::local_basis_stiffness< dim, 2 *dim, real > &, OPERATOR::vol_projection_operator< dim, 2 *dim, real > &, OPERATOR::vol_projection_operator< dim, 2 *dim, real > &, OPERATOR::metric_operators< real, dim, 2 *dim > &, OPERATOR::mapping_shape_functions< dim, 2 *dim, real > &, std::array< std::vector< real >, dim > &, dealii::hp::FEValues< dim, dim > &fe_values_collection_volume, dealii::hp::FEValues< dim, dim > &fe_values_collection_volume_lagrange, const dealii::FESystem< dim, dim > &current_fe_ref, dealii::Vector< real > &local_rhs_int_cell, std::vector< dealii::Tensor< 1, dim, real >> &, const bool, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Builds the necessary fe values and assembles volume residual.
Definition: weak_dg.cpp:3631
dealii::IndexSet locally_owned_dofs
Locally own degrees of freedom.
Definition: dg_base.hpp:398
DissipativeNumericalFlux
Possible dissipative numerical flux types.
dealii::hp::QCollection< dim-1 > face_quadrature_collection
Quadrature used to evaluate face integrals.
Definition: dg_base.hpp:610
virtual std::array< dealii::Tensor< 1, dim, real >, nstate > convective_flux(const std::array< real, nstate > &solution) const =0
Convective fluxes that will be differentiated once in space.
virtual std::array< real, nstate > evaluate_auxiliary_flux(const dealii::types::global_dof_index current_cell_index, const dealii::types::global_dof_index neighbor_cell_index, const real artificial_diss_coeff_int, const real artificial_diss_coeff_ext, const std::array< real, nstate > &soln_int, const std::array< real, nstate > &soln_ext, const std::array< dealii::Tensor< 1, dim, real >, nstate > &soln_grad_int, const std::array< dealii::Tensor< 1, dim, real >, nstate > &soln_grad_ext, const dealii::Tensor< 1, dim, real > &normal_int, const real &penalty, const bool on_boundary=false) const =0
Auxiliary flux at the interface.
std::vector< std::array< dealii::Tensor< 1, dim, real >, n_components > > evaluate_reference_gradients(const std::vector< dealii::Point< dim >> &unit_points) const
Base metric operators class that stores functions used in both the volume and on surface.
Definition: operators.h:1086
void assemble_volume_term(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const LocalSolution< real2, dim, nstate > &local_solution, const LocalSolution< real2, dim, dim > &local_metric, const std::vector< real > &local_dual, const dealii::Quadrature< dim > &quadrature, const Physics::PhysicsBase< dim, nstate, real2 > &physics, std::vector< real2 > &rhs, real2 &dual_dot_residual, const bool compute_metric_derivatives, const dealii::FEValues< dim, dim > &fe_values_vol)
Main function responsible for evaluating the integral over the cell volume and the specified derivati...
Definition: weak_dg.cpp:2810
real current_time
The current time set in set_current_time()
Definition: dg_base.hpp:665
dealii::ConditionalOStream pcout
Parallel std::cout that only outputs on mpi_rank==0.
Definition: dg_base.hpp:894
void assemble_face_codi_taped_derivatives(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const dealii::types::global_dof_index neighbor_cell_index, const std::pair< unsigned int, int > face_subface_int, const std::pair< unsigned int, int > face_subface_ext, const typename dealii::QProjector< dim >::DataSetDescriptor face_data_set_int, const typename dealii::QProjector< dim >::DataSetDescriptor face_data_set_ext, const dealii::FEFaceValuesBase< dim, dim > &, const dealii::FEFaceValuesBase< dim, dim > &, const real penalty, const dealii::FESystem< dim, dim > &fe_int, const dealii::FESystem< dim, dim > &fe_ext, const dealii::Quadrature< dim-1 > &face_quadrature, const std::vector< dealii::types::global_dof_index > &metric_dof_indices_int, const std::vector< dealii::types::global_dof_index > &metric_dof_indices_ext, const std::vector< dealii::types::global_dof_index > &soln_dof_indices_int, const std::vector< dealii::types::global_dof_index > &soln_dof_indices_ext, const Physics::PhysicsBase< dim, nstate, adtype > &physics, const NumericalFlux::NumericalFluxConvective< dim, nstate, adtype > &conv_num_flux, const NumericalFlux::NumericalFluxDissipative< dim, nstate, adtype > &diss_num_flux, dealii::Vector< real > &local_rhs_int_cell, dealii::Vector< real > &local_rhs_ext_cell, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Preparation of CoDiPack taping for internal cell faces integrals, and derivative evaluation.
Definition: weak_dg.cpp:2323
dealii::IndexSet ghost_dofs
Locally relevant ghost degrees of freedom.
Definition: dg_base.hpp:399
The mapping shape functions evaluated at the desired nodes (facet set included in volume grid nodes f...
Definition: operators.h:1026
Base class of numerical flux associated with convection.
bool use_manufactured_source_term
Uses non-zero source term based on the manufactured solution and the PDE.
std::shared_ptr< ArtificialDissipationBase< dim, nstate > > artificial_dissip
Link to Artificial dissipation class (with three dissipation types, depending on the input)...
void assemble_boundary_codi_taped_derivatives(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const unsigned int face_number, const unsigned int boundary_id, const dealii::FEFaceValuesBase< dim, dim > &fe_values_boundary, const real penalty, const dealii::FESystem< dim, dim > &fe_soln, const dealii::Quadrature< dim-1 > &quadrature, const std::vector< dealii::types::global_dof_index > &metric_dof_indices, const std::vector< dealii::types::global_dof_index > &soln_dof_indices, const Physics::PhysicsBase< dim, nstate, adtype > &physics, const NumericalFlux::NumericalFluxConvective< dim, nstate, adtype > &conv_num_flux, const NumericalFlux::NumericalFluxDissipative< dim, nstate, adtype > &diss_num_flux, dealii::Vector< real > &local_rhs_cell, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Preparation of CoDiPack taping for boundary integral, and derivative evaluation.
Definition: weak_dg.cpp:1138
std::shared_ptr< HighOrderGrid< dim, real, MeshType > > high_order_grid
High order grid that will provide the MappingFEField.
Definition: dg_base.hpp:655
real evaluate_CFL(std::vector< std::array< real, nstate > > soln_at_q, const real artificial_dissipation, const real cell_diameter, const unsigned int cell_degree)
Evaluate the time it takes for the maximum wavespeed to cross the cell domain.
void assemble_volume_residual(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const dealii::FEValues< dim, dim > &fe_values_vol, const dealii::FESystem< dim, dim > &fe_soln, const dealii::Quadrature< dim > &quadrature, const std::vector< dealii::types::global_dof_index > &metric_dof_indices, const std::vector< dealii::types::global_dof_index > &soln_dof_indices, dealii::Vector< real > &local_rhs_cell, const dealii::FEValues< dim, dim > &fe_values_lagrange, const Physics::PhysicsBase< dim, nstate, real > &physics, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Evaluate the integral over the cell volume.
Definition: weak_dg.cpp:3412
virtual std::array< real, nstate > source_term(const dealii::Point< dim, real > &pos, const std::array< real, nstate > &solution, const real current_time, const dealii::types::global_dof_index cell_index) const =0
Artificial dissipative fluxes that will be differentiated ONCE in space.
std::vector< real > coefficients
Solution coefficients in the finite element basis.
void assemble_subface_term_and_build_operators(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 unsigned int neighbor_i_subface, const real penalty, const std::vector< dealii::types::global_dof_index > &current_dofs_indices, const std::vector< dealii::types::global_dof_index > &neighbor_dofs_indices, const std::vector< dealii::types::global_dof_index > &current_metric_dofs_indices, const std::vector< dealii::types::global_dof_index > &neighbor_metric_dofs_indices, const unsigned int, const unsigned int, const unsigned int, const unsigned int, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::local_basis_stiffness< dim, 2 *dim, real > &, OPERATOR::vol_projection_operator< dim, 2 *dim, real > &, OPERATOR::vol_projection_operator< dim, 2 *dim, real > &, OPERATOR::metric_operators< real, dim, 2 *dim > &, OPERATOR::metric_operators< real, dim, 2 *dim > &, OPERATOR::mapping_shape_functions< dim, 2 *dim, real > &, std::array< std::vector< real >, dim > &, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_int, dealii::hp::FESubfaceValues< dim, dim > &fe_values_collection_subface, dealii::Vector< real > &current_cell_rhs, dealii::Vector< real > &neighbor_cell_rhs, std::vector< dealii::Tensor< 1, dim, real >> &, dealii::LinearAlgebra::distributed::Vector< double > &rhs, std::array< dealii::LinearAlgebra::distributed::Vector< double >, dim > &, const bool, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Builds the necessary fe values and assembles subface residual.
Definition: weak_dg.cpp:3822
dealii::TrilinosWrappers::SparseMatrix d2RdWdX
Definition: dg_base.hpp:368
void assemble_face_term(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const dealii::types::global_dof_index neighbor_cell_index, const LocalSolution< real2, dim, nstate > &soln_int, const LocalSolution< real2, dim, nstate > &soln_ext, const LocalSolution< real2, dim, dim > &metric_int, const LocalSolution< real2, dim, dim > &metric_ext, const std::vector< double > &dual_int, const std::vector< double > &dual_ext, const std::pair< unsigned int, int > face_subface_int, const std::pair< unsigned int, int > face_subface_ext, const typename dealii::QProjector< dim >::DataSetDescriptor face_data_set_int, const typename dealii::QProjector< dim >::DataSetDescriptor face_data_set_ext, const Physics::PhysicsBase< dim, nstate, real2 > &physics, const NumericalFlux::NumericalFluxConvective< dim, nstate, real2 > &conv_num_flux, const NumericalFlux::NumericalFluxDissipative< dim, nstate, real2 > &diss_num_flux, const dealii::FEFaceValuesBase< dim, dim > &fe_values_int, const dealii::FEFaceValuesBase< dim, dim > &fe_values_ext, const real penalty, const dealii::Quadrature< dim-1 > &face_quadrature, std::vector< real2 > &rhs_int, std::vector< real2 > &rhs_ext, real2 &dual_dot_residual, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Main function responsible for evaluating the internal face integral and the specified derivatives...
Definition: weak_dg.cpp:1505
virtual std::array< real, nstate > physical_source_term(const dealii::Point< dim, real > &pos, const std::array< real, nstate > &solution, const std::array< dealii::Tensor< 1, dim, real >, nstate > &solution_gradient, const dealii::types::global_dof_index cell_index) const
Physical source term that does require differentiation.
Definition: physics.cpp:131
DGWeak(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)
Constructor.
Definition: weak_dg.cpp:450
void assemble_face_term_and_build_operators(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, const std::vector< dealii::types::global_dof_index > &current_dofs_indices, const std::vector< dealii::types::global_dof_index > &neighbor_dofs_indices, const std::vector< dealii::types::global_dof_index > &current_metric_dofs_indices, const std::vector< dealii::types::global_dof_index > &neighbor_metric_dofs_indices, const unsigned int, const unsigned int, const unsigned int, const unsigned int, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::local_basis_stiffness< dim, 2 *dim, real > &, OPERATOR::vol_projection_operator< dim, 2 *dim, real > &, OPERATOR::vol_projection_operator< dim, 2 *dim, real > &, OPERATOR::metric_operators< real, dim, 2 *dim > &, OPERATOR::metric_operators< real, dim, 2 *dim > &, OPERATOR::mapping_shape_functions< dim, 2 *dim, real > &, std::array< std::vector< real >, dim > &, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_int, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_ext, dealii::Vector< real > &current_cell_rhs, dealii::Vector< real > &neighbor_cell_rhs, std::vector< dealii::Tensor< 1, dim, real >> &, dealii::LinearAlgebra::distributed::Vector< double > &rhs, std::array< dealii::LinearAlgebra::distributed::Vector< double >, dim > &, const bool, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Builds the necessary fe values and assembles face residual.
Definition: weak_dg.cpp:3730
const bool has_nonzero_physical_source
Flag to signal that physical source term is non-zero.
Definition: physics.h:62
void assemble_boundary_residual(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const unsigned int face_number, const unsigned int boundary_id, const dealii::FEFaceValuesBase< dim, dim > &fe_values_boundary, const real penalty, const dealii::FESystem< dim, dim > &fe_soln, const dealii::Quadrature< dim-1 > &quadrature, const std::vector< dealii::types::global_dof_index > &metric_dof_indices, const std::vector< dealii::types::global_dof_index > &soln_dof_indices, const Physics::PhysicsBase< dim, nstate, real > &physics, const NumericalFlux::NumericalFluxConvective< dim, nstate, real > &conv_num_flux, const NumericalFlux::NumericalFluxDissipative< dim, nstate, real > &diss_num_flux, dealii::Vector< real > &local_rhs_cell, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Evaluate the integral over the boundary.
Definition: weak_dg.cpp:1322
Abstract class templated on the number of state variables.
const dealii::FESystem< dim, dim > & finite_element
Reference to the finite element system used to represent the solution.
void assemble_volume_codi_taped_derivatives(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const dealii::FEValues< dim, dim > &fe_values_vol, const dealii::FESystem< dim, dim > &fe_soln, const dealii::Quadrature< dim > &quadrature, const std::vector< dealii::types::global_dof_index > &metric_dof_indices, const std::vector< dealii::types::global_dof_index > &soln_dof_indices, dealii::Vector< real > &local_rhs_cell, const dealii::FEValues< dim, dim > &fe_values_lagrange, const Physics::PhysicsBase< dim, nstate, real2 > &physics, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Preparation of CoDiPack taping for volume integral, and derivative evaluation.
Definition: weak_dg.cpp:3232
bool add_artificial_dissipation
Flag to add artificial dissipation from Persson&#39;s shock capturing paper.
dealii::TrilinosWrappers::SparseMatrix system_matrix
Definition: dg_base.hpp:343
DissipativeNumericalFlux diss_num_flux_type
Store diffusive flux type.
dealii::Vector< double > cell_volume
Time it takes for the maximum wavespeed to cross the cell domain.
Definition: dg_base.hpp:450
std::array< real, nstate > evaluate_flux(const std::array< real, nstate > &soln_int, const std::array< real, nstate > &soln_ext, const dealii::Tensor< 1, dim, real > &normal1) const
Returns the convective numerical flux at an interface.
void assemble_volume_term_explicit(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const dealii::FEValues< dim, dim > &fe_values_volume, const std::vector< dealii::types::global_dof_index > &current_dofs_indices, const std::vector< dealii::types::global_dof_index > &metric_dof_indices, const unsigned int poly_degree, const unsigned int grid_degree, dealii::Vector< real > &current_cell_rhs, const dealii::FEValues< dim, dim > &fe_values_lagrange)
Evaluate the integral over the cell volume.
Definition: weak_dg.cpp:460
void assemble_boundary_term_and_build_operators(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 > &cell_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, real > &, OPERATOR::basis_functions< dim, 2 *dim, real > &, OPERATOR::local_basis_stiffness< dim, 2 *dim, real > &, OPERATOR::vol_projection_operator< dim, 2 *dim, real > &, OPERATOR::vol_projection_operator< dim, 2 *dim, real > &, OPERATOR::metric_operators< real, dim, 2 *dim > &, OPERATOR::mapping_shape_functions< dim, 2 *dim, real > &, std::array< std::vector< real >, dim > &, dealii::hp::FEFaceValues< dim, dim > &fe_values_collection_face_int, const dealii::FESystem< dim, dim > &current_fe_ref, dealii::Vector< real > &local_rhs_int_cell, std::vector< dealii::Tensor< 1, dim, real >> &, const bool, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Builds the necessary fe values and assembles boundary residual.
Definition: weak_dg.cpp:3687
bool use_periodic_bc
Flag to use periodic BC.
void assemble_boundary_term_derivatives(typename dealii::DoFHandler< dim >::active_cell_iterator cell, const dealii::types::global_dof_index current_cell_index, const unsigned int face_number, const unsigned int boundary_id, const dealii::FEFaceValuesBase< dim, dim > &fe_values_boundary, const real penalty, const dealii::FESystem< dim, dim > &fe, const dealii::Quadrature< dim-1 > &quadrature, const std::vector< dealii::types::global_dof_index > &metric_dof_indices, const std::vector< dealii::types::global_dof_index > &soln_dof_indices, dealii::Vector< real > &local_rhs_cell, const bool compute_dRdW, const bool compute_dRdX, const bool compute_d2R)
Evaluate the integral over the cell edges that are on domain boundaries and the specified derivatives...
Definition: weak_dg.cpp:1396
dealii::TrilinosWrappers::SparseMatrix d2RdXdX
Definition: dg_base.hpp:364
real1 norm(const dealii::Tensor< 1, dim, real1 > x)
Returns norm of dealii::Tensor<1,dim,real>
dealii::hp::QCollection< dim > volume_quadrature_collection
Finite Element Collection to represent the high-order grid.
Definition: dg_base.hpp:608
ArtificialDissipationParam artificial_dissipation_param
Contains parameters for artificial dissipation.
virtual std::array< dealii::Tensor< 1, dim, real >, nstate > dissipative_flux(const std::array< real, nstate > &solution, const std::array< dealii::Tensor< 1, dim, real >, nstate > &solution_gradient, const dealii::types::global_dof_index cell_index) const =0
Dissipative fluxes that will be differentiated ONCE in space.
const dealii::hp::FECollection< dim > fe_collection
Finite Element Collection for p-finite-element to represent the solution.
Definition: dg_base.hpp:597
Projection operator corresponding to basis functions onto M-norm (L2).
Definition: operators.h:694
Local stiffness matrix without jacobian dependence.
Definition: operators.h:472
const dealii::FE_Q< dim > fe_q_artificial_dissipation
Continuous distribution of artificial dissipation.
Definition: dg_base.hpp:667