2 #include "functional.h" 4 #include <deal.II/base/function.h> 5 #include <deal.II/base/symmetric_tensor.h> 6 #include <deal.II/differentiation/ad/sacado_math.h> 7 #include <deal.II/differentiation/ad/sacado_number_types.h> 8 #include <deal.II/differentiation/ad/sacado_product_types.h> 9 #include <deal.II/dofs/dof_tools.h> 10 #include <deal.II/fe/fe_q.h> 11 #include <deal.II/fe/fe_values.h> 12 #include <deal.II/lac/la_parallel_vector.h> 18 #include "dg/dg_base_state.hpp" 19 #include "lift_drag.hpp" 20 #include "physics/model.h" 21 #include "physics/model_factory.h" 22 #include "physics/physics.h" 23 #include "physics/physics_factory.h" 30 template<
int dim,
typename real1,
typename real2>
31 dealii::Tensor<1,dim,real1> vmult(
const dealii::Tensor<2,dim,real1> A,
const dealii::Tensor<1,dim,real2> x)
33 dealii::Tensor<1,dim,real1> y;
34 for (
int row=0;row<dim;++row) {
36 for (
int col=0;col<dim;++col) {
37 y[row] += A[row][col] * x[col];
48 template<
int dim,
typename real1>
49 real1 norm(
const dealii::Tensor<1,dim,real1> x)
52 for (
int row=0;row<dim;++row) {
53 val += x[row] * x[row];
60 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
61 FunctionalNormLpVolume<dim,nspecies,nstate,real,MeshType>::FunctionalNormLpVolume(
63 std::shared_ptr<DGBase<dim,nspecies,real,MeshType>> _dg,
64 const bool _uses_solution_values,
65 const bool _uses_solution_gradient) :
66 Functional<dim,nspecies,nstate,real,MeshType>::Functional(_dg, _uses_solution_values, _uses_solution_gradient),
69 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
70 template <
typename real2>
71 real2 FunctionalNormLpVolume<dim,nspecies,nstate,real,MeshType>::evaluate_volume_integrand(
73 const dealii::Point<dim,real2> & ,
74 const std::array<real2,nstate> & soln_at_q,
75 const std::array<dealii::Tensor<1,dim,real2>,nstate> &)
const 77 real2 lpnorm_value = 0;
78 for(
unsigned int istate = 0; istate < nstate; ++istate)
79 lpnorm_value += pow(abs(soln_at_q[istate]), this->normLp);
83 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
84 FunctionalNormLpBoundary<dim,nspecies,nstate,real,MeshType>::FunctionalNormLpBoundary(
86 std::vector<unsigned int> _boundary_vector,
87 const bool _use_all_boundaries,
88 std::shared_ptr<DGBase<dim,nspecies,real,MeshType>> _dg,
89 const bool _uses_solution_values,
90 const bool _uses_solution_gradient) :
91 Functional<dim,nspecies,nstate,real,MeshType>::Functional(_dg, _uses_solution_values, _uses_solution_gradient),
93 boundary_vector(_boundary_vector),
94 use_all_boundaries(_use_all_boundaries) {}
96 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
97 template <
typename real2>
98 real2 FunctionalNormLpBoundary<dim,nspecies,nstate,real,MeshType>::evaluate_boundary_integrand(
100 const unsigned int boundary_id,
101 const dealii::Point<dim,real2> & ,
102 const dealii::Tensor<1,dim,real2> & ,
103 const std::array<real2,nstate> & soln_at_q,
104 const std::array<dealii::Tensor<1,dim,real2>,nstate> &)
const 106 real2 lpnorm_value = 0;
109 auto boundary_vector_index = std::find(this->boundary_vector.begin(), this->boundary_vector.end(), boundary_id);
110 bool eval_boundary = this->use_all_boundaries || boundary_vector_index != this->boundary_vector.end();
115 for(
unsigned int istate = 0; istate < nstate; ++istate)
116 lpnorm_value += pow(abs(soln_at_q[istate]), this->normLp);
121 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
122 FunctionalWeightedIntegralVolume<dim,nspecies,nstate,real,MeshType>::FunctionalWeightedIntegralVolume(
123 std::shared_ptr<ManufacturedSolutionFunction<dim,nspecies,real>> _weight_function_double,
124 std::shared_ptr<ManufacturedSolutionFunction<dim,nspecies,FadFadType>> _weight_function_adtype,
125 const bool _use_weight_function_laplacian,
126 std::shared_ptr<DGBase<dim,nspecies,real,MeshType>> _dg,
127 const bool _uses_solution_values,
128 const bool _uses_solution_gradient) :
129 Functional<dim,nspecies,nstate,real,MeshType>::Functional(_dg, _uses_solution_values, _uses_solution_gradient),
130 weight_function_double(_weight_function_double),
131 weight_function_adtype(_weight_function_adtype),
132 use_weight_function_laplacian(_use_weight_function_laplacian) {}
134 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
135 template <
typename real2>
136 real2 FunctionalWeightedIntegralVolume<dim,nspecies,nstate,real,MeshType>::evaluate_volume_integrand(
138 const dealii::Point<dim,real2> & phys_coord,
139 const std::array<real2,nstate> & soln_at_q,
140 const std::array<dealii::Tensor<1,dim,real2>,nstate> & ,
141 std::shared_ptr<ManufacturedSolutionFunction<dim,nspecies,real2>> weight_function)
const 145 if(this->use_weight_function_laplacian){
146 for(
unsigned int istate = 0; istate < nstate; ++istate)
147 val += soln_at_q[istate] * dealii::trace(weight_function->hessian(phys_coord, istate));
149 for(
unsigned int istate = 0; istate < nstate; ++istate)
150 val += soln_at_q[istate] * weight_function->value(phys_coord, istate);
156 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
157 FunctionalWeightedIntegralBoundary<dim,nspecies,nstate,real,MeshType>::FunctionalWeightedIntegralBoundary(
158 std::shared_ptr<ManufacturedSolutionFunction<dim,nspecies,real>> _weight_function_double,
159 std::shared_ptr<ManufacturedSolutionFunction<dim,nspecies,FadFadType>> _weight_function_adtype,
160 const bool _use_weight_function_laplacian,
161 std::vector<unsigned int> _boundary_vector,
162 const bool _use_all_boundaries,
163 std::shared_ptr<DGBase<dim,nspecies,real,MeshType>> _dg,
164 const bool _uses_solution_values,
165 const bool _uses_solution_gradient) :
166 Functional<dim,nspecies,nstate,real,MeshType>::Functional(_dg, _uses_solution_values, _uses_solution_gradient),
167 weight_function_double(_weight_function_double),
168 weight_function_adtype(_weight_function_adtype),
169 use_weight_function_laplacian(_use_weight_function_laplacian),
170 boundary_vector(_boundary_vector),
171 use_all_boundaries(_use_all_boundaries) {}
173 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
174 template <
typename real2>
175 real2 FunctionalWeightedIntegralBoundary<dim,nspecies,nstate,real,MeshType>::evaluate_boundary_integrand(
177 const unsigned int boundary_id,
178 const dealii::Point<dim,real2> & phys_coord,
179 const dealii::Tensor<1,dim,real2> & ,
180 const std::array<real2,nstate> & soln_at_q,
181 const std::array<dealii::Tensor<1,dim,real2>,nstate> &,
182 std::shared_ptr<ManufacturedSolutionFunction<dim,nspecies,real2>> weight_function)
const 187 auto boundary_vector_index = std::find(this->boundary_vector.begin(), this->boundary_vector.end(), boundary_id);
188 bool eval_boundary = this->use_all_boundaries || boundary_vector_index != this->boundary_vector.end();
193 if(this->use_weight_function_laplacian){
194 for(
unsigned int istate = 0; istate < nstate; ++istate)
195 val += soln_at_q[istate] * dealii::trace(weight_function->hessian(phys_coord, istate));
197 for(
unsigned int istate = 0; istate < nstate; ++istate)
198 val += soln_at_q[istate] * weight_function->value(phys_coord, istate);
204 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
205 FunctionalErrorNormLpVolume<dim,nspecies,nstate,real,MeshType>::FunctionalErrorNormLpVolume(
206 const double _normLp,
207 std::shared_ptr<DGBase<dim,nspecies,real,MeshType>> _dg,
208 const bool _uses_solution_values,
209 const bool _uses_solution_gradient) :
210 Functional<dim,nspecies,nstate,real,MeshType>::Functional(_dg, _uses_solution_values, _uses_solution_gradient),
213 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
214 template <
typename real2>
215 real2 FunctionalErrorNormLpVolume<dim,nspecies,nstate,real,MeshType>::evaluate_volume_integrand(
217 const dealii::Point<dim,real2> & phys_coord,
218 const std::array<real2,nstate> & soln_at_q,
219 const std::array<dealii::Tensor<1,dim,real2>,nstate> &)
const 221 real2 lpnorm_value = 0;
222 for(
unsigned int istate = 0; istate < nstate; ++istate){
224 lpnorm_value += pow(abs(soln_at_q[istate] - uexact), this->normLp);
229 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
230 FunctionalErrorNormLpBoundary<dim,nspecies,nstate,real,MeshType>::FunctionalErrorNormLpBoundary(
231 const double _normLp,
232 std::vector<unsigned int> _boundary_vector,
233 const bool _use_all_boundaries,
234 std::shared_ptr<DGBase<dim,nspecies,real,MeshType>> _dg,
235 const bool _uses_solution_values,
236 const bool _uses_solution_gradient) :
237 Functional<dim,nspecies,nstate,real,MeshType>::Functional(_dg, _uses_solution_values, _uses_solution_gradient),
239 boundary_vector(_boundary_vector),
240 use_all_boundaries(_use_all_boundaries) {}
242 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
243 template <
typename real2>
244 real2 FunctionalErrorNormLpBoundary<dim,nspecies,nstate,real,MeshType>::evaluate_boundary_integrand(
246 const unsigned int boundary_id,
247 const dealii::Point<dim,real2> & phys_coord,
248 const dealii::Tensor<1,dim,real2> & ,
249 const std::array<real2,nstate> & soln_at_q,
250 const std::array<dealii::Tensor<1,dim,real2>,nstate> &)
const 252 real2 lpnorm_value = 0;
255 auto boundary_vector_index = std::find(this->boundary_vector.begin(), this->boundary_vector.end(), boundary_id);
256 bool eval_boundary = this->use_all_boundaries || boundary_vector_index != this->boundary_vector.end();
261 for(
int istate = 0; istate < nstate; ++istate){
263 lpnorm_value += pow(abs(soln_at_q[istate] - uexact), this->normLp);
270 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
271 template <
typename real2>
274 const dealii::Point<dim,real2> &,
275 const std::array<real2,nstate> &soln_at_q,
276 const std::array<dealii::Tensor<1,dim,real2>,nstate> &)
const 281 for (
int istate=0; istate<nstate; ++istate) {
282 val += soln_at_q[istate];
288 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
291 const bool uses_solution_values,
292 const bool uses_solution_gradient)
296 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
297 template <
typename real2>
300 const unsigned int boundary_id,
301 const dealii::Point<dim,real2> & ,
302 const dealii::Tensor<1,dim,real2> & ,
303 const std::array<real2,nstate> & soln_at_q,
304 const std::array<dealii::Tensor<1,dim,real2>,nstate> & )
const 308 if(boundary_id == 1002){
320 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
323 const bool _uses_solution_values,
324 const bool _uses_solution_gradient)
326 , d2IdWdW(std::make_shared<dealii::TrilinosWrappers::SparseMatrix>())
327 , d2IdWdX(std::make_shared<dealii::TrilinosWrappers::SparseMatrix>())
328 , d2IdXdX(std::make_shared<dealii::TrilinosWrappers::SparseMatrix>())
329 , uses_solution_values(_uses_solution_values)
330 , uses_solution_gradient(_uses_solution_gradient)
331 ,
pcout(std::cout, dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)==0)
333 using FadType = Sacado::Fad::DFad<real>;
334 using FadFadType = Sacado::Fad::DFad<FadType>;
340 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
343 solution_value.reinit(
dg->solution);
344 solution_value *= 0.0;
345 volume_nodes_value.reinit(
dg->high_order_grid->volume_nodes);
346 volume_nodes_value *= 0.0;
348 solution_dIdW.reinit(
dg->solution);
349 solution_dIdW *= 0.0;
350 volume_nodes_dIdW.reinit(
dg->high_order_grid->volume_nodes);
351 volume_nodes_dIdW *= 0.0;
353 solution_dIdX.reinit(
dg->solution);
354 solution_dIdX *= 0.0;
355 volume_nodes_dIdX.reinit(
dg->high_order_grid->volume_nodes);
356 volume_nodes_dIdX *= 0.0;
358 solution_d2I.reinit(
dg->solution);
360 volume_nodes_d2I.reinit(
dg->high_order_grid->volume_nodes);
361 volume_nodes_d2I *= 0.0;
364 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
368 const bool _uses_solution_values,
369 const bool _uses_solution_gradient)
370 :
Functional(_dg, _uses_solution_values, _uses_solution_gradient)
372 physics_fad_fad = _physics_fad_fad;
375 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
378 dg->solution = solution_set;
381 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
384 dg->high_order_grid->volume_nodes = volume_nodes_set;
387 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
391 dealii::IndexSet locally_owned_dofs = dg->high_order_grid->dof_handler_grid.locally_owned_dofs();
392 dealii::IndexSet locally_relevant_dofs, ghost_dofs;
393 dealii::DoFTools::extract_locally_relevant_dofs(dg->high_order_grid->dof_handler_grid, locally_relevant_dofs);
394 ghost_dofs = locally_relevant_dofs;
395 ghost_dofs.subtract_set(locally_owned_dofs);
396 dIdX.reinit(locally_owned_dofs, ghost_dofs, MPI_COMM_WORLD);
399 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
404 dealii::IndexSet locally_owned_dofs = dg->dof_handler.locally_owned_dofs();
405 dIdw.reinit(locally_owned_dofs, MPI_COMM_WORLD);
412 dealii::SparsityPattern sparsity_pattern_d2IdWdX = dg->get_d2RdWdX_sparsity_pattern ();
413 const dealii::IndexSet &row_parallel_partitioning_d2IdWdX = dg->locally_owned_dofs;
414 const dealii::IndexSet &col_parallel_partitioning_d2IdWdX = dg->high_order_grid->locally_owned_dofs_grid;
415 d2IdWdX->reinit(row_parallel_partitioning_d2IdWdX, col_parallel_partitioning_d2IdWdX, sparsity_pattern_d2IdWdX, MPI_COMM_WORLD);
419 dealii::SparsityPattern sparsity_pattern_d2IdWdW = dg->get_d2RdWdW_sparsity_pattern ();
420 const dealii::IndexSet &row_parallel_partitioning_d2IdWdW = dg->locally_owned_dofs;
421 const dealii::IndexSet &col_parallel_partitioning_d2IdWdW = dg->locally_owned_dofs;
422 d2IdWdW->reinit(row_parallel_partitioning_d2IdWdW, col_parallel_partitioning_d2IdWdW, sparsity_pattern_d2IdWdW, MPI_COMM_WORLD);
426 dealii::SparsityPattern sparsity_pattern_d2IdXdX = dg->get_d2RdXdX_sparsity_pattern ();
427 const dealii::IndexSet &row_parallel_partitioning_d2IdXdX = dg->high_order_grid->locally_owned_dofs_grid;
428 const dealii::IndexSet &col_parallel_partitioning_d2IdXdX = dg->high_order_grid->locally_owned_dofs_grid;
429 d2IdXdX->reinit(row_parallel_partitioning_d2IdXdX, col_parallel_partitioning_d2IdXdX, sparsity_pattern_d2IdXdX, MPI_COMM_WORLD);
435 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
437 const bool compute_dIdW,
const bool compute_dIdX,
const bool compute_d2I,
438 const Sacado::Fad::DFad<Sacado::Fad::DFad<real>> volume_local_sum,
439 std::vector<dealii::types::global_dof_index> cell_soln_dofs_indices,
440 std::vector<dealii::types::global_dof_index> cell_metric_dofs_indices)
442 using FadType = Sacado::Fad::DFad<real>;
444 const unsigned int n_total_indep = volume_local_sum.size();
445 (void) n_total_indep;
446 const unsigned int n_soln_dofs_cell = cell_soln_dofs_indices.size();
447 const unsigned int n_metric_dofs_cell = cell_metric_dofs_indices.size();
448 unsigned int i_derivative = 0;
451 std::vector<real> local_dIdw(n_soln_dofs_cell);
452 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof){
453 local_dIdw[idof] = volume_local_sum.dx(i_derivative++).val();
455 dIdw.add(cell_soln_dofs_indices, local_dIdw);
458 std::vector<real> local_dIdX(n_metric_dofs_cell);
459 for(
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof){
460 local_dIdX[idof] = volume_local_sum.dx(i_derivative++).val();
462 dIdX.add(cell_metric_dofs_indices, local_dIdX);
464 if (compute_dIdW || compute_dIdX) AssertDimension(i_derivative, n_total_indep);
466 std::vector<real> dWidW(n_soln_dofs_cell);
467 std::vector<real> dWidX(n_metric_dofs_cell);
468 std::vector<real> dXidX(n_metric_dofs_cell);
472 for (
unsigned int idof=0; idof<n_soln_dofs_cell; ++idof) {
474 unsigned int j_derivative = 0;
475 const FadType dWi = volume_local_sum.dx(i_derivative++);
477 for (
unsigned int jdof=0; jdof<n_soln_dofs_cell; ++jdof) {
478 dWidW[jdof] = dWi.dx(j_derivative++);
480 d2IdWdW->add(cell_soln_dofs_indices[idof], cell_soln_dofs_indices, dWidW);
482 for (
unsigned int jdof=0; jdof<n_metric_dofs_cell; ++jdof) {
483 dWidX[jdof] = dWi.dx(j_derivative++);
485 d2IdWdX->add(cell_soln_dofs_indices[idof], cell_metric_dofs_indices, dWidX);
488 for (
unsigned int idof=0; idof<n_metric_dofs_cell; ++idof) {
490 const FadType dXi = volume_local_sum.dx(i_derivative++);
492 unsigned int j_derivative = n_soln_dofs_cell;
493 for (
unsigned int jdof=0; jdof<n_metric_dofs_cell; ++jdof) {
494 dXidX[jdof] = dXi.dx(j_derivative++);
496 d2IdXdX->add(cell_metric_dofs_indices[idof], cell_metric_dofs_indices, dXidX);
499 AssertDimension(i_derivative, n_total_indep);
502 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
503 template <
typename real2>
506 const std::vector< real2 > &soln_coeff,
507 const dealii::FESystem<dim> &fe_solution,
508 const std::vector< real2 > &coords_coeff,
509 const dealii::FESystem<dim> &fe_metric,
510 const dealii::Quadrature<dim> &volume_quadrature)
const 512 const unsigned int n_vol_quad_pts = volume_quadrature.size();
513 const unsigned int n_soln_dofs_cell = soln_coeff.size();
514 const unsigned int n_metric_dofs_cell = coords_coeff.size();
516 real2 volume_local_sum = 0.0;
517 for (
unsigned int iquad=0; iquad<n_vol_quad_pts; ++iquad) {
519 const dealii::Point<dim,double> &ref_point = volume_quadrature.point(iquad);
520 const double quad_weight = volume_quadrature.weight(iquad);
524 dealii::Point<dim,real2> phys_coord;
525 for (
int d=0;d<dim;++d) { phys_coord[d] = 0.0;}
526 std::array< dealii::Tensor<1,dim,real2>, dim > coord_grad;
527 dealii::Tensor<2,dim,real2> metric_jacobian;
528 for (
unsigned int idof=0; idof<n_metric_dofs_cell; ++idof) {
529 const unsigned int axis = fe_metric.system_to_component_index(idof).first;
530 phys_coord[axis] += coords_coeff[idof] * fe_metric.shape_value(idof, ref_point);
531 coord_grad[axis] += coords_coeff[idof] * fe_metric.shape_grad (idof, ref_point);
533 for (
int row=0;row<dim;++row) {
534 for (
int col=0;col<dim;++col) {
535 metric_jacobian[row][col] = coord_grad[row][col];
538 const real2 jacobian_determinant = dealii::determinant(metric_jacobian);
539 dealii::Tensor<2,dim,real2> jacobian_transpose_inverse;
540 jacobian_transpose_inverse = dealii::transpose(dealii::invert(metric_jacobian));
543 std::array<real2, nstate> soln_at_q;
545 std::array< dealii::Tensor<1,dim,real2>, nstate > soln_grad_at_q;
546 for (
unsigned int idof=0; idof<n_soln_dofs_cell; ++idof) {
547 const unsigned int istate = fe_solution.system_to_component_index(idof).first;
548 if (uses_solution_values) {
549 soln_at_q[istate] += soln_coeff[idof] * fe_solution.shape_value(idof,ref_point);
551 if (uses_solution_gradient) {
552 const dealii::Tensor<1,dim,real2> phys_shape_grad = dealii::contract<1,0>(jacobian_transpose_inverse, fe_solution.shape_grad(idof,ref_point));
553 soln_grad_at_q[istate] += soln_coeff[idof] * phys_shape_grad;
556 real2 volume_integrand = this->evaluate_volume_integrand(physics, phys_coord, soln_at_q, soln_grad_at_q);
558 volume_local_sum += volume_integrand * jacobian_determinant * quad_weight;
560 return volume_local_sum;
563 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
564 template <
typename real2>
567 const unsigned int boundary_id,
568 const std::vector< real2 > &soln_coeff,
569 const dealii::FESystem<dim> &fe_solution,
570 const std::vector< real2 > &coords_coeff,
571 const dealii::FESystem<dim> &fe_metric,
572 const unsigned int face_number,
573 const dealii::Quadrature<dim-1> &fquadrature)
const 575 const unsigned int n_face_quad_pts = fquadrature.size();
576 const unsigned int n_soln_dofs_cell = soln_coeff.size();
577 const unsigned int n_metric_dofs_cell = coords_coeff.size();
579 const dealii::Quadrature<dim> face_quadrature = dealii::QProjector<dim>::project_to_face( dealii::ReferenceCell::get_hypercube(dim),
582 const dealii::Tensor<1,dim,real> surface_unit_normal = dealii::GeometryInfo<dim>::unit_normal_vector[face_number];
584 real2 boundary_local_sum = 0.0;
585 for (
unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
587 const dealii::Point<dim,double> &ref_point = face_quadrature.point(iquad);
588 const double quad_weight = face_quadrature.weight(iquad);
592 dealii::Point<dim,real2> phys_coord;
593 for (
int d=0;d<dim;++d) { phys_coord[d] = 0.0;}
594 std::array< dealii::Tensor<1,dim,real2>, dim > coord_grad;
595 dealii::Tensor<2,dim,real2> metric_jacobian;
596 for (
unsigned int idof=0; idof<n_metric_dofs_cell; ++idof) {
597 const unsigned int axis = fe_metric.system_to_component_index(idof).first;
598 phys_coord[axis] += coords_coeff[idof] * fe_metric.shape_value(idof, ref_point);
599 coord_grad[axis] += coords_coeff[idof] * fe_metric.shape_grad (idof, ref_point);
601 for (
int row=0;row<dim;++row) {
602 for (
int col=0;col<dim;++col) {
603 metric_jacobian[row][col] = coord_grad[row][col];
606 const real2 jacobian_determinant = dealii::determinant(metric_jacobian);
607 dealii::Tensor<2,dim,real2> jacobian_transpose_inverse;
608 jacobian_transpose_inverse = dealii::transpose(dealii::invert(metric_jacobian));
610 const dealii::Tensor<1,dim,real2> phys_normal = vmult(jacobian_transpose_inverse, surface_unit_normal);
611 const real2 area = norm(phys_normal);
612 const dealii::Tensor<1,dim,real2> phys_unit_normal = phys_normal/area;
614 real2 surface_jacobian_determinant = area*jacobian_determinant;
617 std::array<real2, nstate> soln_at_q;
619 std::array< dealii::Tensor<1,dim,real2>, nstate > soln_grad_at_q;
620 for (
unsigned int idof=0; idof<n_soln_dofs_cell; ++idof) {
621 const unsigned int istate = fe_solution.system_to_component_index(idof).first;
622 if (uses_solution_values) {
623 soln_at_q[istate] += soln_coeff[idof] * fe_solution.shape_value(idof,ref_point);
625 if (uses_solution_gradient) {
626 const dealii::Tensor<1,dim,real2> phys_shape_grad = dealii::contract<1,0>(jacobian_transpose_inverse, fe_solution.shape_grad(idof,ref_point));
627 soln_grad_at_q[istate] += soln_coeff[idof] * phys_shape_grad;
630 real2 boundary_integrand = this->evaluate_boundary_integrand(physics, boundary_id, phys_coord, phys_unit_normal, soln_at_q, soln_grad_at_q);
632 boundary_local_sum += boundary_integrand * surface_jacobian_determinant * quad_weight;
634 return boundary_local_sum;
637 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
640 const unsigned int boundary_id,
641 const std::vector< real > &soln_coeff,
642 const dealii::FESystem<dim> &fe_solution,
643 const std::vector< real > &coords_coeff,
644 const dealii::FESystem<dim> &fe_metric,
645 const unsigned int face_number,
646 const dealii::Quadrature<dim-1> &fquadrature)
const 648 return evaluate_boundary_cell_functional<real>(physics, boundary_id, soln_coeff, fe_solution, coords_coeff, fe_metric, face_number, fquadrature);
651 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
653 const Physics::PhysicsBase<dim,nspecies,nstate,Sacado::Fad::DFad<Sacado::Fad::DFad<real>>> &physics,
654 const unsigned int boundary_id,
655 const std::vector< Sacado::Fad::DFad<Sacado::Fad::DFad<real>> > &soln_coeff,
656 const dealii::FESystem<dim> &fe_solution,
657 const std::vector< Sacado::Fad::DFad<Sacado::Fad::DFad<real>> > &coords_coeff,
658 const dealii::FESystem<dim> &fe_metric,
659 const unsigned int face_number,
660 const dealii::Quadrature<dim-1> &fquadrature)
const 662 return evaluate_boundary_cell_functional<Sacado::Fad::DFad<Sacado::Fad::DFad<real>>>(physics, boundary_id, soln_coeff, fe_solution, coords_coeff, fe_metric, face_number, fquadrature);
665 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
668 const std::vector< real > &soln_coeff,
669 const dealii::FESystem<dim> &fe_solution,
670 const std::vector< real > &coords_coeff,
671 const dealii::FESystem<dim> &fe_metric,
672 const dealii::Quadrature<dim> &volume_quadrature)
const 674 return evaluate_volume_cell_functional<real>(physics, soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
677 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
679 const Physics::PhysicsBase<dim,nspecies,nstate,Sacado::Fad::DFad<Sacado::Fad::DFad<real>>> &physics_fad_fad,
680 const std::vector< Sacado::Fad::DFad<Sacado::Fad::DFad<real>> > &soln_coeff,
681 const dealii::FESystem<dim> &fe_solution,
682 const std::vector< Sacado::Fad::DFad<Sacado::Fad::DFad<real>> > &coords_coeff,
683 const dealii::FESystem<dim> &fe_metric,
684 const dealii::Quadrature<dim> &volume_quadrature)
const 686 return evaluate_volume_cell_functional<Sacado::Fad::DFad<Sacado::Fad::DFad<real>>>(physics_fad_fad, soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
689 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
694 if (dg->solution.size() == solution_value.size()
695 && dg->high_order_grid->volume_nodes.size() == volume_nodes_value.size()) {
697 auto diff_sol = dg->solution;
698 diff_sol -= solution_value;
699 const double l2_norm_sol = diff_sol.l2_norm();
701 if (l2_norm_sol == 0.0) {
703 auto diff_node = dg->high_order_grid->volume_nodes;
704 diff_node -= volume_nodes_value;
705 const double l2_norm_node = diff_node.l2_norm();
707 if (l2_norm_node == 0.0) {
708 pcout <<
" which is already assembled...";
709 compute_value =
false;
713 solution_value = dg->solution;
714 volume_nodes_value = dg->high_order_grid->volume_nodes;
717 pcout <<
" with dIdW...";
719 if (dg->solution.size() == solution_dIdW.size()
720 && dg->high_order_grid->volume_nodes.size() == volume_nodes_dIdW.size()) {
722 auto diff_sol = dg->solution;
723 diff_sol -= solution_dIdW;
724 const double l2_norm_sol = diff_sol.l2_norm();
726 if (l2_norm_sol == 0.0) {
728 auto diff_node = dg->high_order_grid->volume_nodes;
729 diff_node -= volume_nodes_dIdW;
730 const double l2_norm_node = diff_node.l2_norm();
732 if (l2_norm_node == 0.0) {
733 pcout <<
" which is already assembled...";
734 compute_dIdW =
false;
738 solution_dIdW = dg->solution;
739 volume_nodes_dIdW = dg->high_order_grid->volume_nodes;
742 pcout <<
" with dIdX...";
744 if (dg->solution.size() == solution_dIdX.size()
745 && dg->high_order_grid->volume_nodes.size() == volume_nodes_dIdX.size()) {
746 auto diff_sol = dg->solution;
747 diff_sol -= solution_dIdX;
748 const double l2_norm_sol = diff_sol.l2_norm();
750 if (l2_norm_sol == 0.0) {
752 auto diff_node = dg->high_order_grid->volume_nodes;
753 diff_node -= volume_nodes_dIdX;
754 const double l2_norm_node = diff_node.l2_norm();
756 if (l2_norm_node == 0.0) {
757 pcout <<
" which is already assembled...";
758 compute_dIdX =
false;
762 solution_dIdX = dg->solution;
763 volume_nodes_dIdX = dg->high_order_grid->volume_nodes;
766 pcout <<
" with d2IdWdW, d2IdWdX, d2IdXdX...";
768 if (dg->solution.size() == solution_d2I.size()
769 && dg->high_order_grid->volume_nodes.size() == volume_nodes_d2I.size()) {
771 auto diff_sol = dg->solution;
772 diff_sol -= solution_d2I;
773 const double l2_norm_sol = diff_sol.l2_norm();
775 if (l2_norm_sol == 0.0) {
777 auto diff_node = dg->high_order_grid->volume_nodes;
778 diff_node -= volume_nodes_d2I;
779 const double l2_norm_node = diff_node.l2_norm();
781 if (l2_norm_node == 0.0) {
783 pcout <<
" which is already assembled...";
788 solution_d2I = dg->solution;
789 volume_nodes_d2I = dg->high_order_grid->volume_nodes;
793 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
795 const bool compute_dIdW,
796 const bool compute_dIdX,
797 const bool compute_d2I)
799 using FadType = Sacado::Fad::DFad<real>;
800 using FadFadType = Sacado::Fad::DFad<FadType>;
802 bool actually_compute_value =
true;
803 bool actually_compute_dIdW = compute_dIdW;
804 bool actually_compute_dIdX = compute_dIdX;
805 bool actually_compute_d2I = compute_d2I;
808 need_compute(actually_compute_value, actually_compute_dIdW, actually_compute_dIdX, actually_compute_d2I);
811 if (!actually_compute_value && !actually_compute_dIdW && !actually_compute_dIdX && !actually_compute_d2I) {
812 return current_functional_value;
816 real local_functional = 0.0;
819 const dealii::FESystem<dim,dim> &fe_metric = dg->high_order_grid->fe_system;
820 const unsigned int n_metric_dofs_cell = fe_metric.dofs_per_cell;
821 std::vector<dealii::types::global_dof_index> cell_metric_dofs_indices(n_metric_dofs_cell);
824 const unsigned int max_dofs_per_cell = dg->dof_handler.get_fe_collection().max_dofs_per_cell();
825 std::vector<dealii::types::global_dof_index> cell_soln_dofs_indices(max_dofs_per_cell);
826 std::vector<FadFadType> soln_coeff(max_dofs_per_cell);
827 std::vector<real> local_dIdw(max_dofs_per_cell);
829 std::vector<real> local_dIdX(n_metric_dofs_cell);
831 const auto mapping = (*(dg->high_order_grid->mapping_fe_field));
832 dealii::hp::MappingCollection<dim> mapping_collection(mapping);
834 dealii::hp::FEFaceValues<dim,dim> fe_values_collection_face (mapping_collection, dg->fe_collection, dg->face_quadrature_collection, this->face_update_flags);
836 allocate_derivatives(actually_compute_dIdW, actually_compute_dIdX, actually_compute_d2I);
838 dg->solution.update_ghost_values();
839 auto metric_cell = dg->high_order_grid->dof_handler_grid.begin_active();
840 auto soln_cell = dg->dof_handler.begin_active();
841 for( ; soln_cell != dg->dof_handler.end(); ++soln_cell, ++metric_cell) {
842 if(!soln_cell->is_locally_owned())
continue;
846 const unsigned int i_fele = soln_cell->active_fe_index();
847 const unsigned int i_quad = i_fele;
850 const dealii::FESystem<dim,dim> &fe_solution = dg->fe_collection[i_fele];
851 const unsigned int n_soln_dofs_cell = fe_solution.n_dofs_per_cell();
852 cell_soln_dofs_indices.resize(n_soln_dofs_cell);
853 soln_cell->get_dof_indices(cell_soln_dofs_indices);
854 soln_coeff.resize(n_soln_dofs_cell);
857 metric_cell->get_dof_indices (cell_metric_dofs_indices);
858 std::vector< FadFadType > coords_coeff(n_metric_dofs_cell);
859 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
860 coords_coeff[idof] = dg->high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
864 unsigned int n_total_indep = 0;
865 if (actually_compute_dIdW || actually_compute_d2I) n_total_indep += n_soln_dofs_cell;
866 if (actually_compute_dIdX || actually_compute_d2I) n_total_indep += n_metric_dofs_cell;
867 unsigned int i_derivative = 0;
868 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof) {
869 const real val = dg->solution[cell_soln_dofs_indices[idof]];
870 soln_coeff[idof] = val;
871 if (actually_compute_dIdW || actually_compute_d2I) soln_coeff[idof].diff(i_derivative++, n_total_indep);
873 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
874 const real val = dg->high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
875 coords_coeff[idof] = val;
876 if (actually_compute_dIdX || actually_compute_d2I) coords_coeff[idof].diff(i_derivative++, n_total_indep);
878 AssertDimension(i_derivative, n_total_indep);
879 if (actually_compute_d2I) {
880 unsigned int i_derivative = 0;
881 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof) {
882 const real val = dg->solution[cell_soln_dofs_indices[idof]];
883 soln_coeff[idof].val() = val;
884 soln_coeff[idof].val().diff(i_derivative++, n_total_indep);
886 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
887 const real val = dg->high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
888 coords_coeff[idof].val() = val;
889 coords_coeff[idof].val().diff(i_derivative++, n_total_indep);
892 AssertDimension(i_derivative, n_total_indep);
895 const dealii::Quadrature<dim> &volume_quadrature = dg->volume_quadrature_collection[i_quad];
898 FadFadType volume_local_sum = evaluate_volume_cell_functional(*physics_fad_fad, soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
901 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
902 auto face = soln_cell->face(iface);
904 if(face->at_boundary()){
906 const unsigned int boundary_id = face->boundary_id();
911 volume_local_sum += this->evaluate_boundary_cell_functional(*physics_fad_fad, boundary_id, soln_coeff, fe_solution, coords_coeff, fe_metric, iface, dg->face_quadrature_collection[i_quad]);
916 local_functional += volume_local_sum.val().val();
920 if (actually_compute_dIdW) {
921 local_dIdw.resize(n_soln_dofs_cell);
922 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof){
923 local_dIdw[idof] = volume_local_sum.dx(i_derivative++).val();
925 dIdw.add(cell_soln_dofs_indices, local_dIdw);
927 if (actually_compute_dIdX) {
928 local_dIdX.resize(n_metric_dofs_cell);
929 for(
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof){
930 local_dIdX[idof] = volume_local_sum.dx(i_derivative++).val();
932 dIdX.add(cell_metric_dofs_indices, local_dIdX);
934 if (actually_compute_dIdW || actually_compute_dIdX) AssertDimension(i_derivative, n_total_indep);
935 if (actually_compute_d2I) {
936 std::vector<real> dWidW(n_soln_dofs_cell);
937 std::vector<real> dWidX(n_metric_dofs_cell);
938 std::vector<real> dXidX(n_metric_dofs_cell);
941 for (
unsigned int idof=0; idof<n_soln_dofs_cell; ++idof) {
942 unsigned int j_derivative = 0;
943 const FadType dWi = volume_local_sum.dx(i_derivative++);
944 for (
unsigned int jdof=0; jdof<n_soln_dofs_cell; ++jdof) {
945 dWidW[jdof] = dWi.dx(j_derivative++);
947 d2IdWdW->add(cell_soln_dofs_indices[idof], cell_soln_dofs_indices, dWidW);
949 for (
unsigned int jdof=0; jdof<n_metric_dofs_cell; ++jdof) {
950 dWidX[jdof] = dWi.dx(j_derivative++);
952 d2IdWdX->add(cell_soln_dofs_indices[idof], cell_metric_dofs_indices, dWidX);
955 for (
unsigned int idof=0; idof<n_metric_dofs_cell; ++idof) {
957 const FadType dXi = volume_local_sum.dx(i_derivative++);
959 unsigned int j_derivative = n_soln_dofs_cell;
960 for (
unsigned int jdof=0; jdof<n_metric_dofs_cell; ++jdof) {
961 dXidX[jdof] = dXi.dx(j_derivative++);
963 d2IdXdX->add(cell_metric_dofs_indices[idof], cell_metric_dofs_indices, dXidX);
966 AssertDimension(i_derivative, n_total_indep);
969 current_functional_value = dealii::Utilities::MPI::sum(local_functional, MPI_COMM_WORLD);
971 if (actually_compute_dIdW) dIdw.compress(dealii::VectorOperation::add);
972 if (actually_compute_dIdX) dIdX.compress(dealii::VectorOperation::add);
973 if (actually_compute_d2I) {
974 d2IdWdW->compress(dealii::VectorOperation::add);
975 d2IdWdX->compress(dealii::VectorOperation::add);
976 d2IdXdX->compress(dealii::VectorOperation::add);
979 return current_functional_value;
982 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
986 const double stepsize)
989 double local_sum_old;
990 double local_sum_new;
993 dealii::LinearAlgebra::distributed::Vector<real> dIdw;
996 dealii::IndexSet locally_owned_dofs = dg.
dof_handler.locally_owned_dofs();
997 dIdw.reinit(locally_owned_dofs, MPI_COMM_WORLD);
1000 const unsigned int max_dofs_per_cell = dg.
dof_handler.get_fe_collection().max_dofs_per_cell();
1001 std::vector<dealii::types::global_dof_index> cell_soln_dofs_indices(max_dofs_per_cell);
1002 std::vector<dealii::types::global_dof_index> neighbor_dofs_indices(max_dofs_per_cell);
1003 std::vector<real> soln_coeff(max_dofs_per_cell);
1004 std::vector<real> local_dIdw(max_dofs_per_cell);
1007 dealii::hp::MappingCollection<dim> mapping_collection(mapping);
1013 auto metric_cell = dg.
high_order_grid->dof_handler_grid.begin_active();
1015 for( ; cell != dg.
dof_handler.end(); ++cell, ++metric_cell) {
1016 if(!cell->is_locally_owned())
continue;
1019 const unsigned int i_mapp = 0;
1020 const unsigned int i_fele = cell->active_fe_index();
1021 const unsigned int i_quad = i_fele;
1024 const dealii::FESystem<dim,dim> &fe_solution = dg.
fe_collection[i_fele];
1025 const unsigned int n_soln_dofs_cell = fe_solution.n_dofs_per_cell();
1026 cell_soln_dofs_indices.resize(n_soln_dofs_cell);
1027 cell->get_dof_indices(cell_soln_dofs_indices);
1028 soln_coeff.resize(n_soln_dofs_cell);
1029 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof) {
1030 soln_coeff[idof] = dg.
solution[cell_soln_dofs_indices[idof]];
1034 const dealii::FESystem<dim,dim> &fe_metric = dg.
high_order_grid->fe_system;
1035 const unsigned int n_metric_dofs_cell = fe_metric.dofs_per_cell;
1036 std::vector<dealii::types::global_dof_index> cell_metric_dofs_indices(n_metric_dofs_cell);
1037 metric_cell->get_dof_indices (cell_metric_dofs_indices);
1038 std::vector<real> coords_coeff(n_metric_dofs_cell);
1039 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
1040 coords_coeff[idof] = dg.
high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
1047 local_sum_old = this->evaluate_volume_cell_functional(physics, soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
1050 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
1051 auto face = cell->face(iface);
1053 if(face->at_boundary()){
1054 fe_values_collection_face.reinit(cell, iface, i_quad, i_mapp, i_fele);
1056 const unsigned int boundary_id = face->boundary_id();
1060 local_sum_old += this->evaluate_boundary_cell_functional(physics, boundary_id, soln_coeff, fe_solution, coords_coeff, fe_metric, iface, dg.
face_quadrature_collection[i_quad]);
1066 local_dIdw.resize(n_soln_dofs_cell);
1067 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof){
1069 for(
unsigned int idof2 = 0; idof2 < n_soln_dofs_cell; ++idof2){
1070 soln_coeff[idof2] = dg.
solution[cell_soln_dofs_indices[idof2]];
1072 soln_coeff[idof] += stepsize;
1076 local_sum_new = this->evaluate_volume_cell_functional(physics, soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
1079 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
1080 auto face = cell->face(iface);
1082 if(face->at_boundary()){
1083 fe_values_collection_face.reinit(cell, iface, i_quad, i_mapp, i_fele);
1085 const unsigned int boundary_id = face->boundary_id();
1089 local_sum_new += this->evaluate_boundary_cell_functional(physics, boundary_id, soln_coeff, fe_solution, coords_coeff, fe_metric, iface, dg.
face_quadrature_collection[i_quad]);
1094 local_dIdw[idof] = (local_sum_new-local_sum_old)/stepsize;
1097 dIdw.add(cell_soln_dofs_indices, local_dIdw);
1100 dIdw.compress(dealii::VectorOperation::add);
1105 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
1109 const double stepsize)
1112 double local_sum_old;
1113 double local_sum_new;
1116 dealii::LinearAlgebra::distributed::Vector<real> dIdX_FD;
1117 allocate_dIdX(dIdX_FD);
1120 const unsigned int max_dofs_per_cell = dg.
dof_handler.get_fe_collection().max_dofs_per_cell();
1121 std::vector<dealii::types::global_dof_index> cell_soln_dofs_indices(max_dofs_per_cell);
1122 std::vector<dealii::types::global_dof_index> neighbor_dofs_indices(max_dofs_per_cell);
1123 std::vector<real> soln_coeff(max_dofs_per_cell);
1124 std::vector<real> local_dIdX(max_dofs_per_cell);
1127 dealii::hp::MappingCollection<dim> mapping_collection(mapping);
1133 auto metric_cell = dg.
high_order_grid->dof_handler_grid.begin_active();
1135 for( ; cell != dg.
dof_handler.end(); ++cell, ++metric_cell) {
1136 if(!cell->is_locally_owned())
continue;
1140 const unsigned int i_fele = cell->active_fe_index();
1141 const unsigned int i_quad = i_fele;
1144 const dealii::FESystem<dim,dim> &fe_solution = dg.
fe_collection[i_fele];
1145 const unsigned int n_soln_dofs_cell = fe_solution.n_dofs_per_cell();
1146 cell_soln_dofs_indices.resize(n_soln_dofs_cell);
1147 cell->get_dof_indices(cell_soln_dofs_indices);
1148 soln_coeff.resize(n_soln_dofs_cell);
1149 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof) {
1150 soln_coeff[idof] = dg.
solution[cell_soln_dofs_indices[idof]];
1154 const dealii::FESystem<dim,dim> &fe_metric = dg.
high_order_grid->fe_system;
1155 const unsigned int n_metric_dofs_cell = fe_metric.dofs_per_cell;
1156 std::vector<dealii::types::global_dof_index> cell_metric_dofs_indices(n_metric_dofs_cell);
1157 metric_cell->get_dof_indices (cell_metric_dofs_indices);
1158 std::vector<real> coords_coeff(n_metric_dofs_cell);
1159 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
1160 coords_coeff[idof] = dg.
high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
1167 local_sum_old = this->evaluate_volume_cell_functional(physics, soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
1170 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
1171 auto face = cell->face(iface);
1173 if(face->at_boundary()){
1175 const unsigned int boundary_id = face->boundary_id();
1180 local_sum_old += this->evaluate_boundary_cell_functional(physics, boundary_id, soln_coeff, fe_solution, coords_coeff, fe_metric, iface, dg.
face_quadrature_collection[i_quad]);
1186 local_dIdX.resize(n_metric_dofs_cell);
1187 for(
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof){
1189 for(
unsigned int idof2 = 0; idof2 < n_metric_dofs_cell; ++idof2){
1190 coords_coeff[idof2] = dg.
high_order_grid->volume_nodes[cell_metric_dofs_indices[idof2]];
1192 coords_coeff[idof] += stepsize;
1195 local_sum_new = this->evaluate_volume_cell_functional(physics, soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
1198 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
1199 auto face = cell->face(iface);
1201 if(face->at_boundary()){
1203 const unsigned int boundary_id = face->boundary_id();
1208 local_sum_new += this->evaluate_boundary_cell_functional(physics, boundary_id, soln_coeff, fe_solution, coords_coeff, fe_metric, iface, dg.
face_quadrature_collection[i_quad]);
1213 local_dIdX[idof] = (local_sum_new-local_sum_old)/stepsize;
1216 dIdX_FD.add(cell_metric_dofs_indices, local_dIdX);
1219 dIdX_FD.compress(dealii::VectorOperation::add);
1224 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
1225 std::shared_ptr< Functional<dim,nspecies,nstate,real,MeshType> >
1233 template <
int dim,
int nspecies,
int nstate,
typename real,
typename MeshType>
1234 std::shared_ptr< Functional<dim,nspecies,nstate,real,MeshType> >
1239 using FadFadType = Sacado::Fad::DFad<FadType>;
1246 std::shared_ptr< ManufacturedSolutionFunction<dim,nspecies,real> > weight_function_double
1248 std::shared_ptr< ManufacturedSolutionFunction<dim,nspecies,FadFadType> > weight_function_adtype
1253 if constexpr(nspecies==1) {
1254 const double normLp = param.
normLp;
1257 if(functional_type == FunctionalTypeEnum::normLp_volume){
1258 return std::make_shared<FunctionalNormLpVolume<dim,nspecies,nstate,real,MeshType>>(
1263 }
else if(functional_type == FunctionalTypeEnum::normLp_boundary){
1264 return std::make_shared<FunctionalNormLpBoundary<dim,nspecies,nstate,real,MeshType>>(
1271 }
else if(functional_type == FunctionalTypeEnum::weighted_integral_volume){
1272 return std::make_shared<FunctionalWeightedIntegralVolume<dim,nspecies,nstate,real,MeshType>>(
1273 weight_function_double,
1274 weight_function_adtype,
1275 use_weight_function_laplacian,
1279 }
else if(functional_type == FunctionalTypeEnum::weighted_integral_boundary){
1280 return std::make_shared<FunctionalWeightedIntegralBoundary<dim,nspecies,nstate,real,MeshType>>(
1281 weight_function_double,
1282 weight_function_adtype,
1283 use_weight_function_laplacian,
1289 }
else if(functional_type == FunctionalTypeEnum::error_normLp_volume){
1290 return std::make_shared<FunctionalErrorNormLpVolume<dim,nspecies,nstate,real,MeshType>>(
1295 }
else if(functional_type == FunctionalTypeEnum::error_normLp_boundary){
1296 return std::make_shared<FunctionalErrorNormLpBoundary<dim,nspecies,nstate,real,MeshType>>(
1303 }
else if(functional_type == FunctionalTypeEnum::lift){
1304 if constexpr(dim==2 &&
1306 std::is_same<MeshType, dealii::parallel::distributed::Triangulation<dim>>::value)
1308 return std::make_shared<LiftDragFunctional<dim,nspecies,nstate,real,MeshType>>(
1312 }
else if(functional_type == FunctionalTypeEnum::drag){
1313 if constexpr(dim==2 &&
1315 std::is_same<MeshType, dealii::parallel::distributed::Triangulation<dim>>::value)
1317 return std::make_shared<LiftDragFunctional<dim,nspecies,nstate,real,MeshType>>(
1321 }
else if(functional_type == FunctionalTypeEnum::solution_integral) {
1323 return std::make_shared<SolutionIntegral<dim,nspecies,nstate,real,MeshType>>(dg,dg_state->pde_physics_fad_fad,
true,
false);
1324 }
else if(functional_type == FunctionalTypeEnum::outlet_pressure_integral) {
1325 if constexpr (dim==2 && nstate==dim+2){
1326 return std::make_shared<OutletPressureIntegral<dim,nspecies,nstate,real,MeshType>>(dg,
true,
false);
1330 std::cout <<
"Invalid Functional." << std::endl;
1335 #if PHILIP_SPECIES==1 1337 #define POSSIBLE_NSTATE (1)(2)(3)(4)(5) 1339 #define INSTANTIATE_TRIA(r, data, nstate) \ 1340 template class FunctionalNormLpVolume <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::Triangulation<PHILIP_DIM>>; \ 1341 template class FunctionalNormLpBoundary <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::Triangulation<PHILIP_DIM>>; \ 1342 template class FunctionalWeightedIntegralVolume <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::Triangulation<PHILIP_DIM>>; \ 1343 template class FunctionalWeightedIntegralBoundary <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::Triangulation<PHILIP_DIM>>; \ 1344 template class FunctionalErrorNormLpVolume <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::Triangulation<PHILIP_DIM>>; \ 1345 template class FunctionalErrorNormLpBoundary <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::Triangulation<PHILIP_DIM>>; \ 1346 template class Functional <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::Triangulation<PHILIP_DIM>>; \ 1347 template class FunctionalFactory <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::Triangulation<PHILIP_DIM>>; \ 1348 template class SolutionIntegral<PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::Triangulation<PHILIP_DIM>>; \ 1350 template class FunctionalNormLpVolume <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::shared::Triangulation<PHILIP_DIM>>; \ 1351 template class FunctionalNormLpBoundary <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::shared::Triangulation<PHILIP_DIM>>; \ 1352 template class FunctionalWeightedIntegralVolume <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::shared::Triangulation<PHILIP_DIM>>; \ 1353 template class FunctionalWeightedIntegralBoundary <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::shared::Triangulation<PHILIP_DIM>>; \ 1354 template class FunctionalErrorNormLpVolume <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::shared::Triangulation<PHILIP_DIM>>; \ 1355 template class FunctionalErrorNormLpBoundary <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::shared::Triangulation<PHILIP_DIM>>; \ 1356 template class Functional <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::shared::Triangulation<PHILIP_DIM>>; \ 1357 template class FunctionalFactory <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::shared::Triangulation<PHILIP_DIM>>; \ 1358 template class SolutionIntegral<PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::shared::Triangulation<PHILIP_DIM>>; 1359 BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_TRIA, _, POSSIBLE_NSTATE)
1362 #define INSTANTIATE_DISTRIBUTED(r, data, nstate) \ 1363 template class FunctionalNormLpVolume <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::distributed::Triangulation<PHILIP_DIM>>; \ 1364 template class FunctionalNormLpBoundary <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::distributed::Triangulation<PHILIP_DIM>>; \ 1365 template class FunctionalWeightedIntegralVolume <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::distributed::Triangulation<PHILIP_DIM>>; \ 1366 template class FunctionalWeightedIntegralBoundary <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::distributed::Triangulation<PHILIP_DIM>>; \ 1367 template class FunctionalErrorNormLpVolume <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::distributed::Triangulation<PHILIP_DIM>>; \ 1368 template class FunctionalErrorNormLpBoundary <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::distributed::Triangulation<PHILIP_DIM>>; \ 1369 template class Functional <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::distributed::Triangulation<PHILIP_DIM>>; \ 1370 template class FunctionalFactory <PHILIP_DIM, PHILIP_SPECIES, nstate, double, dealii::parallel::distributed::Triangulation<PHILIP_DIM>>; 1372 BOOST_PP_SEQ_FOR_EACH(INSTANTIATE_DISTRIBUTED, _, POSSIBLE_NSTATE)
ManufacturedSolutionType
Selects the manufactured solution to be used if use_manufactured_source_term=true.
FunctionalType functional_type
Selection of functinal type.
Sacado::Fad::DFad< FadType > FadFadType
Sacado AD type that allows 2nd derivatives.
Base class from which Advection, Diffusion, ConvectionDiffusion, and Euler is derived.
FunctionalType
Choices for functional types to be used.
Functional(std::shared_ptr< PHiLiP::DGBase< dim, nspecies, real, MeshType >> _dg, const bool _uses_solution_values=true, const bool _uses_solution_gradient=true)
ManufacturedSolutionEnum weight_function_type
Choice of manufactured solution function to be used in weighting expression.
std::vector< unsigned int > boundary_vector
Boundary of vector ids to be considered for boundary functional evaluation.
dealii::hp::QCollection< dim-1 > face_quadrature_collection
Quadrature used to evaluate face integrals.
Files for the baseline physics.
bool use_all_boundaries
Flag for use of all domain boundaries.
GridRefinementStudyParam grid_refinement_study_param
Contains the parameters for grid refinement study.
Manufactured solution function factory.
std::shared_ptr< HighOrderGrid< dim, real, MeshType > > high_order_grid
High order grid that will provide the MappingFEField.
dealii::hp::QCollection< dim > volume_quadrature_collection
Finite Element Collection to represent the high-order grid.
std::shared_ptr< ManufacturedSolutionFunction< dim, nspecies, real > > manufactured_solution_function
Manufactured solution function.
real2 evaluate_boundary_integrand(const PHiLiP::Physics::PhysicsBase< dim, nspecies, nstate, real2 > &physics, const unsigned int boundary_id, const dealii::Point< dim, real2 > &phys_coord, const dealii::Tensor< 1, dim, real2 > &normal, const std::array< real2, nstate > &soln_at_q, const std::array< dealii::Tensor< 1, dim, real2 >, nstate > &soln_grad_at_q) const
Templated boundary integrand.
Main parameter class that contains the various other sub-parameter classes.
dealii::DoFHandler< dim > dof_handler
Finite Element Collection to represent the high-order grid.
Factory class to construct default functional types.
real compute_pressure(const std::array< real, nstate > &conservative_soln) const
Compute pressure from conservative solution.
double normLp
Choice of Lp norm exponent used in functional calculation.
FunctionalParam functional_param
Functional parameters to be used with grid refinement study.
Sacado::Fad::DFad< real > FadType
Sacado AD type for first derivatives.
Sacado::Fad::DFad< FadType > FadFadType
Sacado AD type that allows 2nd derivatives.
Euler equations. Derived from PhysicsBase.
bool use_weight_function_laplacian
Flag to use weight function laplacian.
real2 evaluate_volume_integrand(const PHiLiP::Physics::PhysicsBase< dim, nspecies, nstate, real2 > &physics, const dealii::Point< dim, real2 > &phys_coord, const std::array< real2, nstate > &soln_at_q, const std::array< dealii::Tensor< 1, dim, real2 >, nstate > &soln_grad_at_q) const
Templated volume integrand.
Parameterse related to the functional object.
std::shared_ptr< Physics::PhysicsBase< dim, nspecies, nstate, Sacado::Fad::DFad< real > > > physics
Problem physics (for calling the functional class)
dealii::LinearAlgebra::distributed::Vector< double > solution
Current modal coefficients of the solution.
Abstract class templated on the number of state variables.
static std::shared_ptr< PhysicsBase< dim, nspecies, nstate, real > > create_Physics(const Parameters::AllParameters *const parameters_input, std::shared_ptr< ModelBase< dim, nspecies, nstate, real > > model_input=nullptr)
Factory to return the correct physics given input file.
dealii::ConditionalOStream pcout
Parallel std::cout that only outputs on mpi_rank==0.
const dealii::hp::FECollection< dim > fe_collection
Finite Element Collection for p-finite-element to represent the solution.
DGBase is independent of the number of state variables.
static std::shared_ptr< ModelBase< dim, nspecies, nstate, real > > create_Model(const Parameters::AllParameters *const parameters_input)
Factory to return the correct model given input parameters.
std::shared_ptr< DGBase< dim, nspecies, real, MeshType > > dg
DG class pointer.