[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
operators.cpp
1 #include <deal.II/base/conditional_ostream.h>
2 #include <deal.II/base/parameter_handler.h>
3 
4 #include <deal.II/base/qprojector.h>
5 #include <deal.II/base/geometry_info.h>
6 
7 #include <deal.II/grid/tria.h>
8 
9 #include <deal.II/fe/fe_dgq.h>
10 #include <deal.II/fe/fe_dgp.h>
11 #include <deal.II/fe/fe_system.h>
12 #include <deal.II/fe/mapping_fe_field.h>
13 #include <deal.II/fe/mapping_q1_eulerian.h>
14 
15 
16 #include <deal.II/dofs/dof_handler.h>
17 
18 #include <deal.II/hp/q_collection.h>
19 #include <deal.II/hp/mapping_collection.h>
20 #include <deal.II/hp/fe_values.h>
21 
22 #include <deal.II/lac/vector.h>
23 #include <deal.II/lac/sparsity_pattern.h>
24 #include <deal.II/lac/trilinos_sparse_matrix.h>
25 #include <deal.II/lac/trilinos_vector.h>
26 #include <deal.II/lac/identity_matrix.h>
27 
28 #include <Epetra_RowMatrixTransposer.h>
29 #include <AztecOO.h>
30 
31 #include "ADTypes.hpp"
32 #include <Sacado.hpp>
33 #include <CoDiPack/include/codi.hpp>
34 
35 #include "operators.h"
36 
37 namespace PHiLiP {
38 namespace OPERATOR {
39 
40 //Constructor
41 template <int dim, int n_faces>
43  const int nstate_input,
44  const unsigned int max_degree_input,
45  const unsigned int grid_degree_input)
46  : max_degree(max_degree_input)
47  , max_grid_degree(grid_degree_input)
48  , nstate(nstate_input)
49  , max_grid_degree_check(grid_degree_input)
50  , mpi_communicator(MPI_COMM_WORLD)
51  , pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(mpi_communicator)==0)
52 {}
53 
54 template <int dim, int n_faces>
55 dealii::FullMatrix<double> OperatorsBase<dim,n_faces>::tensor_product(
56  const dealii::FullMatrix<double> &basis_x,
57  const dealii::FullMatrix<double> &basis_y,
58  const dealii::FullMatrix<double> &basis_z)
59 {
60  const unsigned int rows_x = basis_x.m();
61  const unsigned int columns_x = basis_x.n();
62  const unsigned int rows_y = basis_y.m();
63  const unsigned int columns_y = basis_y.n();
64  const unsigned int rows_z = basis_z.m();
65  const unsigned int columns_z = basis_z.n();
66 
67  if constexpr (dim==1)
68  return basis_x;
69  if constexpr (dim==2){
70  dealii::FullMatrix<double> tens_prod(rows_x * rows_y, columns_x * columns_y);
71  for(unsigned int jdof=0; jdof<rows_y; jdof++){
72  for(unsigned int kdof=0; kdof<rows_x; kdof++){
73  for(unsigned int ndof=0; ndof<columns_y; ndof++){
74  for(unsigned int odof=0; odof<columns_x; odof++){
75  const unsigned int index_row = rows_x * jdof + kdof;
76  const unsigned int index_col = columns_x * ndof + odof;
77  tens_prod[index_row][index_col] = basis_x[kdof][odof] * basis_y[jdof][ndof];
78  }
79  }
80  }
81  }
82  return tens_prod;
83  }
84  if constexpr (dim==3){
85  dealii::FullMatrix<double> tens_prod(rows_x * rows_y * rows_z, columns_x * columns_y * columns_z);
86  for(unsigned int idof=0; idof<rows_z; idof++){
87  for(unsigned int jdof=0; jdof<rows_y; jdof++){
88  for(unsigned int kdof=0; kdof<rows_x; kdof++){
89  for(unsigned int mdof=0; mdof<columns_z; mdof++){
90  for(unsigned int ndof=0; ndof<columns_y; ndof++){
91  for(unsigned int odof=0; odof<columns_x; odof++){
92  const unsigned int index_row = rows_x * rows_y * idof + rows_x * jdof + kdof;
93  const unsigned int index_col = columns_x * columns_y * mdof + columns_x * ndof + odof;
94  tens_prod[index_row][index_col] = basis_x[kdof][odof] * basis_y[jdof][ndof] * basis_z[idof][mdof];
95  }
96  }
97  }
98  }
99  }
100  }
101  return tens_prod;
102  }
103 }
104 
105 template <int dim, int n_faces>
107  const int nstate,
108  const dealii::FullMatrix<double> &basis_x,
109  const dealii::FullMatrix<double> &basis_y,
110  const dealii::FullMatrix<double> &basis_z)
111 {
112  //assert that each basis matrix is of size (rows x columns)
113  const unsigned int rows_x = basis_x.m();
114  const unsigned int columns_x = basis_x.n();
115  const unsigned int rows_y = basis_y.m();
116  const unsigned int columns_y = basis_y.n();
117  const unsigned int rows_z = basis_z.m();
118  const unsigned int columns_z = basis_z.n();
119 
120  const unsigned int rows_1state_x = rows_x / nstate;
121  const unsigned int columns_1state_x = columns_x / nstate;
122  const unsigned int rows_1state_y = rows_y / nstate;
123  const unsigned int columns_1state_y = columns_y / nstate;
124  const unsigned int rows_1state_z = rows_z / nstate;
125  const unsigned int columns_1state_z = columns_z / nstate;
126 
127  const unsigned int rows_all_states = (dim == 1) ? rows_1state_x * nstate :
128  ( (dim == 2) ? rows_1state_x * rows_1state_y * nstate :
129  rows_1state_x * rows_1state_y * rows_1state_z * nstate);
130  const unsigned int columns_all_states = (dim == 1) ? columns_1state_x * nstate :
131  ( (dim == 2) ? columns_1state_x * columns_1state_y * nstate :
132  columns_1state_x * columns_1state_y * columns_1state_z * nstate);
133  dealii::FullMatrix<double> tens_prod(rows_all_states, columns_all_states);
134 
135 
136  for(int istate=0; istate<nstate; istate++){
137  dealii::FullMatrix<double> basis_x_1state(rows_1state_x, columns_1state_x);
138  dealii::FullMatrix<double> basis_y_1state(rows_1state_y, columns_1state_y);
139  dealii::FullMatrix<double> basis_z_1state(rows_1state_z, columns_1state_z);
140  for(unsigned int r=0; r<rows_1state_x; r++){
141  for(unsigned int c=0; c<columns_1state_x; c++){
142  basis_x_1state[r][c] = basis_x[istate*rows_1state_x + r][istate*columns_1state_x + c];
143  }
144  }
145  if constexpr(dim>=2){
146  for(unsigned int r=0; r<rows_1state_y; r++){
147  for(unsigned int c=0; c<columns_1state_y; c++){
148  basis_y_1state[r][c] = basis_y[istate*rows_1state_y + r][istate*columns_1state_y + c];
149  }
150  }
151  }
152  if constexpr(dim>=3){
153  for(unsigned int r=0; r<rows_1state_z; r++){
154  for(unsigned int c=0; c<columns_1state_z; c++){
155  basis_z_1state[r][c] = basis_z[istate*rows_1state_z + r][istate*columns_1state_z + c];
156  }
157  }
158  }
159  const unsigned int r1state = (dim == 1) ? rows_1state_x : ( (dim==2) ? rows_1state_x * rows_1state_y : rows_1state_x * rows_1state_y * rows_1state_z);
160  const unsigned int c1state = (dim == 1) ? columns_1state_x : ( (dim==2) ? columns_1state_x * columns_1state_y : columns_1state_x * columns_1state_y * columns_1state_z);
161  dealii::FullMatrix<double> tens_prod_1state(r1state, c1state);
162  tens_prod_1state = tensor_product(basis_x_1state, basis_y_1state, basis_z_1state);
163  for(unsigned int r=0; r<r1state; r++){
164  for(unsigned int c=0; c<c1state; c++){
165  tens_prod[istate*r1state + r][istate*c1state + c] = tens_prod_1state[r][c];
166  }
167  }
168  }
169  return tens_prod;
170 }
171 
172 template <int dim, int n_faces>
174 {
175  if ((n==0)||(n==1))
176  return 1;
177  else
178  return n*compute_factorial(n-1);
179 }
180 
181 /**********************************
182 *
183 * Sum Factorization class
184 *
185 **********************************/
186 //Constructor
187 template <int dim, int n_faces>
189  const int nstate_input,
190  const unsigned int max_degree_input,
191  const unsigned int grid_degree_input)
192  : OperatorsBase<dim,n_faces>::OperatorsBase(nstate_input, max_degree_input, grid_degree_input)
193 {}
194 
195 inline void print_face_orientation_warning()
196 {
197  const char *msg =
198  "This scenario was considered and a fix has been implemented. "
199  "However, this scenario was never encountered before and thus could not be verified.\n"
200  "You may remove the abort statement and verify that the solution is as expected.\n"
201  "For more information, please see: "
202  "https://www.dealii.org/current/doxygen/deal.II/DEALGlossary.html#GlossFaceOrientation \n\n";
203 
204  std::cout << msg << msg;
205 }
206 
207 template <int dim, int n_faces>
208 template <typename real>
210  const std::vector<bool> face_orientation,
211  const unsigned int /*face_number*/,
212  std::vector<real> &output_vect,
213  const dealii::FullMatrix<double> &basis)
214 {
215  //Initialize temp vector as input vector.
216  std::vector<real> output_vect_temp = output_vect;
217  const unsigned int columns = basis.m();
218  if(!face_orientation[0]){
219  for(unsigned int ydof=0; ydof<columns; ydof++){
220  for(unsigned int xdof=0; xdof<columns; xdof++){//x runs fastest
221  output_vect[xdof+ydof*columns] = output_vect_temp[columns*xdof+ydof];
222  }
223  }
224  }
225  if(face_orientation[1]){
226  std::vector<real> output_vect_temp_rotation = output_vect;
227  for(unsigned int ydof=0; ydof<columns; ydof++){
228  for(unsigned int xdof=0; xdof<columns; xdof++){//x runs fastest
229  output_vect[xdof+ydof*columns] = output_vect_temp_rotation[((columns-1)-ydof)+xdof*columns];
230  }
231  }
232  std::cout << "\nIt appears deal.ii has rotated a face.\n";
233  print_face_orientation_warning();
234  std::abort();
235  }
236  if(face_orientation[2]){
237  std::vector<real> output_vect_temp_flip = output_vect;
238  for(unsigned int ydof=0; ydof<columns; ydof++){
239  for(unsigned int xdof=0; xdof<columns; xdof++){//x runs fastest
240  output_vect[xdof+ydof*columns] = output_vect_temp_flip[(columns*columns-1)-xdof-ydof*columns];
241  }
242  }
243  std::cout << "\nIt appears deal.ii has flipped a face.\n";
244  print_face_orientation_warning();
245  std::abort();
246  }
247 }
248 
249 template <int dim, int n_faces>
250 template <typename real>
252  const std::vector<bool> face_orientation,
253  const unsigned int /*face_number*/,
254  const std::vector<real> &input_vect,
255  std::vector<real> &output_vect,
256  const dealii::FullMatrix<double> &basis)
257 {
258  //Initialize output vector as input vector.
259  output_vect = input_vect;
260  const unsigned int columns = basis.m();
261  if(!face_orientation[0]){
262  for(unsigned int ydof=0; ydof<columns; ydof++){
263  for(unsigned int xdof=0; xdof<columns; xdof++){//x runs fastest
264  output_vect[xdof+ydof*columns] = input_vect[columns*xdof+ydof];
265  }
266  }
267  }
268  if(face_orientation[1]){
269  std::vector<real> output_vect_temp_rotation = output_vect;
270  for(unsigned int ydof=0; ydof<columns; ydof++){
271  for(unsigned int xdof=0; xdof<columns; xdof++){//x runs fastest
272  output_vect[xdof+ydof*columns] = output_vect_temp_rotation[((columns-1)-ydof)+xdof*columns];
273  }
274  }
275  std::cout << "\nIt appears deal.ii has rotated a face.\n";
276  print_face_orientation_warning();
277  std::abort();
278  }
279  if(face_orientation[2]){
280  std::vector<real> output_vect_temp_flip = output_vect;
281  for(unsigned int ydof=0; ydof<columns; ydof++){
282  for(unsigned int xdof=0; xdof<columns; xdof++){//x runs fastest
283  output_vect[xdof+ydof*columns] = output_vect_temp_flip[(columns*columns-1)-xdof-ydof*columns];
284  }
285  }
286  std::cout << "\nIt appears deal.ii has flipped a face.\n";
287  print_face_orientation_warning();
288  std::abort();
289  }
290 }
291 
292 template <int dim, int n_faces>
293 template <typename real>
295  const std::vector<real> &input_vect,
296  std::vector<real> &output_vect,
297  const dealii::FullMatrix<double> &basis_x,
298  const dealii::FullMatrix<double> &basis_y,
299  const dealii::FullMatrix<double> &basis_z,
300  const bool adding,
301  const double factor)
302 {
303  //assert that each basis matrix is of size (rows x columns)
304  const unsigned int rows_x = basis_x.m();
305  const unsigned int rows_y = basis_y.m();
306  const unsigned int rows_z = basis_z.m();
307  const unsigned int columns_x = basis_x.n();
308  const unsigned int columns_y = basis_y.n();
309  const unsigned int columns_z = basis_z.n();
310  if constexpr (dim == 1){
311  assert(rows_x == output_vect.size());
312  assert(columns_x == input_vect.size());
313  }
314  if constexpr (dim == 2){
315  assert(rows_x * rows_y == output_vect.size());
316  assert(columns_x * columns_y == input_vect.size());
317  }
318  if constexpr (dim == 3){
319  assert(rows_x * rows_y * rows_z == output_vect.size());
320  assert(columns_x * columns_y * columns_z == input_vect.size());
321  }
322 
323  if constexpr (dim==1){
324  for(unsigned int iquad=0; iquad<rows_x; iquad++){
325  if(!adding)
326  output_vect[iquad] = 0.0;
327  for(unsigned int jquad=0; jquad<columns_x; jquad++){
328  output_vect[iquad] += factor * basis_x[iquad][jquad] * input_vect[jquad];
329  }
330  }
331  }
332  if constexpr (dim==2){
333  //Apply basis transformation in x-direction.
334  std::vector<real> temp(rows_x * columns_y);
335  for(unsigned int x_dir =0; x_dir<rows_x; x_dir++){
336  for(unsigned int y_dir =0 ; y_dir<columns_y; y_dir++){
337  temp[x_dir * columns_y + y_dir] = 0.0;
338  for(unsigned int stride =0 ; stride<columns_x; stride++){
339  temp[x_dir * columns_y + y_dir] += input_vect[y_dir * columns_x + stride] * basis_x[x_dir][stride];
340  }
341  }
342  }
343  //Apply basis transformation in y-direction.
344  for(unsigned int y_dir =0 ; y_dir<rows_y; y_dir++){
345  for(unsigned int x_dir =0 ; x_dir<rows_x; x_dir++){
346  if(!adding)
347  output_vect[y_dir * rows_x + x_dir] = 0.0;
348  for(unsigned int stride =0; stride<columns_y; stride++){
349  output_vect[y_dir * rows_x + x_dir] += factor * temp[x_dir * columns_y + stride] * basis_y[y_dir][stride];
350  }
351  }
352  }
353  }
354  if constexpr (dim==3){
355  //Apply basis tranformation in x-direction
356  std::vector<real> transformed_x(rows_x * columns_y * columns_z);
357  for(unsigned int x_dir=0; x_dir<rows_x; x_dir++){
358  for(unsigned int z_dir=0; z_dir<columns_z; z_dir++){
359  for(unsigned int y_dir=0; y_dir<columns_y; y_dir++){
360  const unsigned int index = x_dir * columns_y * columns_z + z_dir * columns_y + y_dir;//since next will loop y, write that as free last index
361  transformed_x[index] = 0.0;
362  for(unsigned int stride=0; stride<columns_x; stride++){
363  const unsigned int stride_index = z_dir * columns_x * columns_y + y_dir * columns_x + stride;
364  transformed_x[index] += basis_x[x_dir][stride] * input_vect[stride_index];
365  }
366  }
367  }
368  }
369  //Apply basis tranformation in y-direction
370  std::vector<real> transformed_x_and_y(rows_y * rows_x * columns_z);
371  for(unsigned int y_dir=0; y_dir<rows_y; y_dir++){
372  for(unsigned int x_dir=0; x_dir<rows_x; x_dir++){
373  for(unsigned int z_dir=0; z_dir<columns_z; z_dir++){
374  const unsigned int index = y_dir * rows_x * columns_z + x_dir * columns_z + z_dir;//since next will loop z write that to free index
375  transformed_x_and_y[index] = 0.0;
376  for(unsigned int stride = 0;stride<columns_y;stride++){
377  const unsigned int stride_index = x_dir * columns_y * columns_z + z_dir * columns_y + stride;
378  transformed_x_and_y[index] += basis_y[y_dir][stride] * transformed_x[stride_index];
379  }
380  }
381  }
382  }
383  //Apply basis tranformation in z-direction
384  for(unsigned int z_dir=0; z_dir<rows_z; z_dir++){
385  for(unsigned int y_dir=0; y_dir<rows_y; y_dir++){
386  for(unsigned int x_dir=0; x_dir<rows_x; x_dir++){
387  const unsigned int index = z_dir * rows_x * rows_y + y_dir * rows_x + x_dir;
388  if(!adding)
389  output_vect[index] =0.0;
390  for(unsigned int stride=0; stride<columns_z; stride++){
391  const unsigned int stride_index = y_dir * rows_x * columns_z + x_dir * columns_z + stride;
392  output_vect[index] += factor * basis_z[z_dir][stride] * transformed_x_and_y[stride_index];
393  }
394  }
395  }
396  }
397  }
398 }
399 
400 template <int dim, int n_faces>
401 template <typename real>
403  const std::vector<real> &input_vect,
404  std::vector<real> &output_vect,
405  const dealii::FullMatrix<double> &basis_x,
406  const bool adding,
407  const double factor)
408 {
409  this->matrix_vector_mult(input_vect, output_vect, basis_x, basis_x, basis_x, adding, factor);
410 }
411 
412 template <int dim, int n_faces>
413 template <typename real>
415  const std::vector<bool> face_orientation,
416  const unsigned int face_number,
417  const std::vector<real> &input_vect,
418  std::vector<real> &output_vect,
419  const std::array<dealii::FullMatrix<double>,2> &basis_surf,
420  const dealii::FullMatrix<double> &basis_vol,
421  const bool adding,
422  const double factor)
423 {
424  if(face_number == 0)
425  this->matrix_vector_mult(input_vect, output_vect, basis_surf[0], basis_vol, basis_vol, adding, factor);
426  if(face_number == 1)
427  this->matrix_vector_mult(input_vect, output_vect, basis_surf[1], basis_vol, basis_vol, adding, factor);
428  if(face_number == 2)
429  this->matrix_vector_mult(input_vect, output_vect, basis_vol, basis_surf[0], basis_vol, adding, factor);
430  if(face_number == 3)
431  this->matrix_vector_mult(input_vect, output_vect, basis_vol, basis_surf[1], basis_vol, adding, factor);
432  if(face_number == 4)
433  this->matrix_vector_mult(input_vect, output_vect, basis_vol, basis_vol, basis_surf[0], adding, factor);
434  if(face_number == 5)
435  this->matrix_vector_mult(input_vect, output_vect, basis_vol, basis_vol, basis_surf[1], adding, factor);
436 
437  if(!face_orientation[0] || face_orientation[1] || face_orientation[2]){
438  this->face_orientation_tensor_product(face_orientation, face_number, output_vect, basis_vol);
439  }
440 }
441 
442 
443 template <int dim, int n_faces>
444 template <typename real>
446  const std::vector<bool> face_orientation,
447  const unsigned int face_number,
448  const std::vector<real> &input_vect,
449  const std::vector<double> &weight_vect,
450  std::vector<real> &output_vect,
451  const std::array<dealii::FullMatrix<double>,2> &basis_surf,
452  const dealii::FullMatrix<double> &basis_vol,
453  const bool adding,
454  const double factor)
455 {
456 
457 
458  std::vector<real> input_vect_corrected;
459  if(!face_orientation[0] || face_orientation[1] || face_orientation[2]){
460  this->face_orientation_inner_product(face_orientation, face_number, input_vect, input_vect_corrected, basis_vol);
461  }else{
462  input_vect_corrected = input_vect;
463  }
464 
465  if(face_number == 0)
466  this->inner_product(input_vect_corrected, weight_vect, output_vect, basis_surf[0], basis_vol, basis_vol, adding, factor);
467  if(face_number == 1)
468  this->inner_product(input_vect_corrected, weight_vect, output_vect, basis_surf[1], basis_vol, basis_vol, adding, factor);
469  if(face_number == 2)
470  this->inner_product(input_vect_corrected, weight_vect, output_vect, basis_vol, basis_surf[0], basis_vol, adding, factor);
471  if(face_number == 3)
472  this->inner_product(input_vect_corrected, weight_vect, output_vect, basis_vol, basis_surf[1], basis_vol, adding, factor);
473  if(face_number == 4)
474  this->inner_product(input_vect_corrected, weight_vect, output_vect, basis_vol, basis_vol, basis_surf[0], adding, factor);
475  if(face_number == 5)
476  this->inner_product(input_vect_corrected, weight_vect, output_vect, basis_vol, basis_vol, basis_surf[1], adding, factor);
477 }
478 
479 template <int dim, int n_faces>
480 template <typename real>
482  const dealii::Tensor<1,dim,std::vector<real>> &input_vect,
483  std::vector<real> &output_vect,
484  const dealii::FullMatrix<double> &basis,
485  const dealii::FullMatrix<double> &gradient_basis)
486 {
487  divergence_matrix_vector_mult(input_vect, output_vect,
488  basis, basis, basis,
489  gradient_basis, gradient_basis, gradient_basis);
490 }
491 
492 template <int dim, int n_faces>
493 template <typename real>
495  const dealii::Tensor<1,dim,std::vector<real>> &input_vect,
496  std::vector<real> &output_vect,
497  const dealii::FullMatrix<double> &basis_x,
498  const dealii::FullMatrix<double> &basis_y,
499  const dealii::FullMatrix<double> &basis_z,
500  const dealii::FullMatrix<double> &gradient_basis_x,
501  const dealii::FullMatrix<double> &gradient_basis_y,
502  const dealii::FullMatrix<double> &gradient_basis_z)
503 {
504  for(int idim=0; idim<dim;idim++){
505  if(idim==0)
506  this->matrix_vector_mult(input_vect[idim], output_vect,
507  gradient_basis_x,
508  basis_y,
509  basis_z,
510  false);//first one doesn't add in the divergence
511  if(idim==1)
512  this->matrix_vector_mult(input_vect[idim], output_vect,
513  basis_x,
514  gradient_basis_y,
515  basis_z,
516  true);
517  if(idim==2)
518  this->matrix_vector_mult(input_vect[idim], output_vect,
519  basis_x,
520  basis_y,
521  gradient_basis_z,
522  true);
523  }
524 }
525 
526 template <int dim, int n_faces>
527 template <typename real>
529  const std::vector<real> &input_vect,
530  dealii::Tensor<1,dim,std::vector<real>> &output_vect,
531  const dealii::FullMatrix<double> &basis,
532  const dealii::FullMatrix<double> &gradient_basis)
533 {
534  gradient_matrix_vector_mult(input_vect, output_vect,
535  basis, basis, basis,
536  gradient_basis, gradient_basis, gradient_basis);
537 }
538 
539 template <int dim, int n_faces>
540 template <typename real>
542  const std::vector<real> &input_vect,
543  dealii::Tensor<1,dim,std::vector<real>> &output_vect,
544  const dealii::FullMatrix<double> &basis_x,
545  const dealii::FullMatrix<double> &basis_y,
546  const dealii::FullMatrix<double> &basis_z,
547  const dealii::FullMatrix<double> &gradient_basis_x,
548  const dealii::FullMatrix<double> &gradient_basis_y,
549  const dealii::FullMatrix<double> &gradient_basis_z)
550 {
551  for(int idim=0; idim<dim;idim++){
552  if(idim==0)
553  this->matrix_vector_mult(input_vect, output_vect[idim],
554  gradient_basis_x,
555  basis_y,
556  basis_z,
557  false);
558  if(idim==1)
559  this->matrix_vector_mult(input_vect, output_vect[idim],
560  basis_x,
561  gradient_basis_y,
562  basis_z,
563  false);
564  if(idim==2)
565  this->matrix_vector_mult(input_vect, output_vect[idim],
566  basis_x,
567  basis_y,
568  gradient_basis_z,
569  false);
570  }
571 }
572 
573 template <int dim, int n_faces>
574 template <typename real>
576  const std::vector<real> &input_vect,
577  const std::vector<double> &weight_vect,
578  std::vector<real> &output_vect,
579  const dealii::FullMatrix<double> &basis_x,
580  const dealii::FullMatrix<double> &basis_y,
581  const dealii::FullMatrix<double> &basis_z,
582  const bool adding,
583  const double factor)
584 {
585  //assert that each basis matrix is of size (rows x columns)
586  const unsigned int rows_x = basis_x.m();
587  const unsigned int rows_y = basis_y.m();
588  const unsigned int rows_z = basis_z.m();
589  const unsigned int columns_x = basis_x.n();
590  const unsigned int columns_y = basis_y.n();
591  const unsigned int columns_z = basis_z.n();
592  //Note the assertion has columns to output and rows to input
593  //bc we transpose the basis inputted for the inner product
594  if constexpr (dim == 1){
595  assert(rows_x == input_vect.size());
596  assert(columns_x == output_vect.size());
597  }
598  if constexpr (dim == 2){
599  assert(rows_x * rows_y == input_vect.size());
600  assert(columns_x * columns_y == output_vect.size());
601  }
602  if constexpr (dim == 3){
603  assert(rows_x * rows_y * rows_z == input_vect.size());
604  assert(columns_x * columns_y * columns_z == output_vect.size());
605  }
606  assert(weight_vect.size() == input_vect.size());
607 
608  dealii::FullMatrix<double> basis_x_trans(columns_x, rows_x);
609  dealii::FullMatrix<double> basis_y_trans(columns_y, rows_y);
610  dealii::FullMatrix<double> basis_z_trans(columns_z, rows_z);
611 
612  //set as the transpose as inputed basis
613  //found an issue with Tadd for arbitrary size so I manually do it here.
614  for(unsigned int row=0; row<rows_x; row++){
615  for(unsigned int col=0; col<columns_x; col++){
616  basis_x_trans[col][row] = basis_x[row][col];
617  }
618  }
619  for(unsigned int row=0; row<rows_y; row++){
620  for(unsigned int col=0; col<columns_y; col++){
621  basis_y_trans[col][row] = basis_y[row][col];
622  }
623  }
624  for(unsigned int row=0; row<rows_z; row++){
625  for(unsigned int col=0; col<columns_z; col++){
626  basis_z_trans[col][row] = basis_z[row][col];
627  }
628  }
629 
630  std::vector<real> new_input_vect(input_vect.size());
631  for(unsigned int iquad=0; iquad<input_vect.size(); iquad++){
632  new_input_vect[iquad] = input_vect[iquad] * weight_vect[iquad];
633  }
634 
635  this->matrix_vector_mult(new_input_vect, output_vect, basis_x_trans, basis_y_trans, basis_z_trans, adding, factor);
636 }
637 
638 template <int dim, int n_faces>
639 template <typename real>
641  const std::vector<real> &input_vect,
642  const std::vector<double> &weight_vect,
643  std::vector<real> &output_vect,
644  const dealii::FullMatrix<double> &basis_x,
645  const bool adding,
646  const double factor)
647 {
648  this->inner_product(input_vect, weight_vect, output_vect, basis_x, basis_x, basis_x, adding, factor);
649 }
650 
651 template <int dim, int n_faces>
653  const dealii::Tensor<1,dim,dealii::FullMatrix<double>> &input_mat,
654  std::vector<double> &output_vect,
655  const std::vector<double> &weights,
656  const dealii::FullMatrix<double> &basis,
657  const double scaling)
658 {
659  assert(input_mat[0].m() == output_vect.size());
660 
661  dealii::FullMatrix<double> output_mat(input_mat[0].m(), input_mat[0].n());
662  for(int idim=0; idim<dim; idim++){
663  two_pt_flux_Hadamard_product(input_mat[idim], output_mat, basis, weights, idim);
664  if constexpr(dim==1){
665  for(unsigned int row=0; row<input_mat[0].m(); row++){//n^d rows
666  for(unsigned int col=0; col<basis.m(); col++){//only need to sum n columns
667  const unsigned int col_index = col;
668  output_vect[row] += scaling * output_mat[row][col_index];//scaled by 2.0 for 2pt flux
669  }
670  }
671  }
672  if constexpr(dim==2){
673  const unsigned int size_1D = basis.m();
674  for(unsigned int irow=0; irow<size_1D; irow++){
675  for(unsigned int jrow=0; jrow<size_1D; jrow++){
676  const unsigned int row_index = irow * size_1D + jrow;
677  for(unsigned int col=0; col<size_1D; col++){
678  if(idim==0){
679  const unsigned int col_index = col + irow * size_1D;
680  output_vect[row_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
681  }
682  if(idim==1){
683  const unsigned int col_index = col * size_1D + jrow;
684  output_vect[row_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
685  }
686  }
687  }
688  }
689  }
690  if constexpr(dim==3){
691  const unsigned int size_1D = basis.m();
692  for(unsigned int irow=0; irow<size_1D; irow++){
693  for(unsigned int jrow=0; jrow<size_1D; jrow++){
694  for(unsigned int krow=0; krow<size_1D; krow++){
695  const unsigned int row_index = irow * size_1D * size_1D + jrow * size_1D + krow;
696  for(unsigned int col=0; col<size_1D; col++){
697  if(idim==0){
698  const unsigned int col_index = col + irow * size_1D * size_1D + jrow * size_1D;
699  output_vect[row_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
700  }
701  if(idim==1){
702  const unsigned int col_index = col * size_1D + krow + irow * size_1D * size_1D;
703  output_vect[row_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
704  }
705  if(idim==2){
706  const unsigned int col_index = col * size_1D * size_1D + krow + jrow * size_1D;
707  output_vect[row_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
708  }
709  }
710  }
711  }
712  }
713  }
714  }
715 }
716 
717 template <int dim, int n_faces>
719  const dealii::FullMatrix<double> &input_mat,
720  std::vector<double> &output_vect_vol,
721  std::vector<double> &output_vect_surf,
722  const std::vector<double> &weights,
723  const std::array<dealii::FullMatrix<double>,2> &surf_basis,
724  const unsigned int iface,
725  const unsigned int dim_not_zero,
726  const double scaling)//scaling is unit_ref_normal[dim_not_zero]
727 {
728  assert(input_mat.n() == output_vect_vol.size());
729  assert(input_mat.m() == output_vect_surf.size());
730  const unsigned int iface_1D = iface % 2;
731 
732  dealii::FullMatrix<double> output_mat(input_mat.m(), input_mat.n());
733  two_pt_flux_Hadamard_product(input_mat, output_mat, surf_basis[iface_1D], weights, dim_not_zero);
734  if constexpr(dim==1){
735  for(unsigned int row=0; row<surf_basis[iface_1D].m(); row++){//n rows
736  for(unsigned int col=0; col<surf_basis[iface_1D].n(); col++){//only need to sum n columns
737  output_vect_vol[col] += scaling
738  * output_mat[row][col];//scaled by 2.0 for 2pt flux
739  output_vect_surf[row] -= scaling //minus because skew-symm form
740  * output_mat[row][col];//scaled by 2.0 for 2pt flux
741  }
742  }
743  }
744  if constexpr(dim==2){
745  const unsigned int size_1D_row = surf_basis[iface_1D].m();
746  const unsigned int size_1D_col = surf_basis[iface_1D].n();
747  for(unsigned int irow=0; irow<size_1D_col; irow++){
748  for(unsigned int jrow=0; jrow<size_1D_row; jrow++){
749  const unsigned int row_index = irow * size_1D_row + jrow;
750  for(unsigned int col=0; col<size_1D_col; col++){
751  if(dim_not_zero==0){
752  const unsigned int col_index = col + irow * size_1D_col;
753  output_vect_vol[col_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
754  output_vect_surf[row_index] -= scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
755  }
756  if(dim_not_zero==1){
757  const unsigned int col_index = col * size_1D_col + irow;
758  output_vect_vol[col_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
759  output_vect_surf[row_index] -= scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
760  }
761  }
762  }
763  }
764  }
765  if constexpr(dim==3){
766  const unsigned int size_1D_row = surf_basis[iface_1D].m();
767  const unsigned int size_1D_col = surf_basis[iface_1D].n();
768  for(unsigned int irow=0; irow<size_1D_col; irow++){
769  for(unsigned int jrow=0; jrow<size_1D_col; jrow++){
770  for(unsigned int krow=0; krow<size_1D_row; krow++){
771  const unsigned int row_index = irow * size_1D_row * size_1D_col + jrow * size_1D_row + krow;
772  for(unsigned int col=0; col<size_1D_col; col++){
773  if(dim_not_zero==0){
774  const unsigned int col_index = col + irow * size_1D_col * size_1D_col + jrow * size_1D_col;
775  output_vect_vol[col_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
776  output_vect_surf[row_index] -= scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
777  }
778  if(dim_not_zero==1){
779  const unsigned int col_index = col * size_1D_col + jrow + irow * size_1D_col * size_1D_col;
780  output_vect_vol[col_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
781  output_vect_surf[row_index] -= scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
782  }
783  if(dim_not_zero==2){
784  const unsigned int col_index = col * size_1D_col * size_1D_col + jrow + irow * size_1D_col;
785  output_vect_vol[col_index] += scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
786  output_vect_surf[row_index] -= scaling * output_mat[row_index][col_index];//scaled by 2.0 for 2pt flux
787  }
788  }
789  }
790  }
791  }
792  }
793 }
794 
795 
796 
797 template <int dim, int n_faces>
799  const dealii::FullMatrix<double> &input_mat,
800  dealii::FullMatrix<double> &output_mat,
801  const dealii::FullMatrix<double> &basis,
802  const std::vector<double> &weights,
803  const int direction)
804 {
805  assert(input_mat.size() == output_mat.size());
806  const unsigned int size = basis.n();
807  assert(size == weights.size());
808 
809  if constexpr(dim == 1){
810  Hadamard_product(input_mat, basis, output_mat);
811  }
812  if constexpr(dim == 2){
813  //In the general case, the basis is non-square (think surface lifting functions).
814  //We assume the other directions are square but variable in the basis of interest.
815  const unsigned int rows = basis.m();
816  assert(rows == input_mat.m());
817  if(direction == 0){
818  for(unsigned int idiag=0; idiag<size; idiag++){
819  dealii::FullMatrix<double> local_block(rows, size);
820  std::vector<unsigned int> row_index(rows);
821  std::vector<unsigned int> col_index(size);
822  //fill index range for diagonal blocks of rize rows_x x columns_x
823  std::iota(row_index.begin(), row_index.end(), idiag*rows);
824  std::iota(col_index.begin(), col_index.end(), idiag*size);
825  //extract diagonal block from input matrix
826  local_block.extract_submatrix_from(input_mat, row_index, col_index);
827  dealii::FullMatrix<double> local_Hadamard(rows, size);
828  Hadamard_product(local_block, basis, local_Hadamard);
829  //scale by the diagonal weight from tensor product
830  local_Hadamard *= weights[idiag];
831  //write the values into diagonal block of output
832  local_Hadamard.scatter_matrix_to(row_index, col_index, output_mat);
833  }
834  }
835  if(direction == 1){
836  for(unsigned int idiag=0; idiag<rows; idiag++){
837  const unsigned int row_index = idiag * size;
838  for(unsigned int jdiag=0; jdiag<size; jdiag++){
839  const unsigned int col_index = jdiag * size;
840  for(unsigned int kdiag=0; kdiag<size; kdiag++){
841  output_mat[row_index + kdiag][col_index + kdiag] = basis[idiag][jdiag]
842  * input_mat[row_index + kdiag][col_index + kdiag]
843  * weights[kdiag];
844  }
845  }
846  }
847 
848  }
849  }
850  if constexpr(dim == 3){
851  const unsigned int rows = basis.m();
852  if(direction == 0){
853  unsigned int kdiag=0;
854  for(unsigned int idiag=0; idiag< size * size; idiag++){
855  if(kdiag==size) kdiag = 0;
856  dealii::FullMatrix<double> local_block(rows, size);
857  std::vector<unsigned int> row_index(rows);
858  std::vector<unsigned int> col_index(size);
859  //fill index range for diagonal blocks of rize rows_x x columns_x
860  std::iota(row_index.begin(), row_index.end(), idiag*rows);
861  std::iota(col_index.begin(), col_index.end(), idiag*size);
862  //extract diagonal block from input matrix
863  local_block.extract_submatrix_from(input_mat, row_index, col_index);
864  dealii::FullMatrix<double> local_Hadamard(rows, size);
865  Hadamard_product(local_block, basis, local_Hadamard);
866  //scale by the diagonal weight from tensor product
867  local_Hadamard *= weights[kdiag];
868  kdiag++;
869  const unsigned int jdiag = idiag / size;
870  local_Hadamard *= weights[jdiag];
871  //write the values into diagonal block of output
872  local_Hadamard.scatter_matrix_to(row_index, col_index, output_mat);
873  }
874  }
875  if(direction == 1){
876  for(unsigned int zdiag=0; zdiag<size; zdiag++){
877  for(unsigned int idiag=0; idiag<rows; idiag++){
878  const unsigned int row_index = zdiag * size * rows + idiag * size;
879  for(unsigned int jdiag=0; jdiag<size; jdiag++){
880  const unsigned int col_index = zdiag * size * size + jdiag * size;
881  for(unsigned int kdiag=0; kdiag<size; kdiag++){
882  output_mat[row_index + kdiag][col_index + kdiag] = basis[idiag][jdiag]
883  * input_mat[row_index + kdiag][col_index + kdiag]
884  * weights[zdiag]
885  * weights[kdiag];
886  }
887  }
888  }
889  }
890  }
891  if(direction == 2){
892  for(unsigned int row_block=0; row_block<rows; row_block++){
893  for(unsigned int col_block=0; col_block<size; col_block++){
894  const unsigned int row_index = row_block * size * size;
895  const unsigned int col_index = col_block * size * size;
896  for(unsigned int jdiag=0; jdiag<size; jdiag++){
897  for(unsigned int kdiag=0; kdiag<size; kdiag++){
898  output_mat[row_index + jdiag * size + kdiag][col_index + jdiag * size + kdiag] = basis[row_block][col_block]
899  * input_mat[row_index + jdiag * size + kdiag][col_index + jdiag * size + kdiag]
900  * weights[kdiag]
901  * weights[jdiag];
902  }
903  }
904  }
905  }
906  }
907  }
908 }
909 
910 template <int dim, int n_faces>
912  const dealii::FullMatrix<double> &input_mat1,
913  const dealii::FullMatrix<double> &input_mat2,
914  dealii::FullMatrix<double> &output_mat)
915 {
916  const unsigned int rows = input_mat1.m();
917  const unsigned int columns = input_mat1.n();
918  assert(rows == input_mat2.m());
919  assert(columns == input_mat2.n());
920 
921  for(unsigned int irow=0; irow<rows; irow++){
922  for(unsigned int icol=0; icol<columns; icol++){
923  output_mat[irow][icol] = input_mat1[irow][icol]
924  * input_mat2[irow][icol];
925  }
926  }
927 }
928 
929 template <int dim, int n_faces>
930 template <typename real>
932  const dealii::FullMatrix<double> &input_mat1,
933  const std::vector<real> &input_mat2,
934  std::vector<real> &output_mat)
935 {
936  const unsigned int rows = input_mat1.m();
937  const unsigned int columns = input_mat1.n();
938  assert(rows * columns == input_mat2.size());
939 
940  for(unsigned int irow=0; irow<rows; irow++){
941  for(unsigned int icol=0; icol<columns; icol++){
942  output_mat[irow * columns + icol] = input_mat1[irow][icol]
943  * input_mat2[irow * columns + icol];
944  }
945  }
946 }
947 
948 template <int dim, int n_faces>
950  const unsigned int rows_size,
951  const unsigned int columns_size,
952  std::vector<std::array<unsigned int,dim>> &rows,
953  std::vector<std::array<unsigned int,dim>> &columns)
954 {
955  //Note that for all directions, the rows vector should always be the same.
956  if constexpr(dim == 1){
957  for(unsigned int irow=0; irow<rows_size; irow++){
958  for(unsigned int icol=0; icol<columns_size; icol++){
959  const unsigned int array_index = irow * rows_size + icol;
960  rows[array_index][0] = irow;
961  columns[array_index][0] = icol;
962  }
963  }
964  }
965  if constexpr(dim == 2){
966  for(unsigned int idiag=0; idiag<rows_size; idiag++){
967  for(unsigned int jdiag=0; jdiag<columns_size; jdiag++){
968  for(unsigned int kdiag=0; kdiag<columns_size; kdiag++){
969  const unsigned int array_index = idiag * rows_size * columns_size + jdiag * columns_size + kdiag;
970  const unsigned int row_index = idiag * rows_size;
971  rows[array_index][0] = row_index + jdiag;
972  rows[array_index][1] = row_index + jdiag;
973  //direction 0
974  const unsigned int col_index_0 = idiag * columns_size;
975  columns[array_index][0] = col_index_0 + kdiag;
976  //direction 1
977  const unsigned int col_index_1 = kdiag * columns_size;
978  columns[array_index][1] = col_index_1 + jdiag;
979  }
980  }
981  }
982  }
983  if constexpr(dim == 3){
984  for(unsigned int idiag=0; idiag<rows_size; idiag++){
985  for(unsigned int jdiag=0; jdiag<columns_size; jdiag++){
986  for(unsigned int kdiag=0; kdiag<columns_size; kdiag++){
987  for(unsigned int ldiag=0; ldiag<columns_size; ldiag++){
988  const unsigned int array_index = idiag * rows_size * columns_size * columns_size
989  + jdiag * columns_size * columns_size
990  + kdiag * columns_size
991  + ldiag;
992  const unsigned int row_index = idiag * rows_size * columns_size
993  + jdiag * columns_size;
994  rows[array_index][0] = row_index + kdiag;
995  rows[array_index][1] = row_index + kdiag;
996  rows[array_index][2] = row_index + kdiag;
997  //direction 0
998  const unsigned int col_index_0 = idiag * columns_size * columns_size
999  + jdiag * columns_size;
1000  columns[array_index][0] = col_index_0 + ldiag;
1001  //direction 1
1002  const unsigned int col_index_1 = ldiag * columns_size;
1003  columns[array_index][1] = col_index_1 + kdiag + idiag * columns_size * columns_size;
1004  //direction 2
1005  const unsigned int col_index_2 = ldiag * columns_size * columns_size;
1006  columns[array_index][2] = col_index_2 + kdiag + jdiag * columns_size;
1007  }
1008  }
1009  }
1010  }
1011  }
1012 }
1013 template <int dim, int n_faces>
1015  const unsigned int rows_size_1D,
1016  const unsigned int columns_size_1D,
1017  const std::vector<std::array<unsigned int,dim>> &rows,
1018  const std::vector<std::array<unsigned int,dim>> &columns,
1019  const dealii::FullMatrix<double> &basis,
1020  const std::vector<double> &weights,
1021  std::array<dealii::FullMatrix<double>,dim> &basis_sparse)
1022 {
1023  if constexpr(dim == 1){
1024  for(unsigned int irow=0; irow<rows_size_1D; irow++){
1025  for(unsigned int icol=0; icol<columns_size_1D; icol++){
1026  basis_sparse[0][irow][icol] = basis[irow][icol];
1027  }
1028  }
1029  }
1030  if constexpr(dim == 2){
1031  const unsigned int total_size = rows.size();
1032  for(unsigned int index=0, counter=0; index<total_size; index++, counter++){
1033  if(counter == columns_size_1D){
1034  counter = 0;
1035  }
1036  //direction 0
1037  basis_sparse[0][rows[index][0]][counter] = basis[rows[index][0]%rows_size_1D][columns[index][0]%columns_size_1D]
1038  * weights[rows[index][1]/columns_size_1D];
1039  //direction 1
1040  basis_sparse[1][rows[index][1]][counter] = basis[rows[index][1]/rows_size_1D][columns[index][1]/columns_size_1D]
1041  * weights[rows[index][0]%columns_size_1D];
1042  }
1043  }
1044  if constexpr(dim == 3){
1045  const unsigned int total_size = rows.size();
1046  for(unsigned int index=0, counter=0; index<total_size; index++, counter++){
1047  if(counter == columns_size_1D){
1048  counter = 0;
1049  }
1050  //direction 0
1051  basis_sparse[0][rows[index][0]][counter] = basis[rows[index][0]%rows_size_1D][columns[index][0]%columns_size_1D]
1052  * weights[(rows[index][1]/columns_size_1D)%columns_size_1D]
1053  * weights[rows[index][2]/columns_size_1D/columns_size_1D];
1054  //direction 1
1055  basis_sparse[1][rows[index][1]][counter] = basis[(rows[index][1]/rows_size_1D)%rows_size_1D][(columns[index][1]/columns_size_1D)%columns_size_1D]
1056  * weights[rows[index][0]%columns_size_1D]
1057  * weights[rows[index][2]/columns_size_1D/columns_size_1D];
1058  //direction 2
1059  basis_sparse[2][rows[index][2]][counter] = basis[rows[index][2]/rows_size_1D/rows_size_1D][columns[index][2]/columns_size_1D/columns_size_1D]
1060  * weights[rows[index][0]%columns_size_1D]
1061  * weights[(rows[index][1]/columns_size_1D)%columns_size_1D];
1062  }
1063  }
1064 
1065 }
1066 template <int dim, int n_faces>
1068  const unsigned int rows_size,
1069  const unsigned int columns_size,
1070  std::vector<unsigned int> &rows,
1071  std::vector<unsigned int> &columns,
1072  const int dim_not_zero)
1073 {
1074  //Note that for all directions, the rows vector should always be the same.
1075  if constexpr(dim == 1){
1076  for(unsigned int irow=0; irow<rows_size; irow++){
1077  for(unsigned int icol=0; icol<columns_size; icol++){
1078  const unsigned int array_index = irow * columns_size + icol;
1079  rows[array_index] = irow;
1080  columns[array_index] = icol;
1081  }
1082  }
1083  }
1084  if constexpr(dim == 2){
1085  for(unsigned int idiag=0; idiag<rows_size; idiag++){
1086  for(unsigned int jdiag=0; jdiag<columns_size; jdiag++){
1087  const unsigned int array_index = idiag * columns_size + jdiag ;
1088 
1089  const unsigned int row_index = idiag;
1090  rows[array_index] = row_index;
1091  //direction 0
1092  if(dim_not_zero == 0){
1093  const unsigned int col_index_0 = idiag * columns_size;
1094  columns[array_index] = col_index_0 + jdiag;
1095  }
1096  //direction 1
1097  if(dim_not_zero == 1){
1098  const unsigned int col_index_1 = jdiag * columns_size;
1099  columns[array_index] = col_index_1 + idiag;
1100  }
1101  }
1102  }
1103  }
1104  if constexpr(dim == 3){
1105  for(unsigned int idiag=0; idiag<columns_size; idiag++){
1106  for(unsigned int jdiag=0; jdiag<columns_size; jdiag++){
1107  for(unsigned int kdiag=0; kdiag<columns_size; kdiag++){
1108  const unsigned int array_index = idiag * columns_size * columns_size
1109  + jdiag * columns_size
1110  + kdiag;
1111  const unsigned int row_index = idiag * columns_size + jdiag;
1112  rows[array_index] = row_index;
1113  //direction 0
1114  if(dim_not_zero == 0){
1115  const unsigned int col_index_0 = idiag * columns_size * columns_size
1116  + jdiag * columns_size;
1117  columns[array_index] = col_index_0 + kdiag;
1118  }
1119  //direction 1
1120  if(dim_not_zero == 1){
1121  const unsigned int col_index_1 = kdiag * columns_size;
1122  columns[array_index] = col_index_1 + jdiag + idiag * columns_size * columns_size;
1123  }
1124  //direction 2
1125  if(dim_not_zero == 2){
1126  const unsigned int col_index_2 = kdiag * columns_size * columns_size;
1127  columns[array_index] = col_index_2 + jdiag + idiag * columns_size;
1128  }
1129  }
1130  }
1131  }
1132  }
1133 }
1134 template <int dim, int n_faces>
1136  const unsigned int rows_size,
1137  const unsigned int columns_size_1D,
1138  const std::vector<unsigned int> &rows,
1139  const std::vector<unsigned int> &columns,
1140  const dealii::FullMatrix<double> &basis,
1141  const std::vector<double> &weights,
1142  dealii::FullMatrix<double> &basis_sparse,
1143  const int dim_not_zero)
1144 {
1145  if constexpr(dim == 1){
1146  for(unsigned int irow=0; irow<rows_size; irow++){
1147  for(unsigned int icol=0; icol<columns_size_1D; icol++){
1148  basis_sparse[irow][icol] = basis[irow][icol];
1149  }
1150  }
1151  }
1152  if constexpr(dim == 2){
1153  const unsigned int total_size = rows.size();
1154  for(unsigned int index=0, counter=0; index<total_size; index++, counter++){
1155  if(counter == columns_size_1D){
1156  counter = 0;
1157  }
1158  //direction 0
1159  if(dim_not_zero == 0){
1160  basis_sparse[rows[index]][counter] = basis[0][columns[index]%columns_size_1D]//oneD surf basis only 1 point
1161  * weights[rows[index]%columns_size_1D];
1162  }
1163  //direction 1
1164  if(dim_not_zero == 1){
1165  basis_sparse[rows[index]][counter] = basis[0][columns[index]/columns_size_1D]
1166  * weights[rows[index]%columns_size_1D];
1167  }
1168  }
1169  }
1170  if constexpr(dim == 3){
1171  const unsigned int total_size = rows.size();
1172  for(unsigned int index=0, counter=0; index<total_size; index++, counter++){
1173  if(counter == columns_size_1D){
1174  counter = 0;
1175  }
1176  //direction 0
1177  if(dim_not_zero == 0){
1178  basis_sparse[rows[index]][counter] = basis[0][columns[index]%columns_size_1D]//oneD surf basis only 1 point
1179  * weights[rows[index]%columns_size_1D]
1180  * weights[rows[index]/columns_size_1D];
1181  }
1182  //direction 1
1183  if(dim_not_zero == 1){
1184  basis_sparse[rows[index]][counter] = basis[0][(columns[index]/columns_size_1D)%columns_size_1D]
1185  * weights[rows[index]%columns_size_1D]
1186  * weights[rows[index]/columns_size_1D];
1187  }
1188  //direction 2
1189  if(dim_not_zero == 2){
1190  basis_sparse[rows[index]][counter] = basis[0][columns[index]/columns_size_1D/columns_size_1D]
1191  * weights[rows[index]%columns_size_1D]
1192  * weights[rows[index]/columns_size_1D];
1193  }
1194  }
1195  }
1196 }
1197 
1198 /*******************************************
1199  *
1200  * VOLUME OPERATORS FUNCTIONS
1201  *
1202  *
1203  ******************************************/
1204 
1205 template <int dim, int n_faces>
1207  const int nstate_input,
1208  const unsigned int max_degree_input,
1209  const unsigned int grid_degree_input)
1210  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
1211 {
1212  //Initialize to the max degrees
1213  current_degree = max_degree_input;
1214 }
1215 
1216 template <int dim, int n_faces>
1218  const dealii::FESystem<1,1> &finite_element,
1219  const dealii::Quadrature<1> &quadrature)
1220 {
1221  const unsigned int n_quad_pts = quadrature.size();
1222  const unsigned int n_dofs = finite_element.dofs_per_cell;
1223  //allocate the basis at volume cubature
1224  this->oneD_vol_operator.reinit(n_quad_pts, n_dofs);
1225  //loop and store
1226  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
1227  const dealii::Point<1> qpoint = quadrature.point(iquad);
1228  for(unsigned int idof=0; idof<n_dofs; idof++){
1229  const int istate = finite_element.system_to_component_index(idof).first;
1230  //Basis function idof of poly degree idegree evaluated at cubature node qpoint.
1231  this->oneD_vol_operator[iquad][idof] = finite_element.shape_value_component(idof,qpoint,istate);
1232  }
1233  }
1234 }
1235 
1236 template <int dim, int n_faces>
1238  const dealii::FESystem<1,1> &finite_element,
1239  const dealii::Quadrature<1> &quadrature)
1240 {
1241  const unsigned int n_quad_pts = quadrature.size();
1242  const unsigned int n_dofs = finite_element.dofs_per_cell;
1243  //allocate the basis at volume cubature
1244  this->oneD_grad_operator.reinit(n_quad_pts, n_dofs);
1245  //loop and store
1246  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
1247  const dealii::Point<1> qpoint = quadrature.point(iquad);
1248  for(unsigned int idof=0; idof<n_dofs; idof++){
1249  const int istate = finite_element.system_to_component_index(idof).first;
1250  //Basis function idof of poly degree idegree evaluated at cubature node qpoint.
1251  this->oneD_grad_operator[iquad][idof] = finite_element.shape_grad_component(idof,qpoint,istate)[0];
1252  }
1253  }
1254 }
1255 
1256 template <int dim, int n_faces>
1258  const dealii::FESystem<1,1> &finite_element,
1259  const dealii::Quadrature<0> &face_quadrature)
1260 {
1261  const unsigned int n_face_quad_pts = face_quadrature.size();
1262  const unsigned int n_dofs = finite_element.dofs_per_cell;
1263  const unsigned int n_faces_1D = n_faces / dim;
1264  //loop and store
1265  for(unsigned int iface=0; iface<n_faces_1D; iface++){
1266  //allocate the facet operator
1267  this->oneD_surf_operator[iface].reinit(n_face_quad_pts, n_dofs);
1268  //sum factorized operators use a 1D element.
1269  const dealii::Quadrature<1> quadrature = dealii::QProjector<1>::project_to_face(dealii::ReferenceCell::get_hypercube(1),
1270  face_quadrature,
1271  iface);
1272  for(unsigned int iquad=0; iquad<n_face_quad_pts; iquad++){
1273  const dealii::Point<1> qpoint = quadrature.point(iquad);
1274  for(unsigned int idof=0; idof<n_dofs; idof++){
1275  const int istate = finite_element.system_to_component_index(idof).first;
1276  //Basis function idof of poly degree idegree evaluated at cubature node qpoint.
1277  this->oneD_surf_operator[iface][iquad][idof] = finite_element.shape_value_component(idof,qpoint,istate);
1278  }
1279  }
1280  }
1281 }
1282 
1283 template <int dim, int n_faces>
1285  const dealii::FESystem<1,1> &finite_element,
1286  const dealii::Quadrature<0> &face_quadrature)
1287 {
1288  const unsigned int n_face_quad_pts = face_quadrature.size();
1289  const unsigned int n_dofs = finite_element.dofs_per_cell;
1290  const unsigned int n_faces_1D = n_faces / dim;
1291  //loop and store
1292  for(unsigned int iface=0; iface<n_faces_1D; iface++){
1293  //allocate the facet operator
1294  this->oneD_surf_grad_operator[iface].reinit(n_face_quad_pts, n_dofs);
1295  //sum factorized operators use a 1D element.
1296  const dealii::Quadrature<1> quadrature = dealii::QProjector<1>::project_to_face(dealii::ReferenceCell::get_hypercube(1),
1297  face_quadrature,
1298  iface);
1299  for(unsigned int iquad=0; iquad<n_face_quad_pts; iquad++){
1300  const dealii::Point<1> qpoint = quadrature.point(iquad);
1301  for(unsigned int idof=0; idof<n_dofs; idof++){
1302  const int istate = finite_element.system_to_component_index(idof).first;
1303  //Basis function idof of poly degree idegree evaluated at cubature node qpoint.
1304  this->oneD_surf_grad_operator[iface][iquad][idof] = finite_element.shape_grad_component(idof,qpoint,istate)[0];
1305  }
1306  }
1307  }
1308 }
1309 
1310 template <int dim, int n_faces>
1312  const int nstate_input,
1313  const unsigned int max_degree_input,
1314  const unsigned int grid_degree_input)
1315  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
1316 {
1317  //Initialize to the max degrees
1318  current_degree = max_degree_input;
1319 }
1320 
1321 template <int dim, int n_faces>
1323  const dealii::FESystem<1,1> &finite_element,
1324  const dealii::Quadrature<1> &quadrature)
1325 {
1326  const unsigned int n_quad_pts = quadrature.size();
1327  const unsigned int n_dofs = finite_element.dofs_per_cell;
1328  //allocate
1329  this->oneD_vol_operator.reinit(n_quad_pts, n_dofs);
1330  //loop and store
1331  const std::vector<double> &quad_weights = quadrature.get_weights ();
1332  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
1333  const dealii::Point<1> qpoint = quadrature.point(iquad);
1334  for(unsigned int idof=0; idof<n_dofs; idof++){
1335  const int istate = finite_element.system_to_component_index(idof).first;
1336  //Basis function idof of poly degree idegree evaluated at cubature node qpoint multiplied by quad weight.
1337  this->oneD_vol_operator[iquad][idof] = quad_weights[iquad] * finite_element.shape_value_component(idof,qpoint,istate);
1338  }
1339  }
1340 }
1341 
1342 template <int dim, int n_faces>
1344  const int nstate_input,
1345  const unsigned int max_degree_input,
1346  const unsigned int grid_degree_input)
1347  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
1348 {
1349  //Initialize to the max degrees
1350  current_degree = max_degree_input;
1351 }
1352 
1353 template <int dim, int n_faces>
1355  const dealii::FESystem<1,1> &finite_element,
1356  const dealii::Quadrature<1> &quadrature)
1357 {
1358  const unsigned int n_quad_pts = quadrature.size();
1359  const unsigned int n_dofs = finite_element.dofs_per_cell;
1360  const std::vector<double> &quad_weights = quadrature.get_weights ();
1361  //allocate
1362  this->oneD_vol_operator.reinit(n_dofs,n_dofs);
1363  //loop and store
1364  for (unsigned int itest=0; itest<n_dofs; ++itest) {
1365  const int istate_test = finite_element.system_to_component_index(itest).first;
1366  for (unsigned int itrial=itest; itrial<n_dofs; ++itrial) {
1367  const int istate_trial = finite_element.system_to_component_index(itrial).first;
1368  double value = 0.0;
1369  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
1370  const dealii::Point<1> qpoint = quadrature.point(iquad);
1371  value +=
1372  finite_element.shape_value_component(itest,qpoint,istate_test)
1373  * finite_element.shape_value_component(itrial,qpoint,istate_trial)
1374  * quad_weights[iquad];
1375  }
1376 
1377  this->oneD_vol_operator[itrial][itest] = 0.0;
1378  this->oneD_vol_operator[itest][itrial] = 0.0;
1379  if(istate_test==istate_trial) {
1380  this->oneD_vol_operator[itrial][itest] = value;
1381  this->oneD_vol_operator[itest][itrial] = value;
1382  }
1383  }
1384  }
1385 }
1386 
1387 template <int dim, int n_faces>
1389  const int nstate,
1390  const unsigned int n_dofs, const unsigned int n_quad_pts,
1392  const std::vector<double> &det_Jac,
1393  const std::vector<double> &quad_weights)
1394 
1395 {
1396  const unsigned int n_shape_fns = n_dofs / nstate;
1397  assert(nstate*pow(basis.oneD_vol_operator.m() / nstate, dim) == n_dofs);
1398  dealii::FullMatrix<double> mass_matrix_dim(n_dofs);
1399  dealii::FullMatrix<double> basis_dim(n_dofs);
1400  basis_dim = basis.tensor_product_state(
1401  nstate,
1402  basis.oneD_vol_operator,
1403  basis.oneD_vol_operator,
1404  basis.oneD_vol_operator);
1405  //loop and store
1406  for(int istate=0; istate<nstate; istate++){
1407  for(unsigned int itest=0; itest<n_shape_fns; ++itest){
1408  for (unsigned int itrial=itest; itrial<n_shape_fns; ++itrial) {
1409  double value = 0.0;
1410  const unsigned int trial_index = istate*n_shape_fns + itrial;
1411  const unsigned int test_index = istate*n_shape_fns + itest;
1412  for (unsigned int iquad=0; iquad<n_quad_pts; ++iquad) {
1413  value += basis_dim[iquad][test_index]
1414  * basis_dim[iquad][trial_index]
1415  * det_Jac[iquad]
1416  * quad_weights[iquad];
1417  }
1418  mass_matrix_dim[trial_index][test_index] = value;
1419  mass_matrix_dim[test_index][trial_index] = value;
1420  }
1421  }
1422  }
1423  return mass_matrix_dim;
1424 }
1425 
1426 template <int dim, int n_faces>
1428  const int nstate_input,
1429  const unsigned int max_degree_input,
1430  const unsigned int grid_degree_input,
1431  const bool store_skew_symmetric_form_input)
1432  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
1433  , store_skew_symmetric_form(store_skew_symmetric_form_input)
1434 {
1435  //Initialize to the max degrees
1436  current_degree = max_degree_input;
1437 }
1438 
1439 template <int dim, int n_faces>
1441  const dealii::FESystem<1,1> &finite_element,
1442  const dealii::Quadrature<1> &quadrature)
1443 {
1444  const unsigned int n_quad_pts = quadrature.size();
1445  const unsigned int n_dofs = finite_element.dofs_per_cell;
1446  const std::vector<double> &quad_weights = quadrature.get_weights ();
1447  //allocate
1448  this->oneD_vol_operator.reinit(n_dofs,n_dofs);
1449  //loop and store
1450  for(unsigned int itest=0; itest<n_dofs; itest++){
1451  const int istate_test = finite_element.system_to_component_index(itest).first;
1452  for(unsigned int idof=0; idof<n_dofs; idof++){
1453  const int istate = finite_element.system_to_component_index(idof).first;
1454  double value = 0.0;
1455  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
1456  const dealii::Point<1> qpoint = quadrature.point(iquad);
1457  value += finite_element.shape_value_component(itest,qpoint,istate_test)
1458  * finite_element.shape_grad_component(idof, qpoint, istate)[0]//since it's a 1D operator
1459  * quad_weights[iquad];
1460  }
1461  if(istate == istate_test){
1462  this->oneD_vol_operator[itest][idof] = value;
1463  }
1464  }
1465  }
1467  //allocate
1468  oneD_skew_symm_vol_oper.reinit(n_dofs,n_dofs);
1469  //solve
1470  for(unsigned int idof=0; idof<n_dofs; idof++){
1471  for(unsigned int jdof=0; jdof<n_dofs; jdof++){
1472  oneD_skew_symm_vol_oper[idof][jdof] = this->oneD_vol_operator[idof][jdof]
1473  - this->oneD_vol_operator[jdof][idof];
1474  }
1475  }
1476  }
1477 }
1478 
1479 template <int dim, int n_faces>
1481  const int nstate_input,
1482  const unsigned int max_degree_input,
1483  const unsigned int grid_degree_input)
1484  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
1485 {
1486  //Initialize to the max degrees
1487  current_degree = max_degree_input;
1488 }
1489 
1490 template <int dim, int n_faces>
1492  const dealii::FESystem<1,1> &finite_element,
1493  const dealii::Quadrature<1> &quadrature)
1494 {
1495  const unsigned int n_dofs = finite_element.dofs_per_cell;
1496  local_mass<dim,n_faces> mass_matrix(this->nstate, this->max_degree, this->max_grid_degree);
1497  mass_matrix.build_1D_volume_operator(finite_element, quadrature);
1499  stiffness.build_1D_volume_operator(finite_element, quadrature);
1500  //allocate
1501  this->oneD_vol_operator.reinit(n_dofs,n_dofs);
1502  dealii::FullMatrix<double> inv_mass(n_dofs);
1503  inv_mass.invert(mass_matrix.oneD_vol_operator);
1504  //solves
1505  inv_mass.mmult(this->oneD_vol_operator, stiffness.oneD_vol_operator);
1506 }
1507 
1508 template <int dim, int n_faces>
1510  const int nstate_input,
1511  const unsigned int max_degree_input,
1512  const unsigned int grid_degree_input)
1513  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
1514 {
1515  //Initialize to the max degrees
1516  current_degree = max_degree_input;
1517 }
1518 
1519 template <int dim, int n_faces>
1521  const dealii::FESystem<1,1> &finite_element,
1522  const dealii::Quadrature<1> &quadrature)
1523 {
1524  const unsigned int n_dofs = finite_element.dofs_per_cell;
1525  //allocate
1526  this->oneD_vol_operator.reinit(n_dofs,n_dofs);
1527  //set as identity
1528  for(unsigned int idof=0; idof<n_dofs; idof++){
1529  this->oneD_vol_operator[idof][idof] = 1.0;//set it equal to identity
1530  }
1531  //get modal basis differential operator
1533  diff_oper.build_1D_volume_operator(finite_element, quadrature);
1534  //loop and solve
1535  for(unsigned int idegree=0; idegree< this->max_degree; idegree++){
1536  dealii::FullMatrix<double> derivative_p_temp(n_dofs, n_dofs);
1537  derivative_p_temp.add(1.0, this->oneD_vol_operator);
1538  diff_oper.oneD_vol_operator.mmult(this->oneD_vol_operator, derivative_p_temp);
1539  }
1540 }
1541 
1542 template <int dim, int n_faces>
1544  const int nstate_input,
1545  const unsigned int max_degree_input,
1546  const unsigned int grid_degree_input,
1548  const double FR_user_specified_correction_parameter_value_input)
1549  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
1550  , FR_param_type(FR_param_input)
1551  , FR_user_specified_correction_parameter_value(FR_user_specified_correction_parameter_value_input)
1552 {
1553  //Initialize to the max degrees
1554  current_degree = max_degree_input;
1555  //get the FR corrcetion parameter value
1557 }
1558 
1559 template <int dim, int n_faces>
1561  const unsigned int curr_cell_degree,
1562  double &c)
1563 {
1564  const double pfact = this->compute_factorial(curr_cell_degree);
1565  const double pfact2 = this->compute_factorial(2.0 * curr_cell_degree);
1566  double cp = pfact2/(pow(pfact,2));//since ref element [0,1]
1567  c = 2.0 * (curr_cell_degree+1)/( curr_cell_degree*((2.0*curr_cell_degree+1.0)*(pow(pfact*cp,2))));
1568  c/=2.0;//since orthonormal
1569 }
1570 template <int dim, int n_faces>
1572  const unsigned int curr_cell_degree,
1573  double &c)
1574 {
1575  const double pfact = this->compute_factorial(curr_cell_degree);
1576  const double pfact2 = this->compute_factorial(2.0 * curr_cell_degree);
1577  double cp = pfact2/(pow(pfact,2));
1578  c = 2.0 * (curr_cell_degree)/( (curr_cell_degree+1.0)*((2.0*curr_cell_degree+1.0)*(pow(pfact*cp,2))));
1579  c/=2.0;//since orthonormal
1580 }
1581 template <int dim, int n_faces>
1583  const unsigned int curr_cell_degree,
1584  double &c)
1585 {
1586  const double pfact = this->compute_factorial(curr_cell_degree);
1587  const double pfact2 = this->compute_factorial(2.0 * curr_cell_degree);
1588  double cp = pfact2/(pow(pfact,2));
1589  c = - 2.0 / ( pow((2.0*curr_cell_degree+1.0)*(pow(pfact*cp,2)),1.0));
1590  c/=2.0;//since orthonormal
1591 }
1592 template <int dim, int n_faces>
1594  const unsigned int curr_cell_degree,
1595  double &c)
1596 {
1597  get_c_negative_FR_parameter(curr_cell_degree, c);
1598  c/=2.0;
1599 }
1600 template <int dim, int n_faces>
1602  const unsigned int curr_cell_degree,
1603  double &c)
1604 {
1605  if(curr_cell_degree == 2){
1606  c = 0.186;
1607 // c = 0.173;//RK33
1608  }
1609  else if(curr_cell_degree == 3){
1610  c = 3.67e-3;
1611  }
1612  else if(curr_cell_degree == 4){
1613  c = 4.79e-5;
1614 // c = 4.92e-5;//RK33
1615  }
1616  else if(curr_cell_degree == 5){
1617  c = 4.24e-7;
1618  }
1619  else{
1620  this->pcout << "ERROR: cPlus values are only defined for p=2 through p=5. Aborting..." << std::endl;
1621  std::abort();
1622  }
1623 
1624  c/=2.0;//since orthonormal
1625  c/=pow(pow(2.0,curr_cell_degree),2);//since ref elem [0,1]
1626 }
1627 
1628 template <int dim, int n_faces>
1630  const unsigned int curr_cell_degree,
1631  double &c)
1632 {
1634  if(FR_param_type == FR_enum::cHU || FR_param_type == FR_enum::cHULumped){
1635  get_Huynh_g2_parameter(curr_cell_degree, c);
1636  }
1637  else if(FR_param_type == FR_enum::cSD){
1638  get_spectral_difference_parameter(curr_cell_degree, c);
1639  }
1640  else if(FR_param_type == FR_enum::cNegative){
1641  get_c_negative_FR_parameter(curr_cell_degree, c);
1642  }
1643  else if(FR_param_type == FR_enum::cNegative2){
1644  get_c_negative_divided_by_two_FR_parameter(curr_cell_degree, c);
1645  }
1646  else if(FR_param_type == FR_enum::cDG){
1647  //DG case is the 0.0 case.
1648  c = 0.0;
1649  }
1650  else if(FR_param_type == FR_enum::c10Thousand){
1651  //Set the value to 10000 for arbitrary high-numbers.
1652  c = 10000.0;
1653  }
1654  else if(FR_param_type == FR_enum::cPlus){
1655  get_c_plus_parameter(curr_cell_degree, c);
1656  } else if(FR_param_type == FR_enum::user_specified_value) {
1658  c/=2.0;//since orthonormal
1659  c/=pow(pow(2.0,curr_cell_degree),2);//since ref elem [0,1]
1660  }
1661 }
1662 template <int dim, int n_faces>
1664  const dealii::FullMatrix<double> &local_Mass_Matrix,
1665  const dealii::FullMatrix<double> &pth_derivative,
1666  const unsigned int n_dofs,
1667  const double c,
1668  dealii::FullMatrix<double> &Flux_Reconstruction_operator)
1669 {
1670  dealii::FullMatrix<double> derivative_p_temp(n_dofs);
1671  derivative_p_temp.add(c, pth_derivative);
1672  dealii::FullMatrix<double> Flux_Reconstruction_operator_temp(n_dofs);
1673  derivative_p_temp.Tmmult(Flux_Reconstruction_operator_temp, local_Mass_Matrix);
1674  Flux_Reconstruction_operator_temp.mmult(Flux_Reconstruction_operator, pth_derivative);
1675 }
1676 
1677 
1678 template <int dim, int n_faces>
1680  const dealii::FESystem<1,1> &finite_element,
1681  const dealii::Quadrature<1> &quadrature)
1682 {
1683  const unsigned int n_dofs = finite_element.dofs_per_cell;
1684  //allocate the volume operator
1685  this->oneD_vol_operator.reinit(n_dofs, n_dofs);
1686  //build the FR correction operator
1687  derivative_p<dim,n_faces> pth_derivative(this->nstate, this->max_degree, this->max_grid_degree);
1688  pth_derivative.build_1D_volume_operator(finite_element, quadrature);
1689 
1690  local_mass<dim,n_faces> local_Mass_Matrix(this->nstate, this->max_degree, this->max_grid_degree);
1691  local_Mass_Matrix.build_1D_volume_operator(finite_element, quadrature);
1692  //solves
1693  build_local_Flux_Reconstruction_operator(local_Mass_Matrix.oneD_vol_operator, pth_derivative.oneD_vol_operator, n_dofs, FR_param, this->oneD_vol_operator);
1694 }
1695 
1696 template <int dim, int n_faces>
1698  const int nstate,
1699  const unsigned int n_dofs,
1700  dealii::FullMatrix<double> &pth_deriv,
1701  dealii::FullMatrix<double> &mass_matrix)
1702 {
1703  dealii::FullMatrix<double> Flux_Reconstruction_operator(n_dofs);
1704  dealii::FullMatrix<double> identity (dealii::IdentityMatrix(pth_deriv.m()));
1705  for(int idim=0; idim<dim; idim++){
1706  dealii::FullMatrix<double> pth_deriv_dim(n_dofs);
1707  if(idim==0){
1708  pth_deriv_dim = this->tensor_product_state(nstate, pth_deriv, identity, identity);
1709  }
1710  if(idim==1){
1711  pth_deriv_dim = this->tensor_product_state(nstate, identity, pth_deriv, identity);
1712  }
1713  if(idim==2){
1714  pth_deriv_dim = this->tensor_product_state(nstate, identity, identity, pth_deriv);
1715  }
1716  dealii::FullMatrix<double> derivative_p_temp(n_dofs);
1717  derivative_p_temp.add(FR_param, pth_deriv_dim);
1718  dealii::FullMatrix<double> Flux_Reconstruction_operator_temp(n_dofs);
1719  derivative_p_temp.Tmmult(Flux_Reconstruction_operator_temp, mass_matrix);
1720  Flux_Reconstruction_operator_temp.mmult(Flux_Reconstruction_operator, pth_deriv_dim, true);
1721  }
1722  if constexpr (dim>=2){
1723  const int deriv_2p_loop = (dim==2) ? 1 : dim;
1724  double FR_param_sqrd = pow(FR_param,2.0);
1725  for(int idim=0; idim<deriv_2p_loop; idim++){
1726  dealii::FullMatrix<double> pth_deriv_dim(n_dofs);
1727  if(idim==0){
1728  pth_deriv_dim = this->tensor_product_state(nstate, pth_deriv, pth_deriv, identity);
1729  }
1730  if(idim==1){
1731  pth_deriv_dim = this->tensor_product_state(nstate, identity, pth_deriv, pth_deriv);
1732  }
1733  if(idim==2){
1734  pth_deriv_dim = this->tensor_product_state(nstate, pth_deriv, identity, pth_deriv);
1735  }
1736  dealii::FullMatrix<double> derivative_p_temp(n_dofs);
1737  derivative_p_temp.add(FR_param_sqrd, pth_deriv_dim);
1738  dealii::FullMatrix<double> Flux_Reconstruction_operator_temp(n_dofs);
1739  derivative_p_temp.Tmmult(Flux_Reconstruction_operator_temp, mass_matrix);
1740  Flux_Reconstruction_operator_temp.mmult(Flux_Reconstruction_operator, pth_deriv_dim, true);
1741  }
1742  }
1743  if constexpr (dim == 3){
1744  double FR_param_cubed = pow(FR_param,3.0);
1745  dealii::FullMatrix<double> pth_deriv_dim(n_dofs);
1746  pth_deriv_dim = this->tensor_product_state(nstate, pth_deriv, pth_deriv, pth_deriv);
1747  dealii::FullMatrix<double> derivative_p_temp(n_dofs);
1748  derivative_p_temp.add(FR_param_cubed, pth_deriv_dim);
1749  dealii::FullMatrix<double> Flux_Reconstruction_operator_temp(n_dofs);
1750  derivative_p_temp.Tmmult(Flux_Reconstruction_operator_temp, mass_matrix);
1751  Flux_Reconstruction_operator_temp.mmult(Flux_Reconstruction_operator, pth_deriv_dim, true);
1752  }
1753 
1754  return Flux_Reconstruction_operator;
1755 }
1756 
1757 template <int dim, int n_faces>
1759  const dealii::FullMatrix<double> &local_Mass_Matrix,
1760  const int nstate,
1761  const unsigned int n_dofs)
1762 {
1763  dealii::FullMatrix<double> dim_FR_operator(n_dofs);
1764  if constexpr (dim == 1){
1765  dim_FR_operator = this->oneD_vol_operator;
1766  }
1767  if (dim >= 2){
1768  dealii::FullMatrix<double> FR1(n_dofs);
1769  FR1 = this->tensor_product_state(nstate, this->oneD_vol_operator, local_Mass_Matrix, local_Mass_Matrix);
1770  dealii::FullMatrix<double> FR2(n_dofs);
1771  FR2 = this->tensor_product_state(nstate, local_Mass_Matrix, this->oneD_vol_operator, local_Mass_Matrix);
1772  dealii::FullMatrix<double> FR_cross1(n_dofs);
1773  FR_cross1 = this->tensor_product_state(nstate, this->oneD_vol_operator, this->oneD_vol_operator, local_Mass_Matrix);
1774  dim_FR_operator.add(1.0, FR1, 1.0, FR2, 1.0, FR_cross1);
1775  }
1776  if constexpr (dim == 3){
1777  dealii::FullMatrix<double> FR3(n_dofs);
1778  FR3 = this->tensor_product_state(nstate, local_Mass_Matrix, local_Mass_Matrix, this->oneD_vol_operator);
1779  dealii::FullMatrix<double> FR_cross2(n_dofs);
1780  FR_cross2 = this->tensor_product_state(nstate, this->oneD_vol_operator, local_Mass_Matrix, this->oneD_vol_operator);
1781  dealii::FullMatrix<double> FR_cross3(n_dofs);
1782  FR_cross3 = this->tensor_product_state(nstate, local_Mass_Matrix, this->oneD_vol_operator, this->oneD_vol_operator);
1783  dealii::FullMatrix<double> FR_triple(n_dofs);
1784  FR_triple = this->tensor_product_state(nstate, this->oneD_vol_operator, this->oneD_vol_operator, this->oneD_vol_operator);
1785  dim_FR_operator.add(1.0, FR3, 1.0, FR_cross2, 1.0, FR_cross3);
1786  dim_FR_operator.add(1.0, FR_triple);
1787  }
1788  return dim_FR_operator;
1789 
1790 }
1791 
1792 
1793 template <int dim, int n_faces>
1795  const int nstate_input,
1796  const unsigned int max_degree_input,
1797  const unsigned int grid_degree_input,
1798  const Parameters::AllParameters::Flux_Reconstruction_Aux FR_param_aux_input)
1799  : local_Flux_Reconstruction_operator<dim,n_faces>::local_Flux_Reconstruction_operator(nstate_input, max_degree_input, grid_degree_input, Parameters::AllParameters::Flux_Reconstruction::cDG, 0.0) // Note: cDG and 0.0 are passed as dummy variables
1800  , FR_param_aux_type(FR_param_aux_input)
1801 {
1802  //Initialize to the max degrees
1803  current_degree = max_degree_input;
1804  //get the FR corrcetion parameter value
1806 }
1807 
1808 template <int dim, int n_faces>
1810  const unsigned int curr_cell_degree,
1811  double &k)
1812 {
1814  if(FR_param_aux_type == FR_Aux_enum::kHU){
1815  this->get_Huynh_g2_parameter(curr_cell_degree, k);
1816  }
1817  else if(FR_param_aux_type == FR_Aux_enum::kSD){
1818  this->get_spectral_difference_parameter(curr_cell_degree, k);
1819  }
1820  else if(FR_param_aux_type == FR_Aux_enum::kNegative){
1821  this->get_c_negative_FR_parameter(curr_cell_degree, k);
1822  }
1823  else if(FR_param_aux_type == FR_Aux_enum::kNegative2){//knegative divided by 2
1824  this->get_c_negative_divided_by_two_FR_parameter(curr_cell_degree, k);
1825  }
1826  else if(FR_param_aux_type == FR_Aux_enum::kDG){
1827  k = 0.0;
1828  }
1829  else if(FR_param_aux_type == FR_Aux_enum::k10Thousand){
1830  k = 10000.0;
1831  }
1832  else if(FR_param_aux_type == FR_Aux_enum::kPlus){
1833  this->get_c_plus_parameter(curr_cell_degree, k);
1834  }
1835 }
1836 template <int dim, int n_faces>
1838  const dealii::FESystem<1,1> &finite_element,
1839  const dealii::Quadrature<1> &quadrature)
1840 {
1841  const unsigned int n_dofs = finite_element.dofs_per_cell;
1842  //build the FR correction operator
1843  derivative_p<dim,n_faces> pth_derivative(this->nstate, this->max_degree, this->max_grid_degree);
1844  pth_derivative.build_1D_volume_operator(finite_element, quadrature);
1845  local_mass<dim,n_faces> local_Mass_Matrix(this->nstate, this->max_degree, this->max_grid_degree);
1846  local_Mass_Matrix.build_1D_volume_operator(finite_element, quadrature);
1847  //allocate the volume operator
1848  this->oneD_vol_operator.reinit(n_dofs, n_dofs);
1849  //solves
1850  this->build_local_Flux_Reconstruction_operator(local_Mass_Matrix.oneD_vol_operator, pth_derivative.oneD_vol_operator, n_dofs, FR_param_aux, this->oneD_vol_operator);
1851 }
1852 
1853 template <int dim, int n_faces>
1855  const int nstate_input,
1856  const unsigned int max_degree_input,
1857  const unsigned int grid_degree_input)
1858  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
1859 {
1860  //Initialize to the max degrees
1861  current_degree = max_degree_input;
1862 }
1863 
1864 template <int dim, int n_faces>
1866  const dealii::FullMatrix<double> &norm_matrix_inverse,
1867  const dealii::FullMatrix<double> &integral_vol_basis,
1868  dealii::FullMatrix<double> &volume_projection)
1869 {
1870  norm_matrix_inverse.mTmult(volume_projection, integral_vol_basis);
1871 }
1872 template <int dim, int n_faces>
1874  const dealii::FESystem<1,1> &finite_element,
1875  const dealii::Quadrature<1> &quadrature)
1876 {
1877  const unsigned int n_dofs = finite_element.dofs_per_cell;
1878  const unsigned int n_quad_pts = quadrature.size();
1879  vol_integral_basis<dim,n_faces> integral_vol_basis(this->nstate, this->max_degree, this->max_grid_degree);
1880  integral_vol_basis.build_1D_volume_operator(finite_element, quadrature);
1881  local_mass<dim,n_faces> local_Mass_Matrix(this->nstate, this->max_degree, this->max_grid_degree);
1882  local_Mass_Matrix.build_1D_volume_operator(finite_element, quadrature);
1883  dealii::FullMatrix<double> mass_inv(n_dofs);
1884  mass_inv.invert(local_Mass_Matrix.oneD_vol_operator);
1885  //allocate the volume operator
1886  this->oneD_vol_operator.reinit(n_dofs, n_quad_pts);
1887  //solves
1888  compute_local_vol_projection_operator(mass_inv, integral_vol_basis.oneD_vol_operator, this->oneD_vol_operator);
1889 }
1890 
1891 template <int dim, int n_faces>
1893  const int nstate_input,
1894  const unsigned int max_degree_input,
1895  const unsigned int grid_degree_input,
1897  const double FR_user_specified_correction_parameter_value_input,
1898  const bool store_transpose_input)
1899  : vol_projection_operator<dim,n_faces>::vol_projection_operator(nstate_input, max_degree_input, grid_degree_input)
1900  , store_transpose(store_transpose_input)
1901  , FR_param_type(FR_param_input)
1902  , FR_user_specified_correction_parameter_value(FR_user_specified_correction_parameter_value_input)
1903 {
1904  //Initialize to the max degrees
1905  current_degree = max_degree_input;
1906 }
1907 
1908 template <int dim, int n_faces>
1910  const dealii::FESystem<1,1> &finite_element,
1911  const dealii::Quadrature<1> &quadrature)
1912 {
1913  const unsigned int n_dofs = finite_element.dofs_per_cell;
1914  const unsigned int n_quad_pts = quadrature.size();
1915  vol_integral_basis<dim,n_faces> integral_vol_basis(this->nstate, this->max_degree, this->max_grid_degree);
1916  integral_vol_basis.build_1D_volume_operator(finite_element, quadrature);
1918  local_FR_Mass_Matrix_inv.build_1D_volume_operator(finite_element, quadrature);
1919  //allocate the volume operator
1920  this->oneD_vol_operator.reinit(n_dofs, n_quad_pts);
1921  //solves
1922  this->compute_local_vol_projection_operator(local_FR_Mass_Matrix_inv.oneD_vol_operator, integral_vol_basis.oneD_vol_operator, this->oneD_vol_operator);
1923 
1924  if(store_transpose){
1925  oneD_transpose_vol_operator.reinit(n_quad_pts, n_dofs);
1926  for(unsigned int idof=0; idof<n_dofs; idof++){
1927  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
1928  oneD_transpose_vol_operator[iquad][idof] = this->oneD_vol_operator[idof][iquad];
1929  }
1930  }
1931  }
1932 }
1933 template <int dim, int n_faces>
1935  const int nstate_input,
1936  const unsigned int max_degree_input,
1937  const unsigned int grid_degree_input,
1939  const bool store_transpose_input)
1940  : vol_projection_operator<dim,n_faces>::vol_projection_operator(nstate_input, max_degree_input, grid_degree_input)
1941  , store_transpose(store_transpose_input)
1942  , FR_param_type(FR_param_input)
1943 {
1944  //Initialize to the max degrees
1945  current_degree = max_degree_input;
1946 }
1947 
1948 template <int dim, int n_faces>
1950  const dealii::FESystem<1,1> &finite_element,
1951  const dealii::Quadrature<1> &quadrature)
1952 {
1953  const unsigned int n_dofs = finite_element.dofs_per_cell;
1954  const unsigned int n_quad_pts = quadrature.size();
1955  vol_integral_basis<dim,n_faces> integral_vol_basis(this->nstate, this->max_degree, this->max_grid_degree);
1956  integral_vol_basis.build_1D_volume_operator(finite_element, quadrature);
1957  FR_mass_inv_aux<dim,n_faces> local_FR_Mass_Matrix_inv(this->nstate, this->max_degree, this->max_grid_degree, FR_param_type);
1958  local_FR_Mass_Matrix_inv.build_1D_volume_operator(finite_element, quadrature);
1959  //allocate the volume operator
1960  this->oneD_vol_operator.reinit(n_dofs, n_quad_pts);
1961  //solves
1962  this->compute_local_vol_projection_operator(local_FR_Mass_Matrix_inv.oneD_vol_operator, integral_vol_basis.oneD_vol_operator, this->oneD_vol_operator);
1963 
1964  if(store_transpose){
1965  oneD_transpose_vol_operator.reinit(n_quad_pts, n_dofs);
1966  for(unsigned int idof=0; idof<n_dofs; idof++){
1967  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
1968  oneD_transpose_vol_operator[iquad][idof] = this->oneD_vol_operator[idof][iquad];
1969  }
1970  }
1971  }
1972 }
1973 
1974 template <int dim, int n_faces>
1976  const int nstate_input,
1977  const unsigned int max_degree_input,
1978  const unsigned int grid_degree_input,
1980  const double FR_user_specified_correction_parameter_value_input)
1981  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
1982  , FR_param_type(FR_param_input)
1983  , FR_user_specified_correction_parameter_value(FR_user_specified_correction_parameter_value_input)
1984 {
1985  //Initialize to the max degrees
1986  current_degree = max_degree_input;
1987 }
1988 
1989 template <int dim, int n_faces>
1991  const dealii::FESystem<1,1> &finite_element,
1992  const dealii::Quadrature<1> &quadrature)
1993 {
1994  const unsigned int n_dofs = finite_element.dofs_per_cell;
1995  local_mass<dim,n_faces> local_Mass_Matrix(this->nstate, this->max_degree, this->max_grid_degree);
1996  local_Mass_Matrix.build_1D_volume_operator(finite_element, quadrature);
1998  local_FR_oper.build_1D_volume_operator(finite_element, quadrature);
1999  dealii::FullMatrix<double> FR_mass_matrix(n_dofs);
2000  FR_mass_matrix.add(1.0, local_Mass_Matrix.oneD_vol_operator, 1.0, local_FR_oper.oneD_vol_operator);
2001  //allocate the volume operator
2002  this->oneD_vol_operator.reinit(n_dofs, n_dofs);
2003  //solves
2004  this->oneD_vol_operator.invert(FR_mass_matrix);
2005 }
2006 
2007 template <int dim, int n_faces>
2009  const int nstate_input,
2010  const unsigned int max_degree_input,
2011  const unsigned int grid_degree_input,
2013  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
2014  , FR_param_type(FR_param_input)
2015 {
2016  //Initialize to the max degrees
2017  current_degree = max_degree_input;
2018 }
2019 
2020 template <int dim, int n_faces>
2022  const dealii::FESystem<1,1> &finite_element,
2023  const dealii::Quadrature<1> &quadrature)
2024 {
2025  const unsigned int n_dofs = finite_element.dofs_per_cell;
2026  local_mass<dim,n_faces> local_Mass_Matrix(this->nstate, this->max_degree, this->max_grid_degree);
2027  local_Mass_Matrix.build_1D_volume_operator(finite_element, quadrature);
2029  local_FR_oper.build_1D_volume_operator(finite_element, quadrature);
2030  dealii::FullMatrix<double> FR_mass_matrix(n_dofs);
2031  FR_mass_matrix.add(1.0, local_Mass_Matrix.oneD_vol_operator, 1.0, local_FR_oper.oneD_vol_operator);
2032  //allocate the volume operator
2033  this->oneD_vol_operator.reinit(n_dofs, n_dofs);
2034  //solves
2035  this->oneD_vol_operator.invert(FR_mass_matrix);
2036 }
2037 template <int dim, int n_faces>
2039  const int nstate_input,
2040  const unsigned int max_degree_input,
2041  const unsigned int grid_degree_input,
2043  const double FR_user_specified_correction_parameter_value_input)
2044  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
2045  , FR_param_type(FR_param_input)
2046  , FR_user_specified_correction_parameter_value(FR_user_specified_correction_parameter_value_input)
2047 {
2048  //Initialize to the max degrees
2049  current_degree = max_degree_input;
2050 }
2051 
2052 template <int dim, int n_faces>
2054  const dealii::FESystem<1,1> &finite_element,
2055  const dealii::Quadrature<1> &quadrature)
2056 {
2057  const unsigned int n_dofs = finite_element.dofs_per_cell;
2058  local_mass<dim,n_faces> local_Mass_Matrix(this->nstate, this->max_degree, this->max_grid_degree);
2059  local_Mass_Matrix.build_1D_volume_operator(finite_element, quadrature);
2061  local_FR_oper.build_1D_volume_operator(finite_element, quadrature);
2062  dealii::FullMatrix<double> FR_mass_matrix(n_dofs);
2063  FR_mass_matrix.add(1.0, local_Mass_Matrix.oneD_vol_operator, 1.0, local_FR_oper.oneD_vol_operator);
2064  //allocate the volume operator
2065  this->oneD_vol_operator.reinit(n_dofs, n_dofs);
2066  //solves
2067  this->oneD_vol_operator.add(1.0, FR_mass_matrix);
2068 }
2069 template <int dim, int n_faces>
2071  const int nstate_input,
2072  const unsigned int max_degree_input,
2073  const unsigned int grid_degree_input,
2075  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
2076  , FR_param_type(FR_param_input)
2077 {
2078  //Initialize to the max degrees
2079  current_degree = max_degree_input;
2080 }
2081 
2082 template <int dim, int n_faces>
2084  const dealii::FESystem<1,1> &finite_element,
2085  const dealii::Quadrature<1> &quadrature)
2086 {
2087  const unsigned int n_dofs = finite_element.dofs_per_cell;
2088  local_mass<dim,n_faces> local_Mass_Matrix(this->nstate, this->max_degree, this->max_grid_degree);
2089  local_Mass_Matrix.build_1D_volume_operator(finite_element, quadrature);
2091  local_FR_oper.build_1D_volume_operator(finite_element, quadrature);
2092  dealii::FullMatrix<double> FR_mass_matrix(n_dofs);
2093  FR_mass_matrix.add(1.0, local_Mass_Matrix.oneD_vol_operator, 1.0, local_FR_oper.oneD_vol_operator);
2094  //allocate the volume operator
2095  this->oneD_vol_operator.reinit(n_dofs, n_dofs);
2096  //solves
2097  this->oneD_vol_operator.add(1.0, FR_mass_matrix);
2098 }
2099 
2100 template <int dim, int n_faces>
2102  const int nstate_input,
2103  const unsigned int max_degree_input,
2104  const unsigned int grid_degree_input)
2105  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
2106 {
2107  //Initialize to the max degrees
2108  current_degree = max_degree_input;
2109 }
2110 
2111 template <int dim, int n_faces>
2113  const dealii::FESystem<1,1> &finite_element,
2114  const dealii::Quadrature<1> &quadrature)
2115 {
2116  const unsigned int n_quad_pts = quadrature.size();
2117  const unsigned int n_dofs = finite_element.dofs_per_cell;
2118  //allocate
2119  this->oneD_grad_operator.reinit(n_quad_pts, n_dofs);
2120  //loop and store
2121  const std::vector<double> &quad_weights = quadrature.get_weights ();
2122  for(unsigned int itest=0; itest<n_dofs; itest++){
2123  const int istate_test = finite_element.system_to_component_index(itest).first;
2124  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
2125  const dealii::Point<1> qpoint = quadrature.point(iquad);
2126  this->oneD_grad_operator[iquad][itest] = finite_element.shape_grad_component(itest, qpoint, istate_test)[0]
2127  * quad_weights[iquad];
2128  }
2129  }
2130 }
2131 
2132 /*************************************
2133 *
2134 * SURFACE OPERATORS
2135 *
2136 *************************************/
2137 
2138 template <int dim, int n_faces>
2140  const int nstate_input,
2141  const unsigned int max_degree_input,
2142  const unsigned int grid_degree_input)
2143  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
2144 {
2145  //Initialize to the max degrees
2146  current_degree = max_degree_input;
2147 }
2148 
2149 template <int dim, int n_faces>
2151  const dealii::FESystem<1,1> &finite_element,
2152  const dealii::Quadrature<0> &face_quadrature)
2153 {
2154  const unsigned int n_face_quad_pts = face_quadrature.size();
2155  const unsigned int n_dofs = finite_element.dofs_per_cell;
2156  const unsigned int n_faces_1D = n_faces / dim;
2157  const std::vector<double> &quad_weights = face_quadrature.get_weights ();
2158  //loop and store
2159  for(unsigned int iface=0; iface<n_faces_1D; iface++){
2160  //allocate the facet operator
2161  this->oneD_surf_operator[iface].reinit(n_face_quad_pts, n_dofs);
2162  //sum factorized operators use a 1D element.
2163  const dealii::Quadrature<1> quadrature = dealii::QProjector<1>::project_to_face(dealii::ReferenceCell::get_hypercube(1),
2164  face_quadrature,
2165  iface);
2166  for(unsigned int iquad=0; iquad<n_face_quad_pts; iquad++){
2167  const dealii::Point<1> qpoint = quadrature.point(iquad);
2168  for(unsigned int idof=0; idof<n_dofs; idof++){
2169  const int istate = finite_element.system_to_component_index(idof).first;
2170  //Basis function idof of poly degree idegree evaluated at cubature node qpoint.
2171  this->oneD_surf_operator[iface][iquad][idof] = finite_element.shape_value_component(idof,qpoint,istate)
2172  * quad_weights[iquad];
2173  }
2174  }
2175  }
2176 }
2177 
2178 template <int dim, int n_faces>
2180  const int nstate_input,
2181  const unsigned int max_degree_input,
2182  const unsigned int grid_degree_input)
2183  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
2184 {
2185  //Initialize to the max degrees
2186  current_degree = max_degree_input;
2187 }
2188 
2189 template <int dim, int n_faces>
2191  const dealii::FESystem<1,1> &finite_element,
2192  const dealii::Quadrature<1> &quadrature)
2193 {
2194  const unsigned int n_dofs = finite_element.dofs_per_cell;
2195  local_mass<dim,n_faces> local_Mass_Matrix(this->nstate, this->max_degree, this->max_grid_degree);
2196  local_Mass_Matrix.build_1D_volume_operator(finite_element, quadrature);
2197  //allocate the volume operator
2198  this->oneD_vol_operator.reinit(n_dofs, n_dofs);
2199  //solves
2200  this->oneD_vol_operator.add(1.0, local_Mass_Matrix.oneD_vol_operator);
2201 }
2202 template <int dim, int n_faces>
2204  const unsigned int n_dofs,
2205  const dealii::FullMatrix<double> &norm_matrix,
2206  const dealii::FullMatrix<double> &face_integral,
2207  dealii::FullMatrix<double> &lifting)
2208 {
2209  dealii::FullMatrix<double> norm_inv(n_dofs);
2210  norm_inv.invert(norm_matrix);
2211  norm_inv.mTmult(lifting, face_integral);
2212 }
2213 template <int dim, int n_faces>
2215  const dealii::FESystem<1,1> &finite_element,
2216  const dealii::Quadrature<0> &face_quadrature)
2217 {
2218  const unsigned int n_face_quad_pts = face_quadrature.size();
2219  const unsigned int n_dofs = finite_element.dofs_per_cell;
2220  const unsigned int n_faces_1D = n_faces / dim;
2221  //create surface integral of basis functions
2222  face_integral_basis<dim,n_faces> basis_int_facet(this->nstate, this->max_degree, this->max_grid_degree);
2223  basis_int_facet.build_1D_surface_operator(finite_element, face_quadrature);
2224  //loop and store
2225  for(unsigned int iface=0; iface<n_faces_1D; iface++){
2226  //allocate the facet operator
2227  this->oneD_surf_operator[iface].reinit(n_dofs, n_face_quad_pts);
2228  build_local_surface_lifting_operator(n_dofs, this->oneD_vol_operator, basis_int_facet.oneD_surf_operator[iface], this->oneD_surf_operator[iface]);
2229  }
2230 }
2231 
2232 template <int dim, int n_faces>
2234  const int nstate_input,
2235  const unsigned int max_degree_input,
2236  const unsigned int grid_degree_input,
2238  const double FR_user_specified_correction_parameter_value_input)
2239  : lifting_operator<dim,n_faces>::lifting_operator(nstate_input, max_degree_input, grid_degree_input)
2240  , FR_param_type(FR_param_input)
2241  , FR_user_specified_correction_parameter_value(FR_user_specified_correction_parameter_value_input)
2242 {
2243  //Initialize to the max degrees
2244  current_degree = max_degree_input;
2245 }
2246 
2247 template <int dim, int n_faces>
2249  const dealii::FESystem<1,1> &finite_element,
2250  const dealii::Quadrature<1> &quadrature)
2251 {
2252  const unsigned int n_dofs = finite_element.dofs_per_cell;
2253  local_mass<dim,n_faces> local_Mass_Matrix(this->nstate, this->max_degree, this->max_grid_degree);
2254  local_Mass_Matrix.build_1D_volume_operator(finite_element, quadrature);
2256  local_FR.build_1D_volume_operator(finite_element, quadrature);
2257  //allocate the volume operator
2258  this->oneD_vol_operator.reinit(n_dofs, n_dofs);
2259  //solves
2260  this->oneD_vol_operator.add(1.0, local_Mass_Matrix.oneD_vol_operator);
2261  this->oneD_vol_operator.add(1.0, local_FR.oneD_vol_operator);
2262 }
2263 template <int dim, int n_faces>
2265  const dealii::FESystem<1,1> &finite_element,
2266  const dealii::Quadrature<0> &face_quadrature)
2267 {
2268  const unsigned int n_face_quad_pts = face_quadrature.size();
2269  const unsigned int n_dofs = finite_element.dofs_per_cell;
2270  const unsigned int n_faces_1D = n_faces / dim;
2271  //create surface integral of basis functions
2272  face_integral_basis<dim,n_faces> basis_int_facet(this->nstate, this->max_degree, this->max_grid_degree);
2273  basis_int_facet.build_1D_surface_operator(finite_element, face_quadrature);
2274  //loop and store
2275  for(unsigned int iface=0; iface<n_faces_1D; iface++){
2276  //allocate the facet operator
2277  this->oneD_surf_operator[iface].reinit(n_dofs, n_face_quad_pts);
2278  this->build_local_surface_lifting_operator(n_dofs, this->oneD_vol_operator, basis_int_facet.oneD_surf_operator[iface], this->oneD_surf_operator[iface]);
2279  }
2280 }
2281 
2282 
2283 /******************************************************************************
2284 *
2285 * METRIC MAPPING OPERATORS
2286 *
2287 ******************************************************************************/
2288 
2289 template <int dim, int n_faces>
2291  const int nstate_input,
2292  const unsigned int max_degree_input,
2293  const unsigned int grid_degree_input)
2294  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
2295  , mapping_shape_functions_grid_nodes(nstate_input, max_degree_input, grid_degree_input)
2296  , mapping_shape_functions_flux_nodes(nstate_input, max_degree_input, grid_degree_input)
2297 {
2298  //Initialize to the max degrees
2299  current_degree = max_degree_input;
2300  current_grid_degree = grid_degree_input;
2301 }
2302 
2303 template <int dim, int n_faces>
2305  const dealii::FESystem<1,1> &finite_element,
2306  const dealii::Quadrature<1> &quadrature)
2307 {
2308  assert(finite_element.dofs_per_cell == quadrature.size());//checks collocation
2309  mapping_shape_functions_grid_nodes.build_1D_volume_operator(finite_element, quadrature);
2310  mapping_shape_functions_grid_nodes.build_1D_gradient_operator(finite_element, quadrature);
2311 }
2312 template <int dim, int n_faces>
2314  const dealii::FESystem<1,1> &finite_element,
2315  const dealii::Quadrature<1> &quadrature,
2316  const dealii::Quadrature<0> &face_quadrature)
2317 {
2318  mapping_shape_functions_flux_nodes.build_1D_volume_operator(finite_element, quadrature);
2319  mapping_shape_functions_flux_nodes.build_1D_gradient_operator(finite_element, quadrature);
2320  mapping_shape_functions_flux_nodes.build_1D_surface_operator(finite_element, face_quadrature);
2321  mapping_shape_functions_flux_nodes.build_1D_surface_gradient_operator(finite_element, face_quadrature);
2322 
2323 }
2324 template <int dim, int n_faces>
2326  const dealii::FESystem<1,1> &finite_element,
2327  const dealii::Quadrature<1> &quadrature)
2328 {
2329  mapping_shape_functions_flux_nodes.build_1D_volume_operator(finite_element, quadrature);
2330  mapping_shape_functions_flux_nodes.build_1D_gradient_operator(finite_element, quadrature);
2331 }
2332 
2333 /***********************************************
2334 *
2335 * METRIC DET JAC AND COFACTOR
2336 *
2337 ************************************************/
2338 //Constructor
2339 template <typename real, int dim, int n_faces>
2341  const int nstate_input,
2342  const unsigned int max_degree_input,
2343  const unsigned int grid_degree_input,
2344  const bool store_vol_flux_nodes_input,
2345  const bool store_surf_flux_nodes_input,
2346  const bool store_Jacobian_input)
2347  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate_input, max_degree_input, grid_degree_input)
2348  , store_Jacobian(store_Jacobian_input)
2349  , store_vol_flux_nodes(store_vol_flux_nodes_input)
2350  , store_surf_flux_nodes(store_surf_flux_nodes_input)
2351 {}
2352 
2353 template <typename real, int dim, int n_faces>
2355  const dealii::Tensor<1,dim,real> &phys,
2356  const dealii::Tensor<2,dim,real> &metric_cofactor,
2357  dealii::Tensor<1,dim,real> &ref)
2358 {
2359  for(int idim=0; idim<dim; idim++){
2360  for(int idim2=0; idim2<dim; idim2++){
2361  ref[idim] += metric_cofactor[idim2][idim] * phys[idim2];
2362  }
2363  }
2364 
2365 }
2366 
2367 template <typename real, int dim, int n_faces>
2369  const dealii::Tensor<1,dim,real> &ref,
2370  const dealii::Tensor<2,dim,real> &metric_cofactor,
2371  dealii::Tensor<1,dim,real> &phys)
2372 {
2373  for(int idim=0; idim<dim; idim++){
2374  phys[idim] = 0.0;
2375  for(int idim2=0; idim2<dim; idim2++){
2376  phys[idim] += metric_cofactor[idim][idim2]
2377  * ref[idim2];
2378  }
2379  }
2380 }
2381 
2382 template <typename real, int dim, int n_faces>
2384  const dealii::Tensor<1,dim,std::vector<real>> &phys,
2385  const dealii::Tensor<2,dim,std::vector<real>> &metric_cofactor,
2386  dealii::Tensor<1,dim,std::vector<real>> &ref)
2387 {
2388  assert(phys[0].size() == metric_cofactor[0][0].size());
2389  const unsigned int n_pts = phys[0].size();
2390  for(int idim=0; idim<dim; idim++){
2391  ref[idim].resize(n_pts);
2392  for(int idim2=0; idim2<dim; idim2++){
2393  for(unsigned int ipt=0; ipt<n_pts; ipt++){
2394  ref[idim][ipt] += metric_cofactor[idim2][idim][ipt] * phys[idim2][ipt];
2395  }
2396  }
2397  }
2398 
2399 }
2400 
2401 template <typename real, int dim, int n_faces>
2403  const unsigned int n_quad_pts,
2404  const dealii::Tensor<1,dim,real> &ref,
2405  const dealii::Tensor<2,dim,std::vector<real>> &metric_cofactor,
2406  std::vector<dealii::Tensor<1,dim,real>> &phys)
2407 {
2408  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
2409  real norm =0.0;
2410  for(int idim=0; idim<dim; idim++){
2411  phys[iquad][idim] = 0.0;
2412  for(int idim2=0; idim2<dim; idim2++){
2413  phys[iquad][idim] += metric_cofactor[idim][idim2][iquad]
2414  * ref[idim2];
2415  }
2416  norm += phys[iquad][idim] * phys[iquad][idim];
2417  }
2418  phys[iquad] /= sqrt(norm);
2419  }
2420 }
2421 
2422 template <typename real, int dim, int n_faces>
2424  const unsigned int n_quad_pts,
2425  const unsigned int /*n_metric_dofs*/,//dofs of metric basis. NOTE: this is the number of mapping support points
2426  const std::array<std::vector<real>,dim> &mapping_support_points,
2427  mapping_shape_functions<dim,n_faces> &mapping_basis)
2428 {
2429  det_Jac_vol.resize(n_quad_pts);
2430  //compute determinant of metric Jacobian
2432  n_quad_pts,
2433  mapping_support_points,
2434  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2435  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2436  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2437  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator,
2438  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator,
2439  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator,
2440  det_Jac_vol);
2441 }
2442 
2443 template <typename real, int dim, int n_faces>
2445  const unsigned int n_quad_pts,
2446  const unsigned int n_metric_dofs,//dofs of metric basis. NOTE: this is the number of mapping support points
2447  const std::array<std::vector<real>,dim> &mapping_support_points,
2448  mapping_shape_functions<dim,n_faces> &mapping_basis,
2449  const bool use_invariant_curl_form)
2450 {
2451  det_Jac_vol.resize(n_quad_pts);
2452  for(int idim=0; idim<dim; idim++){
2453  for(int jdim=0; jdim<dim; jdim++){
2454  metric_cofactor_vol[idim][jdim].resize(n_quad_pts);
2455  }
2456  }
2457  //compute determinant of metric Jacobian
2459  n_quad_pts,
2460  mapping_support_points,
2461  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2462  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2463  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2464  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator,
2465  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator,
2466  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator,
2467  det_Jac_vol);
2468  //compute the metric cofactor
2470  n_quad_pts,
2471  n_metric_dofs,
2472  mapping_support_points,
2473  mapping_basis.mapping_shape_functions_grid_nodes.oneD_vol_operator,
2474  mapping_basis.mapping_shape_functions_grid_nodes.oneD_vol_operator,
2475  mapping_basis.mapping_shape_functions_grid_nodes.oneD_vol_operator,
2476  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2477  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2478  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2479  mapping_basis.mapping_shape_functions_grid_nodes.oneD_grad_operator,
2480  mapping_basis.mapping_shape_functions_grid_nodes.oneD_grad_operator,
2481  mapping_basis.mapping_shape_functions_grid_nodes.oneD_grad_operator,
2482  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator,
2483  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator,
2484  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator,
2486  use_invariant_curl_form);
2487 
2489  for(int idim=0; idim<dim; idim++){
2490  flux_nodes_vol[idim].resize(n_quad_pts);
2491  this->matrix_vector_mult(mapping_support_points[idim],
2492  flux_nodes_vol[idim],
2493  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2494  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator,
2495  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator);
2496  }
2497  }
2498 }
2499 
2500 template <typename real, int dim, int n_faces>
2502  const unsigned int iface,
2503  const unsigned int n_quad_pts,
2504  const unsigned int n_metric_dofs,//dofs of metric basis. NOTE: this is the number of mapping support points
2505  const std::array<std::vector<real>,dim> &mapping_support_points,
2506  mapping_shape_functions<dim,n_faces> &mapping_basis,
2507  const bool use_invariant_curl_form)
2508 {
2509  det_Jac_surf.resize(n_quad_pts);
2510  for(int idim=0; idim<dim; idim++){
2511  for(int jdim=0; jdim<dim; jdim++){
2512  metric_cofactor_surf[idim][jdim].resize(n_quad_pts);
2513  }
2514  }
2515  //compute determinant of metric Jacobian
2517  n_quad_pts,
2518  mapping_support_points,
2519  (iface == 0) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[0] :
2520  ((iface == 1) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[1] :
2521  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator),
2522  (iface == 2) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[0] :
2523  ((iface == 3) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[1] :
2524  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator),
2525  (iface == 4) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[0] :
2526  ((iface == 5) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[1] :
2527  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator),
2528  (iface == 0) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[0] :
2529  ((iface == 1) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[1] :
2530  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator),
2531  (iface == 2) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[0] :
2532  ((iface == 3) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[1] :
2533  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator),
2534  (iface == 4) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[0] :
2535  ((iface == 5) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[1] :
2536  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator),
2537  det_Jac_surf);
2538  //compute the metric cofactor
2540  n_quad_pts,
2541  n_metric_dofs,
2542  mapping_support_points,
2543  mapping_basis.mapping_shape_functions_grid_nodes.oneD_vol_operator,
2544  mapping_basis.mapping_shape_functions_grid_nodes.oneD_vol_operator,
2545  mapping_basis.mapping_shape_functions_grid_nodes.oneD_vol_operator,
2546  (iface == 0) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[0] :
2547  ((iface == 1) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[1] :
2548  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator),
2549  (iface == 2) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[0] :
2550  ((iface == 3) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[1] :
2551  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator),
2552  (iface == 4) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[0] :
2553  ((iface == 5) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[1] :
2554  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator),
2555  mapping_basis.mapping_shape_functions_grid_nodes.oneD_grad_operator,
2556  mapping_basis.mapping_shape_functions_grid_nodes.oneD_grad_operator,
2557  mapping_basis.mapping_shape_functions_grid_nodes.oneD_grad_operator,
2558  (iface == 0) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[0] :
2559  ((iface == 1) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[1] :
2560  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator),
2561  (iface == 2) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[0] :
2562  ((iface == 3) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[1] :
2563  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator),
2564  (iface == 4) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[0] :
2565  ((iface == 5) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_grad_operator[1] :
2566  mapping_basis.mapping_shape_functions_flux_nodes.oneD_grad_operator),
2568  use_invariant_curl_form);
2569 
2571  for(int iface=0; iface<n_faces; iface++){
2572  for(int idim=0; idim<dim; idim++){
2573  flux_nodes_surf[iface][idim].resize(n_quad_pts);
2574  this->matrix_vector_mult(mapping_support_points[idim],
2575  flux_nodes_surf[iface][idim],
2576  (iface == 0) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[0] :
2577  ((iface == 1) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[1] :
2578  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator),
2579  (iface == 2) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[0] :
2580  ((iface == 3) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[1] :
2581  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator),
2582  (iface == 4) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[0] :
2583  ((iface == 5) ? mapping_basis.mapping_shape_functions_flux_nodes.oneD_surf_operator[1] :
2584  mapping_basis.mapping_shape_functions_flux_nodes.oneD_vol_operator));
2585  }
2586  }
2587  }
2588 }
2589 
2590 template <typename real, int dim, int n_faces>
2592  const unsigned int n_quad_pts,
2593  const std::array<std::vector<real>,dim> &mapping_support_points,
2594  const dealii::FullMatrix<double> &basis_x_flux_nodes,
2595  const dealii::FullMatrix<double> &basis_y_flux_nodes,
2596  const dealii::FullMatrix<double> &basis_z_flux_nodes,
2597  const dealii::FullMatrix<double> &grad_basis_x_flux_nodes,
2598  const dealii::FullMatrix<double> &grad_basis_y_flux_nodes,
2599  const dealii::FullMatrix<double> &grad_basis_z_flux_nodes,
2600  std::vector<dealii::Tensor<2,dim,real>> &local_Jac)
2601 {
2602  for(int idim=0; idim<dim; idim++){
2603  for(int jdim=0; jdim<dim; jdim++){
2604  // std::vector<real> output_vect(pow(n_quad_pts_1D,dim));
2605  std::vector<real> output_vect(n_quad_pts);
2606  if(jdim == 0)
2607  this->matrix_vector_mult(mapping_support_points[idim], output_vect,
2608  grad_basis_x_flux_nodes,
2609  basis_y_flux_nodes,
2610  basis_z_flux_nodes);
2611  if(jdim == 1)
2612  this->matrix_vector_mult(mapping_support_points[idim], output_vect,
2613  basis_x_flux_nodes,
2614  grad_basis_y_flux_nodes,
2615  basis_z_flux_nodes);
2616  if(jdim == 2)
2617  this->matrix_vector_mult(mapping_support_points[idim], output_vect,
2618  basis_x_flux_nodes,
2619  basis_y_flux_nodes,
2620  grad_basis_z_flux_nodes);
2621  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
2622  local_Jac[iquad][idim][jdim] = output_vect[iquad];
2623  }
2624  }
2625  }
2626 }
2627 
2628 template <typename real, int dim, int n_faces>
2630  const unsigned int n_quad_pts,//number volume quad pts
2631  const std::array<std::vector<real>,dim> &mapping_support_points,
2632  const dealii::FullMatrix<double> &basis_x_flux_nodes,
2633  const dealii::FullMatrix<double> &basis_y_flux_nodes,
2634  const dealii::FullMatrix<double> &basis_z_flux_nodes,
2635  const dealii::FullMatrix<double> &grad_basis_x_flux_nodes,
2636  const dealii::FullMatrix<double> &grad_basis_y_flux_nodes,
2637  const dealii::FullMatrix<double> &grad_basis_z_flux_nodes,
2638  std::vector<real> &det_metric_Jac)
2639 {
2640  //mapping support points must be passed as a vector[dim][n_metric_dofs]
2641  assert(pow(this->max_grid_degree+1,dim) == mapping_support_points[0].size());
2642 
2643  std::vector<dealii::Tensor<2,dim,real>> Jacobian_flux_nodes(n_quad_pts);
2644  this->build_metric_Jacobian(n_quad_pts,
2645  mapping_support_points,
2646  basis_x_flux_nodes,
2647  basis_y_flux_nodes,
2648  basis_z_flux_nodes,
2649  grad_basis_x_flux_nodes,
2650  grad_basis_y_flux_nodes,
2651  grad_basis_z_flux_nodes,
2652  Jacobian_flux_nodes);
2653  if(store_Jacobian){
2654  for(int idim=0; idim<dim; idim++){
2655  for(int jdim=0; jdim<dim; jdim++){
2656  metric_Jacobian_vol_cubature[idim][jdim].resize(n_quad_pts);
2657  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
2658  metric_Jacobian_vol_cubature[idim][jdim][iquad] = Jacobian_flux_nodes[iquad][idim][jdim];
2659  }
2660  }
2661  }
2662  }
2663 
2664  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
2665  det_metric_Jac[iquad] = dealii::determinant(Jacobian_flux_nodes[iquad]);
2666  //check for valid cell
2667  if(det_metric_Jac[iquad] <= 1e-14){
2668  std::cout<<"The determinant of the Jacobian is negative. Aborting..."<<std::endl;
2669  std::abort();
2670  }
2671  }
2672 }
2673 template <typename real, int dim, int n_faces>
2675  const unsigned int n_quad_pts,//number flux pts
2676  const unsigned int n_metric_dofs,//dofs of metric basis. NOTE: this is the number of mapping support points
2677  const std::array<std::vector<real>,dim> &mapping_support_points,
2678  const dealii::FullMatrix<double> &basis_x_grid_nodes,
2679  const dealii::FullMatrix<double> &basis_y_grid_nodes,
2680  const dealii::FullMatrix<double> &basis_z_grid_nodes,
2681  const dealii::FullMatrix<double> &basis_x_flux_nodes,
2682  const dealii::FullMatrix<double> &basis_y_flux_nodes,
2683  const dealii::FullMatrix<double> &basis_z_flux_nodes,
2684  const dealii::FullMatrix<double> &grad_basis_x_grid_nodes,
2685  const dealii::FullMatrix<double> &grad_basis_y_grid_nodes,
2686  const dealii::FullMatrix<double> &grad_basis_z_grid_nodes,
2687  const dealii::FullMatrix<double> &grad_basis_x_flux_nodes,
2688  const dealii::FullMatrix<double> &grad_basis_y_flux_nodes,
2689  const dealii::FullMatrix<double> &grad_basis_z_flux_nodes,
2690  dealii::Tensor<2,dim,std::vector<real>> &metric_cofactor,
2691  const bool use_invariant_curl_form)
2692 {
2693  //mapping support points must be passed as a vector[dim][n_metric_dofs]
2694  //Solve for Cofactor
2695  if (dim == 1){//constant for 1D
2696  std::fill(metric_cofactor[0][0].begin(), metric_cofactor[0][0].end(), 1.0);
2697  }
2698  if (dim == 2){
2699  std::vector<dealii::Tensor<2,dim,real>> Jacobian_flux_nodes(n_quad_pts);
2700  this->build_metric_Jacobian(n_quad_pts,
2701  mapping_support_points,
2702  basis_x_flux_nodes,
2703  basis_y_flux_nodes,
2704  basis_z_flux_nodes,
2705  grad_basis_x_flux_nodes,
2706  grad_basis_y_flux_nodes,
2707  grad_basis_z_flux_nodes,
2708  Jacobian_flux_nodes);
2709  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
2710  metric_cofactor[0][0][iquad] = Jacobian_flux_nodes[iquad][1][1];
2711  metric_cofactor[1][0][iquad] = - Jacobian_flux_nodes[iquad][0][1];
2712  metric_cofactor[0][1][iquad] = - Jacobian_flux_nodes[iquad][1][0];
2713  metric_cofactor[1][1][iquad] = Jacobian_flux_nodes[iquad][0][0];
2714  }
2715  }
2716  if (dim == 3){
2717  compute_local_3D_cofactor(n_metric_dofs,
2718  n_quad_pts,
2719  mapping_support_points,
2720  basis_x_grid_nodes,
2721  basis_y_grid_nodes,
2722  basis_z_grid_nodes,
2723  basis_x_flux_nodes,
2724  basis_y_flux_nodes,
2725  basis_z_flux_nodes,
2726  grad_basis_x_grid_nodes,
2727  grad_basis_y_grid_nodes,
2728  grad_basis_z_grid_nodes,
2729  grad_basis_x_flux_nodes,
2730  grad_basis_y_flux_nodes,
2731  grad_basis_z_flux_nodes,
2732  metric_cofactor,
2733  use_invariant_curl_form);
2734  }
2735 }
2736 
2737 template <typename real, int dim, int n_faces>
2739  const unsigned int n_metric_dofs,
2740  const unsigned int /*n_quad_pts*/,
2741  const std::array<std::vector<real>,dim> &mapping_support_points,
2742  const dealii::FullMatrix<double> &basis_x_grid_nodes,
2743  const dealii::FullMatrix<double> &basis_y_grid_nodes,
2744  const dealii::FullMatrix<double> &basis_z_grid_nodes,
2745  const dealii::FullMatrix<double> &basis_x_flux_nodes,
2746  const dealii::FullMatrix<double> &basis_y_flux_nodes,
2747  const dealii::FullMatrix<double> &basis_z_flux_nodes,
2748  const dealii::FullMatrix<double> &grad_basis_x_grid_nodes,
2749  const dealii::FullMatrix<double> &grad_basis_y_grid_nodes,
2750  const dealii::FullMatrix<double> &grad_basis_z_grid_nodes,
2751  const dealii::FullMatrix<double> &grad_basis_x_flux_nodes,
2752  const dealii::FullMatrix<double> &grad_basis_y_flux_nodes,
2753  const dealii::FullMatrix<double> &grad_basis_z_flux_nodes,
2754  dealii::Tensor<2,dim,std::vector<real>> &metric_cofactor,
2755  const bool use_invariant_curl_form)
2756 {
2757  //Conservative Curl Form
2758 
2759  //compute grad Xm, NOTE: it is the same as the Jacobian at Grid Nodes
2760  std::vector<dealii::Tensor<2,dim,real>> grad_Xm(n_metric_dofs);//gradient of mapping support points at Grid Nodes
2761  this->build_metric_Jacobian(n_metric_dofs,
2762  mapping_support_points,
2763  basis_x_grid_nodes,
2764  basis_y_grid_nodes,
2765  basis_z_grid_nodes,
2766  grad_basis_x_grid_nodes,
2767  grad_basis_y_grid_nodes,
2768  grad_basis_z_grid_nodes,
2769  grad_Xm);
2770 
2771  //Store Xl * grad Xm using fact the mapping shape functions collocated on Grid Nodes.
2772  //Also, we only store the ones needed, not all to reduce computational cost.
2773  std::vector<real> z_dy_dxi(n_metric_dofs);
2774  std::vector<real> z_dy_deta(n_metric_dofs);
2775  std::vector<real> z_dy_dzeta(n_metric_dofs);
2776 
2777  std::vector<real> x_dz_dxi(n_metric_dofs);
2778  std::vector<real> x_dz_deta(n_metric_dofs);
2779  std::vector<real> x_dz_dzeta(n_metric_dofs);
2780 
2781  std::vector<real> y_dx_dxi(n_metric_dofs);
2782  std::vector<real> y_dx_deta(n_metric_dofs);
2783  std::vector<real> y_dx_dzeta(n_metric_dofs);
2784 
2785  for(unsigned int grid_node=0; grid_node<n_metric_dofs; grid_node++){
2786  z_dy_dxi[grid_node] = mapping_support_points[2][grid_node] * grad_Xm[grid_node][1][0];
2787  if(use_invariant_curl_form){
2788  z_dy_dxi[grid_node] = 0.5 * z_dy_dxi[grid_node]
2789  - 0.5 * mapping_support_points[1][grid_node] * grad_Xm[grid_node][2][0];
2790  }
2791  z_dy_deta[grid_node] = mapping_support_points[2][grid_node] * grad_Xm[grid_node][1][1];
2792  if(use_invariant_curl_form){
2793  z_dy_deta[grid_node] = 0.5 * z_dy_deta[grid_node]
2794  - 0.5 * mapping_support_points[1][grid_node] * grad_Xm[grid_node][2][1];
2795  }
2796  z_dy_dzeta[grid_node] = mapping_support_points[2][grid_node] * grad_Xm[grid_node][1][2];
2797  if(use_invariant_curl_form){
2798  z_dy_dzeta[grid_node] = 0.5 * z_dy_dzeta[grid_node]
2799  - 0.5 * mapping_support_points[1][grid_node] * grad_Xm[grid_node][2][2];
2800  }
2801 
2802  x_dz_dxi[grid_node] = mapping_support_points[0][grid_node] * grad_Xm[grid_node][2][0];
2803  if(use_invariant_curl_form){
2804  x_dz_dxi[grid_node] = 0.5 * x_dz_dxi[grid_node]
2805  - 0.5 * mapping_support_points[2][grid_node] * grad_Xm[grid_node][0][0];
2806  }
2807  x_dz_deta[grid_node] = mapping_support_points[0][grid_node] * grad_Xm[grid_node][2][1];
2808  if(use_invariant_curl_form){
2809  x_dz_deta[grid_node] = 0.5 * x_dz_deta[grid_node]
2810  - 0.5 * mapping_support_points[2][grid_node] * grad_Xm[grid_node][0][1];
2811  }
2812  x_dz_dzeta[grid_node] = mapping_support_points[0][grid_node] * grad_Xm[grid_node][2][2];
2813  if(use_invariant_curl_form){
2814  x_dz_dzeta[grid_node] = 0.5 * x_dz_dzeta[grid_node]
2815  - 0.5 * mapping_support_points[2][grid_node] * grad_Xm[grid_node][0][2];
2816  }
2817 
2818  y_dx_dxi[grid_node] = mapping_support_points[1][grid_node] * grad_Xm[grid_node][0][0];
2819  if(use_invariant_curl_form){
2820  y_dx_dxi[grid_node] = 0.5 * y_dx_dxi[grid_node]
2821  - 0.5 * mapping_support_points[0][grid_node] * grad_Xm[grid_node][1][0];
2822  }
2823  y_dx_deta[grid_node] = mapping_support_points[1][grid_node] * grad_Xm[grid_node][0][1];
2824  if(use_invariant_curl_form){
2825  y_dx_deta[grid_node] = 0.5 * y_dx_deta[grid_node]
2826  - 0.5 * mapping_support_points[0][grid_node] * grad_Xm[grid_node][1][1];
2827  }
2828  y_dx_dzeta[grid_node] = mapping_support_points[1][grid_node] * grad_Xm[grid_node][0][2];
2829  if(use_invariant_curl_form){
2830  y_dx_dzeta[grid_node] = 0.5 * y_dx_dzeta[grid_node]
2831  - 0.5 * mapping_support_points[0][grid_node] * grad_Xm[grid_node][1][2];
2832  }
2833  }
2834 
2835  //Compute metric Cofactor via conservative curl form at flux nodes.
2836  //C11
2837  this->matrix_vector_mult(z_dy_dzeta, metric_cofactor[0][0],
2838  basis_x_flux_nodes, grad_basis_y_flux_nodes, basis_z_flux_nodes, false, -1.0);
2839  this->matrix_vector_mult(z_dy_deta, metric_cofactor[0][0],
2840  basis_x_flux_nodes, basis_y_flux_nodes, grad_basis_z_flux_nodes, true);
2841  //C12
2842  this->matrix_vector_mult(z_dy_dzeta, metric_cofactor[0][1],
2843  grad_basis_x_flux_nodes, basis_y_flux_nodes, basis_z_flux_nodes);
2844  this->matrix_vector_mult(z_dy_dxi, metric_cofactor[0][1],
2845  basis_x_flux_nodes, basis_y_flux_nodes, grad_basis_z_flux_nodes, true, -1.0);
2846  //C13
2847  this->matrix_vector_mult(z_dy_deta, metric_cofactor[0][2],
2848  grad_basis_x_flux_nodes, basis_y_flux_nodes, basis_z_flux_nodes, false, -1.0);
2849  this->matrix_vector_mult(z_dy_dxi, metric_cofactor[0][2],
2850  basis_x_flux_nodes, grad_basis_y_flux_nodes, basis_z_flux_nodes, true);
2851 
2852  //C21
2853  this->matrix_vector_mult(x_dz_dzeta, metric_cofactor[1][0],
2854  basis_x_flux_nodes, grad_basis_y_flux_nodes, basis_z_flux_nodes, false, -1.0);
2855  this->matrix_vector_mult(x_dz_deta, metric_cofactor[1][0],
2856  basis_x_flux_nodes, basis_y_flux_nodes, grad_basis_z_flux_nodes, true);
2857  //C22
2858  this->matrix_vector_mult(x_dz_dzeta, metric_cofactor[1][1],
2859  grad_basis_x_flux_nodes, basis_y_flux_nodes, basis_z_flux_nodes);
2860  this->matrix_vector_mult(x_dz_dxi, metric_cofactor[1][1],
2861  basis_x_flux_nodes, basis_y_flux_nodes, grad_basis_z_flux_nodes, true, -1.0);
2862  //C23
2863  this->matrix_vector_mult(x_dz_deta, metric_cofactor[1][2],
2864  grad_basis_x_flux_nodes, basis_y_flux_nodes, basis_z_flux_nodes, false, -1.0);
2865  this->matrix_vector_mult(x_dz_dxi, metric_cofactor[1][2],
2866  basis_x_flux_nodes, grad_basis_y_flux_nodes, basis_z_flux_nodes, true);
2867 
2868  //C31
2869  this->matrix_vector_mult(y_dx_dzeta, metric_cofactor[2][0],
2870  basis_x_flux_nodes, grad_basis_y_flux_nodes, basis_z_flux_nodes, false, -1.0);
2871  this->matrix_vector_mult(y_dx_deta, metric_cofactor[2][0],
2872  basis_x_flux_nodes, basis_y_flux_nodes, grad_basis_z_flux_nodes, true);
2873  //C32
2874  this->matrix_vector_mult(y_dx_dzeta, metric_cofactor[2][1],
2875  grad_basis_x_flux_nodes, basis_y_flux_nodes, basis_z_flux_nodes);
2876  this->matrix_vector_mult(y_dx_dxi, metric_cofactor[2][1],
2877  basis_x_flux_nodes, basis_y_flux_nodes, grad_basis_z_flux_nodes, true, -1.0);
2878  //C33
2879  this->matrix_vector_mult(y_dx_deta, metric_cofactor[2][2],
2880  grad_basis_x_flux_nodes, basis_y_flux_nodes, basis_z_flux_nodes, false, -1.0);
2881  this->matrix_vector_mult(y_dx_dxi, metric_cofactor[2][2],
2882  basis_x_flux_nodes, grad_basis_y_flux_nodes, basis_z_flux_nodes, true);
2883 
2884 }
2885 
2886 /**********************************
2887 *
2888 * Sum Factorization STATE class
2889 *
2890 **********************************/
2891 //Constructor
2892 template <int dim, int nstate, int n_faces>
2894  const unsigned int max_degree_input,
2895  const unsigned int grid_degree_input)
2896  : SumFactorizedOperators<dim,n_faces>::SumFactorizedOperators(nstate, max_degree_input, grid_degree_input)
2897 {}
2898 
2899 template <int dim, int nstate, int n_faces>
2901  const unsigned int max_degree_input,
2902  const unsigned int grid_degree_input)
2903  : SumFactorizedOperatorsState<dim,nstate,n_faces>::SumFactorizedOperatorsState(max_degree_input, grid_degree_input)
2904 {
2905  //Initialize to the max degrees
2906  current_degree = max_degree_input;
2907 }
2908 
2909 template <int dim, int nstate, int n_faces>
2911  const dealii::FESystem<1,1> &finite_element,
2912  const dealii::Quadrature<1> &quadrature)
2913 {
2914  const unsigned int n_quad_pts = quadrature.size();
2915  const unsigned int n_dofs = finite_element.dofs_per_cell;
2916  const unsigned int n_shape_fns = n_dofs / nstate;
2917  //Note thate the flux basis should only have one state in the finite element.
2918  //loop and store
2919  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
2920  const dealii::Point<1> qpoint = quadrature.point(iquad);
2921  for(unsigned int idof=0; idof<n_dofs; idof++){
2922  const unsigned int istate = finite_element.system_to_component_index(idof).first;
2923  const unsigned int ishape = finite_element.system_to_component_index(idof).second;
2924  if(ishape == 0)
2925  this->oneD_vol_state_operator[istate].reinit(n_quad_pts, n_shape_fns);
2926 
2927  //Basis function idof of poly degree idegree evaluated at cubature node qpoint.
2928  this->oneD_vol_state_operator[istate][iquad][ishape] = finite_element.shape_value_component(idof,qpoint,istate);
2929  }
2930  }
2931 }
2932 
2933 template <int dim, int nstate, int n_faces>
2935  const dealii::FESystem<1,1> &finite_element,
2936  const dealii::Quadrature<1> &quadrature)
2937 {
2938  const unsigned int n_quad_pts = quadrature.size();
2939  const unsigned int n_dofs = finite_element.dofs_per_cell;
2940  const unsigned int n_shape_fns = n_dofs / nstate;
2941  //loop and store
2942  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
2943  const dealii::Point<1> qpoint = quadrature.point(iquad);
2944  for(unsigned int idof=0; idof<n_dofs; idof++){
2945  const unsigned int istate = finite_element.system_to_component_index(idof).first;
2946  const unsigned int ishape = finite_element.system_to_component_index(idof).second;
2947  if(ishape == 0)
2948  this->oneD_grad_state_operator[istate].reinit(n_quad_pts, n_shape_fns);
2949 
2950  this->oneD_grad_state_operator[istate][iquad][ishape] = finite_element.shape_grad_component(idof, qpoint, istate)[0];
2951  }
2952  }
2953 }
2954 template <int dim, int nstate, int n_faces>
2956  const dealii::FESystem<1,1> &finite_element,
2957  const dealii::Quadrature<0> &face_quadrature)
2958 {
2959  const unsigned int n_face_quad_pts = face_quadrature.size();
2960  const unsigned int n_dofs = finite_element.dofs_per_cell;
2961  const unsigned int n_faces_1D = n_faces / dim;
2962  const unsigned int n_shape_fns = n_dofs / nstate;
2963  //loop and store
2964  for(unsigned int iface=0; iface<n_faces_1D; iface++){
2965  const dealii::Quadrature<1> quadrature = dealii::QProjector<1>::project_to_face(dealii::ReferenceCell::get_hypercube(1),
2966  face_quadrature,
2967  iface);
2968  for(unsigned int iquad=0; iquad<n_face_quad_pts; iquad++){
2969  for(unsigned int idof=0; idof<n_dofs; idof++){
2970  const unsigned int istate = finite_element.system_to_component_index(idof).first;
2971  const unsigned int ishape = finite_element.system_to_component_index(idof).second;
2972  if(ishape == 0)
2973  this->oneD_surf_state_operator[istate][iface].reinit(n_face_quad_pts, n_shape_fns);
2974 
2975  this->oneD_surf_state_operator[istate][iface][iquad][ishape] = finite_element.shape_value_component(idof,quadrature.point(iquad),istate);
2976  }
2977  }
2978  }
2979 }
2980 
2981 template <int dim, int nstate, int n_faces>
2983  const unsigned int max_degree_input,
2984  const unsigned int grid_degree_input)
2985  : SumFactorizedOperatorsState<dim,nstate,n_faces>::SumFactorizedOperatorsState(max_degree_input, grid_degree_input)
2986 {
2987  //Initialize to the max degrees
2988  current_degree = max_degree_input;
2989 }
2990 
2991 template <int dim, int nstate, int n_faces>
2993  const dealii::FESystem<1,1> &finite_element,
2994  const dealii::Quadrature<1> &quadrature)
2995 {
2996  const unsigned int n_quad_pts = quadrature.size();
2997  const unsigned int n_dofs = finite_element.dofs_per_cell;
2998  assert(n_dofs == n_quad_pts);
2999  //Note thate the flux basis should only have one state in the finite element.
3000  //loop and store
3001  for(int istate=0; istate<nstate; istate++){
3002  //allocate the basis at volume cubature
3003  this->oneD_vol_state_operator[istate].reinit(n_quad_pts, n_dofs);
3004  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
3005  const dealii::Point<1> qpoint = quadrature.point(iquad);
3006  for(unsigned int idof=0; idof<n_dofs; idof++){
3007  //Basis function idof of poly degree idegree evaluated at cubature node qpoint.
3008  this->oneD_vol_state_operator[istate][iquad][idof] = finite_element.shape_value_component(idof,qpoint,0);
3009  }
3010  }
3011  }
3012 }
3013 
3014 template <int dim, int nstate, int n_faces>
3016  const dealii::FESystem<1,1> &finite_element,
3017  const dealii::Quadrature<1> &quadrature)
3018 {
3019  const unsigned int n_quad_pts = quadrature.size();
3020  const unsigned int n_dofs = finite_element.dofs_per_cell;
3021  assert(n_dofs == n_quad_pts);
3022  //loop and store
3023  for(int istate=0; istate<nstate; istate++){
3024  //allocate
3025  this->oneD_grad_state_operator[istate].reinit(n_quad_pts, n_dofs);
3026  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
3027  const dealii::Point<1> qpoint = quadrature.point(iquad);
3028  for(unsigned int idof=0; idof<n_dofs; idof++){
3029  this->oneD_grad_state_operator[istate][iquad][idof] = finite_element.shape_grad_component(idof, qpoint, 0)[0];
3030  }
3031  }
3032  }
3033 }
3034 template <int dim, int nstate, int n_faces>
3036  const dealii::FESystem<1,1> &finite_element,
3037  const dealii::Quadrature<0> &face_quadrature)
3038 {
3039  const unsigned int n_face_quad_pts = face_quadrature.size();
3040  const unsigned int n_dofs = finite_element.dofs_per_cell;
3041  const unsigned int n_faces_1D = n_faces / dim;
3042  //loop and store
3043  for(unsigned int iface=0; iface<n_faces_1D; iface++){
3044  const dealii::Quadrature<1> quadrature = dealii::QProjector<1>::project_to_face(dealii::ReferenceCell::get_hypercube(1),
3045  face_quadrature,
3046  iface);
3047  for(int istate=0; istate<nstate; istate++){
3048  this->oneD_surf_state_operator[istate][iface].reinit(n_face_quad_pts, n_dofs);
3049  for(unsigned int iquad=0; iquad<n_face_quad_pts; iquad++){
3050  for(unsigned int idof=0; idof<n_dofs; idof++){
3051  this->oneD_surf_state_operator[istate][iface][iquad][idof] = finite_element.shape_value_component(idof,quadrature.point(iquad),0);
3052  }
3053  }
3054  }
3055  }
3056 }
3057 
3058 
3059 template <int dim, int nstate, int n_faces>
3061  const unsigned int max_degree_input,
3062  const unsigned int grid_degree_input)
3063  : flux_basis_functions_state<dim,nstate,n_faces>::flux_basis_functions_state(max_degree_input, grid_degree_input)
3064 {
3065  //Initialize to the max degrees
3066  current_degree = max_degree_input;
3067 }
3068 
3069 template <int dim, int nstate, int n_faces>
3071  const dealii::FESystem<1,1> &finite_element,
3072  const dealii::Quadrature<1> &quadrature)
3073 {
3074  const unsigned int n_quad_pts = quadrature.size();
3075  const unsigned int n_dofs_flux = quadrature.size();
3076  const unsigned int n_dofs = finite_element.dofs_per_cell;
3077  //loop and store
3078  const std::vector<double> &quad_weights = quadrature.get_weights ();
3079  for(int istate_flux=0; istate_flux<nstate; istate_flux++){
3080  //allocate
3081  this->oneD_vol_state_operator[istate_flux].reinit(n_dofs, n_quad_pts);
3082  for(unsigned int itest=0; itest<n_dofs; itest++){
3083  const int istate_test = finite_element.system_to_component_index(itest).first;
3084  for(unsigned int idof=0; idof<n_dofs_flux; idof++){
3085  double value = 0.0;
3086  for(unsigned int iquad=0; iquad<n_quad_pts; iquad++){
3087  const dealii::Point<1> qpoint = quadrature.point(iquad);
3088  value += finite_element.shape_value_component(itest, qpoint, istate_test)
3089  * quad_weights[iquad]
3090  * this->oneD_grad_state_operator[istate_flux][iquad][idof];
3091  }
3092  this->oneD_vol_state_operator[istate_flux][itest][idof] = value;
3093  }
3094  }
3095  }
3096 }
3097 
3098 
3100 
3102 
3108 
3122 template class FR_mass <PHILIP_DIM, 2*PHILIP_DIM>;
3125 
3126 //template class basis_at_facet_cubature <PHILIP_DIM, 2*PHILIP_DIM>;
3130 
3132 
3138 //template class vol_metric_operators <double,PHILIP_DIM, 2*PHILIP_DIM>;
3139 //template class vol_determinant_metric_Jacobian<PHILIP_DIM, 2*PHILIP_DIM>;
3140 //template class vol_metric_cofactor<PHILIP_DIM, 2*PHILIP_DIM>;
3141 //template class surface_metric_cofactor<PHILIP_DIM, 2*PHILIP_DIM>;
3142 //
3148 
3159 
3161  const std::vector<double> &input_vect,
3162  std::vector<double> &output_vect,
3163  const dealii::FullMatrix<double> &basis_x,
3164  const dealii::FullMatrix<double> &basis_y,
3165  const dealii::FullMatrix<double> &basis_z,
3166  const bool adding,
3167  const double factor);
3169  const std::vector<FadType> &input_vect,
3170  std::vector<FadType> &output_vect,
3171  const dealii::FullMatrix<double> &basis_x,
3172  const dealii::FullMatrix<double> &basis_y,
3173  const dealii::FullMatrix<double> &basis_z,
3174  const bool adding,
3175  const double factor);
3177  const std::vector<RadType> &input_vect,
3178  std::vector<RadType> &output_vect,
3179  const dealii::FullMatrix<double> &basis_x,
3180  const dealii::FullMatrix<double> &basis_y,
3181  const dealii::FullMatrix<double> &basis_z,
3182  const bool adding,
3183  const double factor);
3185  const std::vector<FadFadType> &input_vect,
3186  std::vector<FadFadType> &output_vect,
3187  const dealii::FullMatrix<double> &basis_x,
3188  const dealii::FullMatrix<double> &basis_y,
3189  const dealii::FullMatrix<double> &basis_z,
3190  const bool adding,
3191  const double factor);
3193  const std::vector<RadFadType> &input_vect,
3194  std::vector<RadFadType> &output_vect,
3195  const dealii::FullMatrix<double> &basis_x,
3196  const dealii::FullMatrix<double> &basis_y,
3197  const dealii::FullMatrix<double> &basis_z,
3198  const bool adding,
3199  const double factor);
3200 
3202  const dealii::Tensor<1,PHILIP_DIM,std::vector<double>> &input_vect,
3203  std::vector<double> &output_vect,
3204  const dealii::FullMatrix<double> &basis_x,
3205  const dealii::FullMatrix<double> &basis_y,
3206  const dealii::FullMatrix<double> &basis_z,
3207  const dealii::FullMatrix<double> &gradient_basis_x,
3208  const dealii::FullMatrix<double> &gradient_basis_y,
3209  const dealii::FullMatrix<double> &gradient_basis_z);
3211  const dealii::Tensor<1,PHILIP_DIM,std::vector<FadType>> &input_vect,
3212  std::vector<FadType> &output_vect,
3213  const dealii::FullMatrix<double> &basis_x,
3214  const dealii::FullMatrix<double> &basis_y,
3215  const dealii::FullMatrix<double> &basis_z,
3216  const dealii::FullMatrix<double> &gradient_basis_x,
3217  const dealii::FullMatrix<double> &gradient_basis_y,
3218  const dealii::FullMatrix<double> &gradient_basis_z);
3220  const dealii::Tensor<1,PHILIP_DIM,std::vector<RadType>> &input_vect,
3221  std::vector<RadType> &output_vect,
3222  const dealii::FullMatrix<double> &basis_x,
3223  const dealii::FullMatrix<double> &basis_y,
3224  const dealii::FullMatrix<double> &basis_z,
3225  const dealii::FullMatrix<double> &gradient_basis_x,
3226  const dealii::FullMatrix<double> &gradient_basis_y,
3227  const dealii::FullMatrix<double> &gradient_basis_z);
3229  const dealii::Tensor<1,PHILIP_DIM,std::vector<FadFadType>> &input_vect,
3230  std::vector<FadFadType> &output_vect,
3231  const dealii::FullMatrix<double> &basis_x,
3232  const dealii::FullMatrix<double> &basis_y,
3233  const dealii::FullMatrix<double> &basis_z,
3234  const dealii::FullMatrix<double> &gradient_basis_x,
3235  const dealii::FullMatrix<double> &gradient_basis_y,
3236  const dealii::FullMatrix<double> &gradient_basis_z);
3238  const dealii::Tensor<1,PHILIP_DIM,std::vector<RadFadType>> &input_vect,
3239  std::vector<RadFadType> &output_vect,
3240  const dealii::FullMatrix<double> &basis_x,
3241  const dealii::FullMatrix<double> &basis_y,
3242  const dealii::FullMatrix<double> &basis_z,
3243  const dealii::FullMatrix<double> &gradient_basis_x,
3244  const dealii::FullMatrix<double> &gradient_basis_y,
3245  const dealii::FullMatrix<double> &gradient_basis_z);
3246 
3248  const dealii::Tensor<1,PHILIP_DIM,std::vector<double>> &input_vect,
3249  std::vector<double> &output_vect,
3250  const dealii::FullMatrix<double> &basis,
3251  const dealii::FullMatrix<double> &gradient_basis);
3253  const dealii::Tensor<1,PHILIP_DIM,std::vector<FadType>> &input_vect,
3254  std::vector<FadType> &output_vect,
3255  const dealii::FullMatrix<double> &basis,
3256  const dealii::FullMatrix<double> &gradient_basis);
3258  const dealii::Tensor<1,PHILIP_DIM,std::vector<RadType>> &input_vect,
3259  std::vector<RadType> &output_vect,
3260  const dealii::FullMatrix<double> &basis,
3261  const dealii::FullMatrix<double> &gradient_basis);
3263  const dealii::Tensor<1,PHILIP_DIM,std::vector<FadFadType>> &input_vect,
3264  std::vector<FadFadType> &output_vect,
3265  const dealii::FullMatrix<double> &basis,
3266  const dealii::FullMatrix<double> &gradient_basis);
3268  const dealii::Tensor<1,PHILIP_DIM,std::vector<RadFadType>> &input_vect,
3269  std::vector<RadFadType> &output_vect,
3270  const dealii::FullMatrix<double> &basis,
3271  const dealii::FullMatrix<double> &gradient_basis);
3272 
3273 
3275  const std::vector<double> &input_vect,
3276  dealii::Tensor<1,PHILIP_DIM,std::vector<double>> &output_vect,
3277  const dealii::FullMatrix<double> &basis_x,
3278  const dealii::FullMatrix<double> &basis_y,
3279  const dealii::FullMatrix<double> &basis_z,
3280  const dealii::FullMatrix<double> &gradient_basis_x,
3281  const dealii::FullMatrix<double> &gradient_basis_y,
3282  const dealii::FullMatrix<double> &gradient_basis_z);
3284  const std::vector<FadType> &input_vect,
3285  dealii::Tensor<1,PHILIP_DIM,std::vector<FadType>> &output_vect,
3286  const dealii::FullMatrix<double> &basis_x,
3287  const dealii::FullMatrix<double> &basis_y,
3288  const dealii::FullMatrix<double> &basis_z,
3289  const dealii::FullMatrix<double> &gradient_basis_x,
3290  const dealii::FullMatrix<double> &gradient_basis_y,
3291  const dealii::FullMatrix<double> &gradient_basis_z);
3293  const std::vector<RadType> &input_vect,
3294  dealii::Tensor<1,PHILIP_DIM,std::vector<RadType>> &output_vect,
3295  const dealii::FullMatrix<double> &basis_x,
3296  const dealii::FullMatrix<double> &basis_y,
3297  const dealii::FullMatrix<double> &basis_z,
3298  const dealii::FullMatrix<double> &gradient_basis_x,
3299  const dealii::FullMatrix<double> &gradient_basis_y,
3300  const dealii::FullMatrix<double> &gradient_basis_z);
3302  const std::vector<FadFadType> &input_vect,
3303  dealii::Tensor<1,PHILIP_DIM,std::vector<FadFadType>> &output_vect,
3304  const dealii::FullMatrix<double> &basis_x,
3305  const dealii::FullMatrix<double> &basis_y,
3306  const dealii::FullMatrix<double> &basis_z,
3307  const dealii::FullMatrix<double> &gradient_basis_x,
3308  const dealii::FullMatrix<double> &gradient_basis_y,
3309  const dealii::FullMatrix<double> &gradient_basis_z);
3311  const std::vector<RadFadType> &input_vect,
3312  dealii::Tensor<1,PHILIP_DIM,std::vector<RadFadType>> &output_vect,
3313  const dealii::FullMatrix<double> &basis_x,
3314  const dealii::FullMatrix<double> &basis_y,
3315  const dealii::FullMatrix<double> &basis_z,
3316  const dealii::FullMatrix<double> &gradient_basis_x,
3317  const dealii::FullMatrix<double> &gradient_basis_y,
3318  const dealii::FullMatrix<double> &gradient_basis_z);
3319 
3321  const std::vector<double> &input_vect,
3322  dealii::Tensor<1,PHILIP_DIM,std::vector<double>> &output_vect,
3323  const dealii::FullMatrix<double> &basis,
3324  const dealii::FullMatrix<double> &gradient_basis);
3326  const std::vector<FadType> &input_vect,
3327  dealii::Tensor<1,PHILIP_DIM,std::vector<FadType>> &output_vect,
3328  const dealii::FullMatrix<double> &basis,
3329  const dealii::FullMatrix<double> &gradient_basis);
3331  const std::vector<RadType> &input_vect,
3332  dealii::Tensor<1,PHILIP_DIM,std::vector<RadType>> &output_vect,
3333  const dealii::FullMatrix<double> &basis,
3334  const dealii::FullMatrix<double> &gradient_basis);
3336  const std::vector<FadFadType> &input_vect,
3337  dealii::Tensor<1,PHILIP_DIM,std::vector<FadFadType>> &output_vect,
3338  const dealii::FullMatrix<double> &basis,
3339  const dealii::FullMatrix<double> &gradient_basis);
3341  const std::vector<RadFadType> &input_vect,
3342  dealii::Tensor<1,PHILIP_DIM,std::vector<RadFadType>> &output_vect,
3343  const dealii::FullMatrix<double> &basis,
3344  const dealii::FullMatrix<double> &gradient_basis);
3345 
3346 
3348  const std::vector<double> &input_vect,
3349  const std::vector<double> &weight_vect,
3350  std::vector<double> &output_vect,
3351  const dealii::FullMatrix<double> &basis_x,
3352  const dealii::FullMatrix<double> &basis_y,
3353  const dealii::FullMatrix<double> &basis_z,
3354  const bool adding = false,
3355  const double factor = 1.0);
3357  const std::vector<FadType> &input_vect,
3358  const std::vector<double> &weight_vect,
3359  std::vector<FadType> &output_vect,
3360  const dealii::FullMatrix<double> &basis_x,
3361  const dealii::FullMatrix<double> &basis_y,
3362  const dealii::FullMatrix<double> &basis_z,
3363  const bool adding = false,
3364  const double factor = 1.0);
3366  const std::vector<RadType> &input_vect,
3367  const std::vector<double> &weight_vect,
3368  std::vector<RadType> &output_vect,
3369  const dealii::FullMatrix<double> &basis_x,
3370  const dealii::FullMatrix<double> &basis_y,
3371  const dealii::FullMatrix<double> &basis_z,
3372  const bool adding = false,
3373  const double factor = 1.0);
3375  const std::vector<FadFadType> &input_vect,
3376  const std::vector<double> &weight_vect,
3377  std::vector<FadFadType> &output_vect,
3378  const dealii::FullMatrix<double> &basis_x,
3379  const dealii::FullMatrix<double> &basis_y,
3380  const dealii::FullMatrix<double> &basis_z,
3381  const bool adding = false,
3382  const double factor = 1.0);
3384  const std::vector<RadFadType> &input_vect,
3385  const std::vector<double> &weight_vect,
3386  std::vector<RadFadType> &output_vect,
3387  const dealii::FullMatrix<double> &basis_x,
3388  const dealii::FullMatrix<double> &basis_y,
3389  const dealii::FullMatrix<double> &basis_z,
3390  const bool adding = false,
3391  const double factor = 1.0);
3392 
3394  const std::vector<double> &input_vect,
3395  std::vector<double> &output_vect,
3396  const dealii::FullMatrix<double> &basis_x,
3397  const bool adding = false,
3398  const double factor = 1.0);
3400  const std::vector<FadType> &input_vect,
3401  std::vector<FadType> &output_vect,
3402  const dealii::FullMatrix<double> &basis_x,
3403  const bool adding = false,
3404  const double factor = 1.0);
3406  const std::vector<RadType> &input_vect,
3407  std::vector<RadType> &output_vect,
3408  const dealii::FullMatrix<double> &basis_x,
3409  const bool adding = false,
3410  const double factor = 1.0);
3412  const std::vector<FadFadType> &input_vect,
3413  std::vector<FadFadType> &output_vect,
3414  const dealii::FullMatrix<double> &basis_x,
3415  const bool adding = false,
3416  const double factor = 1.0);
3418  const std::vector<RadFadType> &input_vect,
3419  std::vector<RadFadType> &output_vect,
3420  const dealii::FullMatrix<double> &basis_x,
3421  const bool adding = false,
3422  const double factor = 1.0);
3423 
3425  const std::vector<double> &input_vect,
3426  const std::vector<double> &weight_vect,
3427  std::vector<double> &output_vect,
3428  const dealii::FullMatrix<double> &basis_x,
3429  const bool adding = false,
3430  const double factor = 1.0);
3432  const std::vector<FadType> &input_vect,
3433  const std::vector<double> &weight_vect,
3434  std::vector<FadType> &output_vect,
3435  const dealii::FullMatrix<double> &basis_x,
3436  const bool adding = false,
3437  const double factor = 1.0);
3439  const std::vector<RadType> &input_vect,
3440  const std::vector<double> &weight_vect,
3441  std::vector<RadType> &output_vect,
3442  const dealii::FullMatrix<double> &basis_x,
3443  const bool adding = false,
3444  const double factor = 1.0);
3446  const std::vector<FadFadType> &input_vect,
3447  const std::vector<double> &weight_vect,
3448  std::vector<FadFadType> &output_vect,
3449  const dealii::FullMatrix<double> &basis_x,
3450  const bool adding = false,
3451  const double factor = 1.0);
3453  const std::vector<RadFadType> &input_vect,
3454  const std::vector<double> &weight_vect,
3455  std::vector<RadFadType> &output_vect,
3456  const dealii::FullMatrix<double> &basis_x,
3457  const bool adding = false,
3458  const double factor = 1.0);
3459 
3461  const std::vector<bool> face_orientation,
3462  const unsigned int face_number,
3463  const std::vector<double> &input_vect,
3464  std::vector<double> &output_vect,
3465  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3466  const dealii::FullMatrix<double> &basis_vol,
3467  const bool adding = false,
3468  const double factor = 1.0);
3470  const std::vector<bool> face_orientation,
3471  const unsigned int face_number,
3472  const std::vector<FadType> &input_vect,
3473  std::vector<FadType> &output_vect,
3474  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3475  const dealii::FullMatrix<double> &basis_vol,
3476  const bool adding = false,
3477  const double factor = 1.0);
3479  const std::vector<bool> face_orientation,
3480  const unsigned int face_number,
3481  const std::vector<RadType> &input_vect,
3482  std::vector<RadType> &output_vect,
3483  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3484  const dealii::FullMatrix<double> &basis_vol,
3485  const bool adding = false,
3486  const double factor = 1.0);
3488  const std::vector<bool> face_orientation,
3489  const unsigned int face_number,
3490  const std::vector<FadFadType> &input_vect,
3491  std::vector<FadFadType> &output_vect,
3492  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3493  const dealii::FullMatrix<double> &basis_vol,
3494  const bool adding = false,
3495  const double factor = 1.0);
3497  const std::vector<bool> face_orientation,
3498  const unsigned int face_number,
3499  const std::vector<RadFadType> &input_vect,
3500  std::vector<RadFadType> &output_vect,
3501  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3502  const dealii::FullMatrix<double> &basis_vol,
3503  const bool adding = false,
3504  const double factor = 1.0);
3505 
3506 
3508  const std::vector<bool> face_orientation,
3509  const unsigned int face_number,
3510  const std::vector<double> &input_vect,
3511  const std::vector<double> &weight_vect,
3512  std::vector< double> &output_vect,
3513  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3514  const dealii::FullMatrix<double> &basis_vol,
3515  const bool adding = false,
3516  const double factor = 1.0);
3518  const std::vector<bool> face_orientation,
3519  const unsigned int face_number,
3520  const std::vector<FadType> &input_vect,
3521  const std::vector<double> &weight_vect,
3522  std::vector< FadType> &output_vect,
3523  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3524  const dealii::FullMatrix<double> &basis_vol,
3525  const bool adding = false,
3526  const double factor = 1.0);
3528  const std::vector<bool> face_orientation,
3529  const unsigned int face_number,
3530  const std::vector<RadType> &input_vect,
3531  const std::vector<double> &weight_vect,
3532  std::vector< RadType> &output_vect,
3533  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3534  const dealii::FullMatrix<double> &basis_vol,
3535  const bool adding = false,
3536  const double factor = 1.0);
3538  const std::vector<bool> face_orientation,
3539  const unsigned int face_number,
3540  const std::vector<FadFadType> &input_vect,
3541  const std::vector<double> &weight_vect,
3542  std::vector< FadFadType> &output_vect,
3543  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3544  const dealii::FullMatrix<double> &basis_vol,
3545  const bool adding = false,
3546  const double factor = 1.0);
3548  const std::vector<bool> face_orientation,
3549  const unsigned int face_number,
3550  const std::vector<RadFadType> &input_vect,
3551  const std::vector<double> &weight_vect,
3552  std::vector< RadFadType> &output_vect,
3553  const std::array<dealii::FullMatrix<double>,2> &basis_surf,//only 2 faces in 1D
3554  const dealii::FullMatrix<double> &basis_vol,
3555  const bool adding = false,
3556  const double factor = 1.0);
3557 
3559  const dealii::FullMatrix<double> &input_mat,
3560  const std::vector<double> &input_vect,
3561  std::vector< double> &output_vect);
3563  const dealii::FullMatrix<double> &input_mat,
3564  const std::vector<FadType> &input_vect,
3565  std::vector< FadType> &output_vect);
3567  const dealii::FullMatrix<double> &input_mat,
3568  const std::vector<RadType> &input_vect,
3569  std::vector< RadType> &output_vect);
3571  const dealii::FullMatrix<double> &input_mat,
3572  const std::vector<FadFadType> &input_vect,
3573  std::vector< FadFadType> &output_vect);
3575  const dealii::FullMatrix<double> &input_mat,
3576  const std::vector<RadFadType> &input_vect,
3577  std::vector< RadFadType> &output_vect);
3578 
3579 } // OPERATOR namespace
3580 } // PHiLiP namespace
3581 
bool store_transpose
Flag is store transpose operator.
Definition: operators.h:762
std::array< dealii::FullMatrix< double >, nstate > oneD_vol_state_operator
Stores the one dimensional volume operator.
Definition: operators.h:1346
The FLUX basis functions separated by nstate with n shape functions.
Definition: operators.h:1393
vol_projection_operator(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:1854
SumFactorizedOperators(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Precompute 1D operator in constructor.
Definition: operators.cpp:188
dealii::ConditionalOStream pcout
Parallel std::cout that only outputs on mpi_rank==0.
Definition: operators.h:103
const unsigned int max_degree
Max polynomial degree.
Definition: operators.h:66
void inner_product(const std::vector< real > &input_vect, const std::vector< double > &weight_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const dealii::FullMatrix< double > &basis_y, const dealii::FullMatrix< double > &basis_z, const bool adding=false, const double factor=1.0)
Computes the inner product between a matrix and a vector multiplied by some weight function...
Definition: operators.cpp:575
dealii::Tensor< 2, dim, std::vector< real > > metric_cofactor_vol
The volume metric cofactor matrix.
Definition: operators.h:1210
const Parameters::AllParameters::Flux_Reconstruction FR_param_type
Flux reconstruction parameter type.
Definition: operators.h:765
const double FR_user_specified_correction_parameter_value
User specified flux recontruction correction parameter value.
Definition: operators.h:1041
lifting_operator_FR(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const Parameters::AllParameters::Flux_Reconstruction FR_param_input, const double FR_user_specified_correction_parameter_value_input=0.0)
Constructor.
Definition: operators.cpp:2233
void build_facet_metric_operators(const unsigned int iface, const unsigned int n_quad_pts, const unsigned int n_metric_dofs, const std::array< std::vector< real >, dim > &mapping_support_points, mapping_shape_functions< dim, n_faces > &mapping_basis, const bool use_invariant_curl_form=false)
Builds the facet metric operators.
Definition: operators.cpp:2501
The metric independent inverse of the FR mass matrix .
Definition: operators.h:815
basis_functions< dim, n_faces > mapping_shape_functions_flux_nodes
Object of mapping shape functions evaluated at flux nodes.
Definition: operators.h:1090
void build_1D_gradient_state_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2934
Sacado::Fad::DFad< FadType > FadFadType
Sacado AD type that allows 2nd derivatives.
Definition: ADTypes.hpp:12
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:508
metric_operators(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const bool store_vol_flux_nodes_input=false, const bool store_surf_flux_nodes_input=false, const bool store_Jacobian_input=false)
Constructor.
Definition: operators.cpp:2340
The integration of gradient of solution basis.
Definition: operators.h:924
FR_mass_inv_aux(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const Parameters::AllParameters::Flux_Reconstruction_Aux FR_param_input)
Constructor.
Definition: operators.cpp:2008
const bool store_skew_symmetric_form
Flag to store the skew symmetric form .
Definition: operators.h:511
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2083
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:853
const int nstate
Number of states.
Definition: operators.h:70
void face_orientation_tensor_product(const std::vector< bool > face_orientation, const unsigned int face_number, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis)
These function correct the face orientation of a face, in case deal.ii changes it.
Definition: operators.cpp:209
Sum Factorization derived class.
Definition: operators.h:112
Sacado::Fad::DFad< double > FadType
Sacado AD type for first derivatives.
Definition: ADTypes.hpp:11
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1837
double FR_param
Flux reconstruction paramater value.
Definition: operators.h:585
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1217
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &face_quadrature)
Assembles the one dimensional norm operator that it is lifted onto.
Definition: operators.cpp:2248
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1520
void get_FR_correction_parameter(const unsigned int curr_cell_degree, double &c)
Gets the FR correction parameter for the primary equation and stores.
Definition: operators.cpp:1629
codi_JacobianComputationType RadType
CoDiPaco reverse-AD type for first derivatives.
Definition: ADTypes.hpp:27
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:827
The metric independent FR mass matrix for auxiliary equation .
Definition: operators.h:893
void build_1D_volume_state_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2910
void transform_reference_unit_normal_to_physical_unit_normal(const unsigned int n_quad_pts, const dealii::Tensor< 1, dim, real > &ref, const dealii::Tensor< 2, dim, std::vector< real >> &metric_cofactor, std::vector< dealii::Tensor< 1, dim, real >> &phys)
Given a reference tensor, return the physical tensor.
Definition: operators.cpp:2402
void build_1D_shape_functions_at_volume_flux_nodes(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Constructs the volume and volume gradient operator.
Definition: operators.cpp:2325
void Hadamard_product(const dealii::FullMatrix< double > &input_mat1, const dealii::FullMatrix< double > &input_mat2, dealii::FullMatrix< double > &output_mat)
Computes a single Hadamard product.
Definition: operators.cpp:911
void matrix_vector_mult_1D(const std::vector< real > &input_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const bool adding=false, const double factor=1.0)
Apply the matrix vector operation using the 1D operator in each direction.
Definition: operators.cpp:402
FR_mass(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const Parameters::AllParameters::Flux_Reconstruction FR_param_input, const double FR_user_specified_correction_parameter_value_input=0.0)
Constructor.
Definition: operators.cpp:2038
const Parameters::AllParameters::Flux_Reconstruction FR_param_type
Flux reconstruction parameter type.
Definition: operators.h:880
void build_local_Flux_Reconstruction_operator(const dealii::FullMatrix< double > &local_Mass_Matrix, const dealii::FullMatrix< double > &pth_derivative, const unsigned int n_dofs, const double c, dealii::FullMatrix< double > &Flux_Reconstruction_operator)
Computes a single local Flux_Reconstruction operator (ESFR correction operator) on the fly for a loca...
Definition: operators.cpp:1663
void build_1D_surface_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 0 > &face_quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2150
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1440
void build_determinant_volume_metric_Jacobian(const unsigned int n_quad_pts, const unsigned int n_metric_dofs, const std::array< std::vector< real >, dim > &mapping_support_points, mapping_shape_functions< dim, n_faces > &mapping_basis)
Builds just the determinant of the volume metric determinant.
Definition: operators.cpp:2423
Projection operator corresponding to basis functions onto -norm for auxiliary equation.
Definition: operators.h:784
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &face_quadrature)
Assembles the one dimensional norm operator that it is lifted onto.
Definition: operators.cpp:2190
dealii::FullMatrix< double > build_dim_Flux_Reconstruction_operator(const dealii::FullMatrix< double > &local_Mass_Matrix, const int nstate, const unsigned int n_dofs)
Computes the dim sized flux reconstruction operator with simplified tensor product form...
Definition: operators.cpp:1758
const double FR_user_specified_correction_parameter_value
User specified flux recontruction correction parameter value.
Definition: operators.h:883
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:733
void matrix_vector_mult(const std::vector< real > &input_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const dealii::FullMatrix< double > &basis_y, const dealii::FullMatrix< double > &basis_z, const bool adding=false, const double factor=1.0)
Computes a matrix-vector product using sum-factorization. Pass the one-dimensional basis...
Definition: operators.cpp:294
Files for the baseline physics.
Definition: ADTypes.hpp:10
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:967
void build_1D_shape_functions_at_flux_nodes(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature, const dealii::Quadrature< 0 > &face_quadrature)
Constructs the volume, gradient, surface, and surface gradient operator.
Definition: operators.cpp:2313
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1354
void compute_local_3D_cofactor(const unsigned int n_metric_dofs, const unsigned int n_quad_pts, const std::array< std::vector< real >, dim > &mapping_support_points, const dealii::FullMatrix< double > &basis_x_grid_nodes, const dealii::FullMatrix< double > &basis_y_grid_nodes, const dealii::FullMatrix< double > &basis_z_grid_nodes, const dealii::FullMatrix< double > &basis_x_flux_nodes, const dealii::FullMatrix< double > &basis_y_flux_nodes, const dealii::FullMatrix< double > &basis_z_flux_nodes, const dealii::FullMatrix< double > &grad_basis_x_grid_nodes, const dealii::FullMatrix< double > &grad_basis_y_grid_nodes, const dealii::FullMatrix< double > &grad_basis_z_grid_nodes, const dealii::FullMatrix< double > &grad_basis_x_flux_nodes, const dealii::FullMatrix< double > &grad_basis_y_flux_nodes, const dealii::FullMatrix< double > &grad_basis_z_flux_nodes, dealii::Tensor< 2, dim, std::vector< real >> &metric_cofactor, const bool use_invariant_curl_form=false)
Computes local 3D cofactor matrix.
Definition: operators.cpp:2738
mapping_shape_functions(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:2290
void divergence_two_pt_flux_Hadamard_product(const dealii::Tensor< 1, dim, dealii::FullMatrix< double >> &input_mat, std::vector< double > &output_vect, const std::vector< double > &weights, const dealii::FullMatrix< double > &basis, const double scaling=2.0)
Computes the divergence of the 2pt flux Hadamard products, then sums the rows.
Definition: operators.cpp:652
dealii::Tensor< 2, dim, std::vector< real > > metric_cofactor_surf
The facet metric cofactor matrix, for ONE face.
Definition: operators.h:1213
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:554
In order to have all state operators be arrays of array, we template by dim, type, nstate, and number of faces.
Definition: operators.h:1337
void sum_factorized_Hadamard_sparsity_pattern(const unsigned int rows_size, const unsigned int columns_size, std::vector< std::array< unsigned int, dim >> &rows, std::vector< std::array< unsigned int, dim >> &columns)
Computes the rows and columns vectors with non-zero indices for sum-factorized Hadamard products...
Definition: operators.cpp:949
lifting_operator(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:2179
Flux_Reconstruction
Type of correction in Flux Reconstruction.
void sum_factorized_Hadamard_surface_sparsity_pattern(const unsigned int rows_size, const unsigned int columns_size, std::vector< unsigned int > &rows, std::vector< unsigned int > &columns, const int dim_not_zero)
Computes the rows and columns vectors with non-zero indices for surface sum-factorized Hadamard produ...
Definition: operators.cpp:1067
const bool store_Jacobian
Flag if store metric Jacobian at flux nodes.
Definition: operators.h:1144
basis_functions_state(const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:2900
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:1035
-th order modal derivative of basis fuctions, ie/
Definition: operators.h:544
const double FR_user_specified_correction_parameter_value
User specified flux recontruction correction parameter value.
Definition: operators.h:579
std::array< dealii::FullMatrix< double >, 2 > oneD_surf_grad_operator
Stores the one dimensional surface gradient operator.
Definition: operators.h:391
void get_c_negative_FR_parameter(const unsigned int curr_cell_degree, double &c)
Evaluates the flux reconstruction parameter at the bottom limit where the scheme is unstable...
Definition: operators.cpp:1582
void divergence_matrix_vector_mult_1D(const dealii::Tensor< 1, dim, std::vector< real >> &input_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis, const dealii::FullMatrix< double > &gradient_basis)
Computes the divergence using sum-factorization where the basis are the same in each direction...
Definition: operators.cpp:481
const Parameters::AllParameters::Flux_Reconstruction FR_param_type
Flux reconstruction parameter type.
Definition: operators.h:1038
That is Quadrature Weights multiplies with basis_at_vol_cubature.
Definition: operators.h:441
void matrix_vector_mult_surface_1D(const std::vector< bool > face_orientation, const unsigned int face_number, const std::vector< real > &input_vect, std::vector< real > &output_vect, const std::array< dealii::FullMatrix< double >, 2 > &basis_surf, const dealii::FullMatrix< double > &basis_vol, const bool adding=false, const double factor=1.0)
Apply sum-factorization matrix vector multiplication on a surface.
Definition: operators.cpp:414
const bool store_surf_flux_nodes
Flag if store metric Jacobian at flux nodes.
Definition: operators.h:1150
void build_local_metric_cofactor_matrix(const unsigned int n_quad_pts, const unsigned int n_metric_dofs, const std::array< std::vector< real >, dim > &mapping_support_points, const dealii::FullMatrix< double > &basis_x_grid_nodes, const dealii::FullMatrix< double > &basis_y_grid_nodes, const dealii::FullMatrix< double > &basis_z_grid_nodes, const dealii::FullMatrix< double > &basis_x_flux_nodes, const dealii::FullMatrix< double > &basis_y_flux_nodes, const dealii::FullMatrix< double > &basis_z_flux_nodes, const dealii::FullMatrix< double > &grad_basis_x_grid_nodes, const dealii::FullMatrix< double > &grad_basis_y_grid_nodes, const dealii::FullMatrix< double > &grad_basis_z_grid_nodes, const dealii::FullMatrix< double > &grad_basis_x_flux_nodes, const dealii::FullMatrix< double > &grad_basis_y_flux_nodes, const dealii::FullMatrix< double > &grad_basis_z_flux_nodes, dealii::Tensor< 2, dim, std::vector< real >> &metric_cofactor, const bool use_invariant_curl_form=false)
Called on the fly and returns the metric cofactor at cubature nodes.
Definition: operators.cpp:2674
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:934
basis_functions< dim, n_faces > mapping_shape_functions_grid_nodes
Object of mapping shape functions evaluated at grid nodes.
Definition: operators.h:1087
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:992
void transform_reference_to_physical(const dealii::Tensor< 1, dim, real > &ref, const dealii::Tensor< 2, dim, real > &metric_cofactor, dealii::Tensor< 1, dim, real > &phys)
Given a reference tensor, return the physical tensor.
Definition: operators.cpp:2368
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:416
dealii::FullMatrix< double > tensor_product(const dealii::FullMatrix< double > &basis_x, const dealii::FullMatrix< double > &basis_y, const dealii::FullMatrix< double > &basis_z)
Returns the tensor product of matrices passed.
Definition: operators.cpp:55
void build_1D_surface_gradient_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 0 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1284
void gradient_matrix_vector_mult(const std::vector< real > &input_vect, dealii::Tensor< 1, dim, std::vector< real >> &output_vect, const dealii::FullMatrix< double > &basis_x, const dealii::FullMatrix< double > &basis_y, const dealii::FullMatrix< double > &basis_z, const dealii::FullMatrix< double > &gradient_basis_x, const dealii::FullMatrix< double > &gradient_basis_y, const dealii::FullMatrix< double > &gradient_basis_z)
Computes the gradient of a scalar using sum-factorization.
Definition: operators.cpp:541
double compute_factorial(double n)
Standard function to compute factorial of a number.
Definition: operators.cpp:173
This is the solution basis , the modal differential opertaor commonly seen in DG defined as ...
Definition: operators.h:524
ESFR correction matrix without jac dependence.
Definition: operators.h:564
void get_Huynh_g2_parameter(const unsigned int curr_cell_degree, double &c)
Evaluates Huynh&#39;s g2 parameter for flux reconstruction.
Definition: operators.cpp:1560
std::vector< real > det_Jac_vol
The determinant of the metric Jacobian at volume cubature nodes.
Definition: operators.h:1216
Local mass matrix without jacobian dependence.
Definition: operators.h:461
const Parameters::AllParameters::Flux_Reconstruction_Aux FR_param_type
Flux reconstruction parameter type.
Definition: operators.h:856
The DG lifting operator is defined as the operator that lifts inner products of polynomials of some o...
Definition: operators.h:982
void build_volume_metric_operators(const unsigned int n_quad_pts, const unsigned int n_metric_dofs, const std::array< std::vector< real >, dim > &mapping_support_points, mapping_shape_functions< dim, n_faces > &mapping_basis, const bool use_invariant_curl_form=false)
Builds the volume metric operators.
Definition: operators.cpp:2444
dealii::FullMatrix< double > build_dim_mass_matrix(const int nstate, const unsigned int n_dofs, const unsigned int n_quad_pts, basis_functions< dim, n_faces > &basis, const std::vector< double > &det_Jac, const std::vector< double > &quad_weights)
Assemble the dim mass matrix on the fly with metric Jacobian dependence.
Definition: operators.cpp:1388
bool store_transpose
Flag is store transpose operator.
Definition: operators.h:799
std::array< dealii::FullMatrix< double >, nstate > oneD_grad_state_operator
Stores the one dimensional gradient operator.
Definition: operators.h:1352
const unsigned int max_grid_degree
Max grid degree.
Definition: operators.h:68
void build_metric_Jacobian(const unsigned int n_quad_pts, const std::array< std::vector< real >, dim > &mapping_support_points, const dealii::FullMatrix< double > &basis_x_flux_nodes, const dealii::FullMatrix< double > &basis_y_flux_nodes, const dealii::FullMatrix< double > &basis_z_flux_nodes, const dealii::FullMatrix< double > &grad_basis_x_flux_nodes, const dealii::FullMatrix< double > &grad_basis_y_flux_nodes, const dealii::FullMatrix< double > &grad_basis_z_flux_nodes, std::vector< dealii::Tensor< 2, dim, real >> &local_Jac)
Builds the metric Jacobian evaluated at a vector of points.
Definition: operators.cpp:2591
void compute_local_vol_projection_operator(const dealii::FullMatrix< double > &norm_matrix_inverse, const dealii::FullMatrix< double > &integral_vol_basis, dealii::FullMatrix< double > &volume_projection)
Computes a single local projection operator on some space (norm).
Definition: operators.cpp:1865
void Hadamard_product_AD_vector(const dealii::FullMatrix< double > &input_mat1, const std::vector< real > &input_mat2, std::vector< real > &output_mat)
Computes a single Hadamard product for AD type.
Definition: operators.cpp:931
void build_1D_gradient_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2112
std::array< std::array< dealii::FullMatrix< double >, 2 >, nstate > oneD_surf_state_operator
Stores the one dimensional surface operator.
Definition: operators.h:1349
dealii::Tensor< 2, dim, std::vector< real > > metric_Jacobian_vol_cubature
Stores the metric Jacobian at flux nodes.
Definition: operators.h:1222
SumFactorizedOperatorsState(const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:2893
dealii::FullMatrix< double > oneD_transpose_vol_operator
Stores the transpose of the operator for fast weight-adjusted solves.
Definition: operators.h:779
dealii::FullMatrix< double > build_dim_Flux_Reconstruction_operator_directly(const int nstate, const unsigned int n_dofs, dealii::FullMatrix< double > &pth_deriv, dealii::FullMatrix< double > &mass_matrix)
Computes the dim sized flux reconstruction operator for general Mass Matrix (needed for curvilinear)...
Definition: operators.cpp:1697
The ESFR lifting operator.
Definition: operators.h:1023
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:471
void sum_factorized_Hadamard_basis_assembly(const unsigned int rows_size_1D, const unsigned int columns_size_1D, const std::vector< std::array< unsigned int, dim >> &rows, const std::vector< std::array< unsigned int, dim >> &columns, const dealii::FullMatrix< double > &basis, const std::vector< double > &weights, std::array< dealii::FullMatrix< double >, dim > &basis_sparse)
Constructs the basis operator storing all non-zero entries for a "sum-factorized" Hadamard product...
Definition: operators.cpp:1014
void build_1D_surface_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 0 > &face_quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2214
const Parameters::AllParameters::Flux_Reconstruction_Aux FR_param_type
Flux reconstruction parameter type.
Definition: operators.h:802
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1491
Base metric operators class that stores functions used in both the volume and on surface.
Definition: operators.h:1131
void build_determinant_metric_Jacobian(const unsigned int n_quad_pts, const std::array< std::vector< real >, dim > &mapping_support_points, const dealii::FullMatrix< double > &basis_x_flux_nodes, const dealii::FullMatrix< double > &basis_y_flux_nodes, const dealii::FullMatrix< double > &basis_z_flux_nodes, const dealii::FullMatrix< double > &grad_basis_x_flux_nodes, const dealii::FullMatrix< double > &grad_basis_y_flux_nodes, const dealii::FullMatrix< double > &grad_basis_z_flux_nodes, std::vector< real > &det_metric_Jac)
Assembles the determinant of metric Jacobian.
Definition: operators.cpp:2629
ESFR correction matrix for AUX EQUATION without jac dependence.
Definition: operators.h:684
local_Flux_Reconstruction_operator_aux(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const Parameters::AllParameters::Flux_Reconstruction_Aux FR_param_aux_input)
Constructor.
Definition: operators.cpp:1794
void build_1D_surface_state_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 0 > &face_quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:3035
dealii::FullMatrix< double > oneD_vol_operator
Stores the one dimensional volume operator.
Definition: operators.h:380
The mapping shape functions evaluated at the desired nodes (facet set included in volume grid nodes f...
Definition: operators.h:1071
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:771
unsigned int current_grid_degree
Stores the degree of the current grid degree.
Definition: operators.h:1084
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:796
const bool store_vol_flux_nodes
Flag if store metric Jacobian at flux nodes.
Definition: operators.h:1147
const Parameters::AllParameters::Flux_Reconstruction FR_param_type
Flux reconstruction parameter type.
Definition: operators.h:576
std::array< dealii::FullMatrix< double >, 2 > oneD_surf_operator
Stores the one dimensional surface operator.
Definition: operators.h:385
The basis functions separated by nstate with n shape functions.
Definition: operators.h:1361
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1949
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:451
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1873
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:904
The metric independent FR mass matrix .
Definition: operators.h:865
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1909
void inner_product_1D(const std::vector< real > &input_vect, const std::vector< double > &weight_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const bool adding=false, const double factor=1.0)
Apply the inner product operation using the 1D operator in each direction.
Definition: operators.cpp:640
void build_1D_gradient_state_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:3015
void transform_physical_to_reference(const dealii::Tensor< 1, dim, real > &phys, const dealii::Tensor< 2, dim, real > &metric_cofactor, dealii::Tensor< 1, dim, real > &ref)
Given a physical tensor, return the reference tensor.
Definition: operators.cpp:2354
const Parameters::AllParameters::Flux_Reconstruction_Aux FR_param_aux_type
Flux reconstruction parameter type.
Definition: operators.h:698
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2053
void build_1D_surface_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 0 > &face_quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2264
const Parameters::AllParameters::Flux_Reconstruction_Aux FR_param_type
Flux reconstruction parameter type.
Definition: operators.h:907
void build_local_surface_lifting_operator(const unsigned int n_dofs, const dealii::FullMatrix< double > &norm_matrix, const dealii::FullMatrix< double > &face_integral, dealii::FullMatrix< double > &lifting)
Builds the local lifting operator.
Definition: operators.cpp:2203
Flux_Reconstruction_Aux
Type of correction in Flux Reconstruction for the auxiliary variables.
dealii::FullMatrix< double > oneD_grad_operator
Stores the one dimensional gradient operator.
Definition: operators.h:388
void inner_product_surface_1D(const std::vector< bool > face_orientation, const unsigned int face_number, const std::vector< real > &input_vect, const std::vector< double > &weight_vect, std::vector< real > &output_vect, const std::array< dealii::FullMatrix< double >, 2 > &basis_surf, const dealii::FullMatrix< double > &basis_vol, const bool adding=false, const double factor=1.0)
Apply sum-factorization inner product on a surface.
Definition: operators.cpp:445
basis_functions(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:1206
std::vector< real > det_Jac_surf
The determinant of the metric Jacobian at facet cubature nodes.
Definition: operators.h:1219
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:877
The metric independent inverse of the FR mass matrix for auxiliary equation .
Definition: operators.h:842
Projection operator corresponding to basis functions onto -norm.
Definition: operators.h:749
void get_c_plus_parameter(const unsigned int curr_cell_degree, double &c)
Gets the FR correction parameter corresponding to the maximum timestep.
Definition: operators.cpp:1601
void build_1D_shape_functions_at_grid_nodes(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Constructs the volume operator and gradient operator.
Definition: operators.cpp:2304
local_mass(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:1343
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:534
void divergence_matrix_vector_mult(const dealii::Tensor< 1, dim, std::vector< real >> &input_vect, std::vector< real > &output_vect, const dealii::FullMatrix< double > &basis_x, const dealii::FullMatrix< double > &basis_y, const dealii::FullMatrix< double > &basis_z, const dealii::FullMatrix< double > &gradient_basis_x, const dealii::FullMatrix< double > &gradient_basis_y, const dealii::FullMatrix< double > &gradient_basis_z)
Computes the divergence using the sum factorization matrix-vector multiplication. ...
Definition: operators.cpp:494
vol_integral_gradient_basis(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:2101
void build_1D_volume_state_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:3070
dealii::FullMatrix< double > oneD_skew_symm_vol_oper
Skew-symmetric volume operator .
Definition: operators.h:519
void get_FR_aux_correction_parameter(const unsigned int curr_cell_degree, double &k)
Gets the FR correction parameter for the auxiliary equations and stores.
Definition: operators.cpp:1809
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1679
vol_projection_operator_FR(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const Parameters::AllParameters::Flux_Reconstruction FR_param_input, const double FR_user_specified_correction_parameter_value_input=0.0, const bool store_transpose_input=false)
Constructor.
Definition: operators.cpp:1892
std::array< dealii::Tensor< 1, dim, std::vector< real > >, n_faces > flux_nodes_surf
Stores the physical facet flux nodes.
Definition: operators.h:1228
"Stiffness" operator used in DG Strong form.
Definition: operators.h:1428
void sum_factorized_Hadamard_surface_basis_assembly(const unsigned int rows_size, const unsigned int columns_size_1D, const std::vector< unsigned int > &rows, const std::vector< unsigned int > &columns, const dealii::FullMatrix< double > &basis, const std::vector< double > &weights, dealii::FullMatrix< double > &basis_sparse, const int dim_not_zero)
Constructs the basis operator storing all non-zero entries for a "sum-factorized" surface Hadamard p...
Definition: operators.cpp:1135
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:1437
FR_mass_aux(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const Parameters::AllParameters::Flux_Reconstruction_Aux FR_param_input)
Constructor.
Definition: operators.cpp:2070
virtual void build_1D_volume_state_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2992
modal_basis_differential_operator(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:1480
void two_pt_flux_Hadamard_product(const dealii::FullMatrix< double > &input_mat, dealii::FullMatrix< double > &output_mat, const dealii::FullMatrix< double > &basis, const std::vector< double > &weights, const int direction)
Computes the Hadamard product ONLY for 2pt flux calculations.
Definition: operators.cpp:798
Operator base class.
Definition: operators.h:53
local_Flux_Reconstruction_operator(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const Parameters::AllParameters::Flux_Reconstruction FR_param_input, const double FR_user_specified_correction_parameter_value_input=0.0)
Constructor.
Definition: operators.cpp:1543
double FR_param_aux
Flux reconstruction paramater value.
Definition: operators.h:701
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1322
FR_mass_inv(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const Parameters::AllParameters::Flux_Reconstruction FR_param_input, const double FR_user_specified_correction_parameter_value_input=0.0)
Constructor.
Definition: operators.cpp:1975
local_basis_stiffness(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const bool store_skew_symmetric_form_input=false)
Constructor.
Definition: operators.cpp:1427
const Parameters::AllParameters::Flux_Reconstruction FR_param_type
Flux reconstruction parameter type.
Definition: operators.h:830
void get_spectral_difference_parameter(const unsigned int curr_cell_degree, double &c)
Evaluates the spectral difference parameter for flux reconstruction.
Definition: operators.cpp:1571
const double FR_user_specified_correction_parameter_value
User specified flux recontruction correction parameter value.
Definition: operators.h:833
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1990
face_integral_basis(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:2139
real1 norm(const dealii::Tensor< 1, dim, real1 > x)
Returns norm of dealii::Tensor<1,dim,real>
dealii::FullMatrix< double > tensor_product_state(const int nstate, const dealii::FullMatrix< double > &basis_x, const dealii::FullMatrix< double > &basis_y, const dealii::FullMatrix< double > &basis_z)
Returns the tensor product of matrices passed, but makes it sparse diagonal by state.
Definition: operators.cpp:106
void get_c_negative_divided_by_two_FR_parameter(const unsigned int curr_cell_degree, double &c)
Evaluates the flux reconstruction parameter at the bottom limit where the scheme is unstable...
Definition: operators.cpp:1593
void gradient_matrix_vector_mult_1D(const std::vector< real > &input_vect, dealii::Tensor< 1, dim, std::vector< real >> &output_vect, const dealii::FullMatrix< double > &basis, const dealii::FullMatrix< double > &gradient_basis)
Computes the gradient of a scalar using sum-factorization where the basis are the same in each direct...
Definition: operators.cpp:528
vol_projection_operator_FR_aux(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input, const Parameters::AllParameters::Flux_Reconstruction_Aux FR_param_input, const bool store_transpose_input=false)
Constructor.
Definition: operators.cpp:1934
void transform_physical_to_reference_vector(const dealii::Tensor< 1, dim, std::vector< real >> &phys, const dealii::Tensor< 2, dim, std::vector< real >> &metric_cofactor, dealii::Tensor< 1, dim, std::vector< real >> &ref)
Given a physical tensor of vector of points, return the reference tensor of vector.
Definition: operators.cpp:2383
codi_HessianComputationType RadFadType
Nested reverse-forward mode type for Jacobian and Hessian computation using TapeHelper.
Definition: ADTypes.hpp:28
const double FR_user_specified_correction_parameter_value
User specified flux recontruction correction parameter value.
Definition: operators.h:768
void build_1D_volume_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2021
void build_1D_surface_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 0 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1257
void build_1D_surface_state_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 0 > &face_quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:2955
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:1081
dealii::Tensor< 1, dim, std::vector< real > > flux_nodes_vol
Stores the physical volume flux nodes.
Definition: operators.h:1225
The surface integral of test functions.
Definition: operators.h:957
void build_1D_gradient_operator(const dealii::FESystem< 1, 1 > &finite_element, const dealii::Quadrature< 1 > &quadrature)
Assembles the one dimensional operator.
Definition: operators.cpp:1237
Projection operator corresponding to basis functions onto M-norm (L2).
Definition: operators.h:723
local_flux_basis_stiffness(const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:3060
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:582
dealii::FullMatrix< double > oneD_transpose_vol_operator
Stores the transpose of the operator for fast weight-adjusted solves.
Definition: operators.h:810
vol_integral_basis(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:1311
Local stiffness matrix without jacobian dependence.
Definition: operators.h:497
derivative_p(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:1509
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:1370
flux_basis_functions_state(const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:2982
OperatorsBase(const int nstate_input, const unsigned int max_degree_input, const unsigned int grid_degree_input)
Constructor.
Definition: operators.cpp:42
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:1402
unsigned int current_degree
Stores the degree of the current poly degree.
Definition: operators.h:695
void surface_two_pt_flux_Hadamard_product(const dealii::FullMatrix< double > &input_mat, std::vector< double > &output_vect_vol, std::vector< double > &output_vect_surf, const std::vector< double > &weights, const std::array< dealii::FullMatrix< double >, 2 > &surf_basis, const unsigned int iface, const unsigned int dim_not_zero, const double scaling=2.0)
Computes the surface cross Hadamard products for skew-symmetric form from Eq. (15) in Chan...
Definition: operators.cpp:718