[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
convection_diffusion.cpp
1 #include <boost/preprocessor/seq/for_each.hpp>
2 #include "ADTypes.hpp"
3 
4 #include "convection_diffusion.h"
5 
6 namespace PHiLiP {
7 namespace Physics {
8 
9 template <int nstate, typename real>
10 std::array<real,nstate> stdvector_to_stdarray(const std::vector<real> vector)
11 {
12  std::array<real,nstate> array;
13  for (int i=0; i<nstate; i++) { array[i] = vector[i]; }
14  return array;
15 }
16 
17 template <int dim, int nspecies, int nstate, typename real>
20  const int /*boundary_type*/,
21  const dealii::Point<dim, real> &pos,
22  const dealii::Tensor<1,dim,real> &normal_int,
23  const std::array<real,nstate> &soln_int,
24  const std::array<dealii::Tensor<1,dim,real>,nstate> &soln_grad_int,
25  std::array<real,nstate> &soln_bc,
26  std::array<dealii::Tensor<1,dim,real>,nstate> &soln_grad_bc) const
27 {
28  std::array<real,nstate> boundary_values;
29  std::array<dealii::Tensor<1,dim,real>,nstate> boundary_gradients;
30  for (int i=0; i<nstate; i++) {
31  boundary_values[i] = this->manufactured_solution_function->value (pos, i);
32  boundary_gradients[i] = this->manufactured_solution_function->gradient (pos, i);
33  }
34 
35  for (int istate=0; istate<nstate; ++istate) {
36 
37  std::array<real,nstate> characteristic_dot_n = convective_eigenvalues(boundary_values, normal_int);
38  const bool inflow = (characteristic_dot_n[istate] <= 0.);
39 
40  if (inflow || hasDiffusion) { // Dirichlet boundary condition
41  // soln_bc[istate] = boundary_values[istate];
42  // soln_grad_bc[istate] = soln_grad_int[istate];
43 
44  soln_bc[istate] = boundary_values[istate];
45  soln_grad_bc[istate] = soln_grad_int[istate];
46 
47  } else { // Neumann boundary condition
48  // //soln_bc[istate] = soln_int[istate];
49  // //soln_bc[istate] = boundary_values[istate];
50  // soln_bc[istate] = -soln_int[istate]+2*boundary_values[istate];
51  soln_bc[istate] = soln_int[istate];
52 
53  // **************************************************************************************************************
54  // Note I don't know how to properly impose the soln_grad_bc to obtain an adjoint consistent scheme
55  // Currently, Neumann boundary conditions are only imposed for the linear advection
56  // Therefore, soln_grad_bc does not affect the solution
57  // **************************************************************************************************************
58  soln_grad_bc[istate] = soln_grad_int[istate];
59  //soln_grad_bc[istate] = boundary_gradients[istate];
60  //soln_grad_bc[istate] = -soln_grad_int[istate]+2*boundary_gradients[istate];
61  }
62  }
63 }
64 
65 template <int dim, int nspecies, int nstate, typename real>
66 std::array<dealii::Tensor<1,dim,real>,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
67 ::convective_flux (const std::array<real,nstate> &solution) const
68 {
69  std::array<dealii::Tensor<1,dim,real>,nstate> conv_flux;
70  const dealii::Tensor<1,dim,real> velocity_field = advection_speed();
71  for (int i=0; i<nstate; ++i) {
72  conv_flux[i] = 0.0;
73  for (int d=0; d<dim; ++d) {
74  conv_flux[i][d] += velocity_field[d] * solution[i];
75  }
76  }
77  return conv_flux;
78 }
79 
80 template <int dim, int nspecies, int nstate, typename real>
81 std::array<dealii::Tensor<1,dim,real>,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
83  const std::array<real,nstate> &soln1,
84  const std::array<real,nstate> &soln2) const
85 {
86  std::array<real,nstate> arr_avg;
87  for (int i = 0 ; i < nstate; ++i) {
88  arr_avg[i] = (soln1[i] + soln2[i])/2.0;
89  }
90  return convective_flux(arr_avg);
91 }
92 
93 template <int dim, int nspecies, int nstate, typename real>
95 ::convert_conservative_to_primitive ( const std::array<real,nstate> &conservative_soln ) const
96 {
97  return conservative_soln;
98 }
99 
100 template <int dim, int nspecies, int nstate, typename real>
101 std::array<real,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
102 ::convert_primitive_to_conservative ( const std::array<real,nstate> &primitive_soln ) const
103 {
104  return primitive_soln;
105 }
106 
107 template <int dim, int nspecies, int nstate, typename real>
108 std::array<dealii::Tensor<1,dim,real>,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
110  const std::array<real,nstate> &/*primitive_soln*/,
111  const std::array<dealii::Tensor<1,dim,real>,nstate> &primitive_soln_gradient) const
112 {
113  return primitive_soln_gradient;
114 }
115 
116 template <int dim, int nspecies, int nstate, typename real>
117 std::array<dealii::Tensor<1,dim,real>,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
119  const std::array<real,nstate> &/*conservative_soln*/,
120  const std::array<dealii::Tensor<1,dim,real>,nstate> &conservative_soln_gradient) const
121 {
122  return conservative_soln_gradient;
123 }
124 
125 template <int dim, int nspecies, int nstate, typename real>
128  const std::array<real,nstate> &conservative_soln) const
129 {
130  return conservative_soln;
131 }
132 
133 template <int dim, int nspecies, int nstate, typename real>
136  const std::array<real,nstate> &entropy_var) const
137 {
138  return entropy_var;
139 }
140 
141 template <int dim, int nspecies, int nstate, typename real>
142 dealii::Tensor<1,dim,real> ConvectionDiffusion<dim,nspecies,nstate,real>
144 {
145  dealii::Tensor<1,dim,real> advection_speed;
146  if (hasConvection) {
147  if(dim >= 1) advection_speed[0] = linear_advection_velocity[0];
148  if(dim >= 2) advection_speed[1] = linear_advection_velocity[1];
149  if(dim >= 3) advection_speed[2] = linear_advection_velocity[2];
150  } else {
151  const real zero = 0.0;
152  if(dim >= 1) advection_speed[0] = zero;
153  if(dim >= 2) advection_speed[1] = zero;
154  if(dim >= 3) advection_speed[2] = zero;
155  }
156  return advection_speed;
157 }
158 
159 template <int dim, int nspecies, int nstate, typename real>
162 {
163  if(hasDiffusion) return diffusion_scaling_coeff;
164  const real zero = 0.0;
165  return zero;
166 }
167 
168 template <int dim, int nspecies, int nstate, typename real>
169 std::array<real,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
171  const std::array<real,nstate> &/*solution*/,
172  const dealii::Tensor<1,dim,real> &normal) const
173 {
174  std::array<real,nstate> eig;
175  const dealii::Tensor<1,dim,real> advection_speed = this->advection_speed();
176  real eig_value = 0.0;
177  for (int d=0; d<dim; ++d) {
178  eig_value += advection_speed[d]*normal[d];
179  }
180  for (int i=0; i<nstate; i++) {
181  eig[i] = eig_value;
182  }
183  return eig;
184 }
185 
186 template <int dim, int nspecies, int nstate, typename real>
188 ::max_convective_eigenvalue (const std::array<real,nstate> &/*soln*/) const
189 {
190  const dealii::Tensor<1,dim,real> advection_speed = this->advection_speed();
191  real max_eig = 0;
192  for (int i=0; i<dim; i++) {
193  real abs_adv = abs(advection_speed[i]);
194  max_eig = std::max(max_eig,abs_adv);
195  }
196  return max_eig;
197 }
198 
199 template <int dim, int nspecies, int nstate, typename real>
201 ::max_viscous_eigenvalue (const std::array<real,nstate> &/*soln*/) const
202 {
203  const real diff_coeff = this->diffusion_coefficient();
204  real max_eig = 0;
205  for (int i=0; i<dim; i++) {
206  for (int j=0; j<dim; j++) {
207  real abs_visc = abs(diff_coeff * this->diffusion_tensor[i][j]);
208  max_eig = std::max(max_eig,abs_visc);
209  }
210  }
211  return max_eig;
212 }
213 
214 template <int dim, int nspecies, int nstate, typename real>
215 std::array<dealii::Tensor<1,dim,real>,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
217  const std::array<real,nstate> &/*solution*/,
218  const std::array<dealii::Tensor<1,dim,real>,nstate> &solution_gradient) const
219 {
220  std::array<dealii::Tensor<1,dim,real>,nstate> diss_flux;
221  const real diff_coeff = diffusion_coefficient();
222  for (int i=0; i<nstate; i++) {
223  for (int d1=0; d1<dim; d1++) {
224  diss_flux[i][d1] = 0.0;
225  for (int d2=0; d2<dim; d2++) {
226  diss_flux[i][d1] += -diff_coeff*(this->diffusion_tensor[d1][d2]*solution_gradient[i][d2]);
227  }
228  }
229  }
230  return diss_flux;
231 }
232 
233 template <int dim, int nspecies, int nstate, typename real>
234 std::array<dealii::Tensor<1,dim,real>,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
236  const std::array<real,nstate> &solution,
237  const std::array<dealii::Tensor<1,dim,real>,nstate> &solution_gradient,
238  const dealii::types::global_dof_index /*cell_index*/) const
239 {
240  return dissipative_flux(solution, solution_gradient);
241 }
242 
243 template <int dim, int nspecies, int nstate, typename real>
244 std::array<real,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
246  const dealii::Point<dim,real> &pos,
247  const std::array<real,nstate> &solution,
248  const real current_time,
249  const dealii::types::global_dof_index /*cell_index*/) const
250 {
251  return source_term(pos,solution,current_time);
252 }
253 
254 template <int dim, int nspecies, int nstate, typename real>
255 std::array<real,nstate> ConvectionDiffusion<dim,nspecies,nstate,real>
257  const dealii::Point<dim,real> &pos,
258  const std::array<real,nstate> &/*solution*/,
259  const real current_time) const
260 {
261  std::array<real,nstate> source;
262  const dealii::Tensor<1,dim,real> velocity_field = this->advection_speed();
263  const real diff_coeff = diffusion_coefficient();
264 
265 
266  using TestType = Parameters::AllParameters::TestType;
267 
268  if(this->test_type == TestType::convection_diffusion_periodicity){
269  for(int istate =0; istate<nstate; istate++){
270  source[istate] = 0.0;
271  const double pi = atan(1)*4.0;
272  real sine_term = 1.0;
273  for(int idim=0; idim<dim; idim++){
274  sine_term *= sin(pi * pos[idim]);
275  }
276  source[istate] += (- diff_coeff) * exp(-diff_coeff * current_time) * sine_term;//the unsteady term
277  for(int idim=0; idim<dim; idim++){//laplacian term
278  source[istate] += diff_coeff * pow(pi,2) * exp(-diff_coeff * current_time)
279  * this->diffusion_tensor[idim][idim] * sine_term;
280  }
281  for(int idim=0; idim<dim; idim++){//cross terms
282  for(int jdim=0; jdim<dim; jdim++){
283  if(idim != jdim){
284  real cross_term = cos(pi*pos[idim]) * cos(pi*pos[jdim]);
285  if(dim == 3){
286  int kdim = 3 - idim - jdim;
287  cross_term *= sin(pi*pos[kdim]);
288  }
289  source[istate] += - diff_coeff * pow(pi,2) * exp(-diff_coeff * current_time)
290  * this->diffusion_tensor[idim][jdim] * cross_term;
291  }
292  }
293  }
294  }
295  }
296  else{
297  for (int istate=0; istate<nstate; istate++) {
298  dealii::Tensor<1,dim,real> manufactured_gradient = this->manufactured_solution_function->gradient (pos, istate);
299  // dealii::Tensor<1,dim,real> manufactured_gradient_fd = this->manufactured_solution_function.gradient_fd (pos, istate);
300  // std::cout<<"FD" <<std::endl;
301  // std::cout<<manufactured_gradient_fd <<std::endl;
302  // std::cout<<"AN" <<std::endl;
303  // std::cout<<manufactured_gradient <<std::endl;
304  // std::cout<<"DIFF" <<std::endl;
305  // std::cout<<manufactured_gradient - manufactured_gradient_fd <<std::endl;
306  dealii::SymmetricTensor<2,dim,real> manufactured_hessian = this->manufactured_solution_function->hessian (pos, istate);
307  // dealii::SymmetricTensor<2,dim,real> manufactured_hessian_fd = this->manufactured_solution_function.hessian_fd (pos, istate);
308  // std::cout<<"FD" <<std::endl;
309  // std::cout<<manufactured_hessian_fd <<std::endl;
310  // std::cout<<"AN" <<std::endl;
311  // std::cout<<manufactured_hessian <<std::endl;
312  // std::cout<<"DIFF" <<std::endl;
313  // std::cout<<manufactured_hessian - manufactured_hessian_fd <<std::endl;
314 
315  //source[istate] = velocity_field*manufactured_gradient;
316  real grad = 0.0;
317  for (int d=0; d<dim; ++d) {
318  grad += velocity_field[d] * manufactured_gradient[d];
319  }
320  source[istate] = grad;
321 
322  real hess = 0.0;
323  for (int dr=0; dr<dim; ++dr) {
324  for (int dc=0; dc<dim; ++dc) {
325  hess += (this->diffusion_tensor)[dr][dc] * manufactured_hessian[dr][dc];
326  }
327  }
328  source[istate] += -diff_coeff*hess;
329  }
330  }
331  return source;
332 }
333 
334 #if PHILIP_SPECIES==1
335  // Define a sequence of indices representing the range [1, 6]
336  #define POSSIBLE_NSTATE (1)(2)(3)(4)(5)(6)
337 
338  // Define a macro to instantiate Convection Diffusion Functions for a specific nstate
339  #define INSTANTIATE_CONVECTION_DIFFUSION(r, data, nstate) \
340  template class ConvectionDiffusion < PHILIP_DIM, PHILIP_SPECIES, nstate, double >; \
341  template class ConvectionDiffusion < PHILIP_DIM, PHILIP_SPECIES, nstate, FadType >; \
342  template class ConvectionDiffusion < PHILIP_DIM, PHILIP_SPECIES, nstate, RadType >; \
343  template class ConvectionDiffusion < PHILIP_DIM, PHILIP_SPECIES, nstate, FadFadType >; \
344  template class ConvectionDiffusion < PHILIP_DIM, PHILIP_SPECIES, nstate, RadFadType >;
345  BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_CONVECTION_DIFFUSION, _, POSSIBLE_NSTATE)
346 #endif
347 } // Physics namespace
348 } // PHiLiP namespace
349 
350 
std::array< real, nstate > compute_conservative_variables_from_entropy_variables(const std::array< real, nstate > &entropy_var) const
Computes the conservative variables from the entropy variables.
std::array< real, nstate > convert_primitive_to_conservative(const std::array< real, nstate > &primitive_soln) const
Convert primitive solution to conservative solution.
std::array< dealii::Tensor< 1, dim, real >, nstate > convert_primitive_gradient_to_conservative_gradient(const std::array< real, nstate > &primitive_soln, const std::array< dealii::Tensor< 1, dim, real >, nstate > &primitive_soln_gradient) const
TestType
Possible integration tests to run.
void boundary_face_values(const int, const dealii::Point< dim, real > &, const dealii::Tensor< 1, dim, real > &, const std::array< real, nstate > &, const std::array< dealii::Tensor< 1, dim, real >, nstate > &, std::array< real, nstate > &, std::array< dealii::Tensor< 1, dim, real >, nstate > &) const
If diffusion is present, assign Dirichlet boundary condition.
std::array< real, nstate > convective_eigenvalues(const std::array< real, nstate > &, const dealii::Tensor< 1, dim, real > &) const
Spectral radius of convective term Jacobian is &#39;c&#39;.
dealii::Tensor< 1, dim, real > advection_speed() const
Linear advection speed: c.
Files for the baseline physics.
Definition: ADTypes.hpp:10
std::array< real, nstate > compute_entropy_variables(const std::array< real, nstate > &conservative_soln) const
Computes the entropy variables.
std::array< dealii::Tensor< 1, dim, real >, nstate > convective_numerical_split_flux(const std::array< real, nstate > &soln1, const std::array< real, nstate > &soln2) const override
Convective numerical split flux for split form.
real max_viscous_eigenvalue(const std::array< real, nstate > &soln) const
Maximum viscous eigenvalue.
std::array< dealii::Tensor< 1, dim, real >, nstate > convert_conservative_gradient_to_primitive_gradient(const std::array< real, nstate > &conservative_soln, const std::array< dealii::Tensor< 1, dim, real >, nstate > &conservative_soln_gradient) const
std::array< real, nstate > convert_conservative_to_primitive(const std::array< real, nstate > &conservative_soln) const
Convert conservative variables to primitive variables.
real max_convective_eigenvalue(const std::array< real, nstate > &soln) const
Maximum convective eigenvalue.
std::array< real, nstate > source_term(const dealii::Point< dim, real > &pos, const std::array< real, nstate > &solution, const real current_time, const dealii::types::global_dof_index cell_index) const
Source term is zero or depends on manufactured solution.
std::array< dealii::Tensor< 1, dim, real >, nstate > dissipative_flux(const std::array< real, nstate > &solution, const std::array< dealii::Tensor< 1, dim, real >, nstate > &solution_gradient, const dealii::types::global_dof_index cell_index) const
Dissipative flux: u.
real diffusion_coefficient() const
Diffusion coefficient.
std::array< dealii::Tensor< 1, dim, real >, nstate > convective_flux(const std::array< real, nstate > &solution) const
Convective flux: .