2 #include "target_functional.h" 4 #include <deal.II/base/qprojector.h> 5 #include <deal.II/differentiation/ad/sacado_math.h> 6 #include <deal.II/differentiation/ad/sacado_number_types.h> 7 #include <deal.II/differentiation/ad/sacado_product_types.h> 8 #include <deal.II/dofs/dof_tools.h> 9 #include <deal.II/fe/fe_q.h> 10 #include <deal.II/fe/fe_values.h> 11 #include <deal.II/lac/la_parallel_vector.h> 16 #include "dg/dg_base.hpp" 17 #include "physics/model.h" 18 #include "physics/model_factory.h" 19 #include "physics/physics.h" 20 #include "physics/physics_factory.h" 23 template<
int dim,
typename real1,
typename real2>
24 dealii::Tensor<1,dim,real1> vmult(
const dealii::Tensor<2,dim,real1> A,
const dealii::Tensor<1,dim,real2> x)
26 dealii::Tensor<1,dim,real1> y;
27 for (
int row=0;row<dim;++row) {
29 for (
int col=0;col<dim;++col) {
30 y[row] += A[row][col] * x[col];
40 template<
int dim,
typename real1>
41 real1
norm(
const dealii::Tensor<1,dim,real1> x)
44 for (
int row=0;row<dim;++row) {
45 val += x[row] * x[row];
50 template <
int dim,
int nstate,
typename real>
53 const bool _uses_solution_values,
54 const bool _uses_solution_gradient)
56 , target_solution(dg->solution)
58 using FadType = Sacado::Fad::DFad<real>;
63 template <
int dim,
int nstate,
typename real>
66 const dealii::LinearAlgebra::distributed::Vector<real> &
target_solution,
67 const bool _uses_solution_values,
68 const bool _uses_solution_gradient)
70 , target_solution(target_solution)
72 using FadType = Sacado::Fad::DFad<real>;
78 template <
int dim,
int nstate,
typename real>
81 std::shared_ptr<
Physics::PhysicsBase<dim,nstate,Sacado::Fad::DFad<Sacado::Fad::DFad<real>>> > _physics_fad_fad,
82 const bool _uses_solution_values,
83 const bool _uses_solution_gradient)
84 :
Functional<dim,nstate,real>::
Functional(_dg, _physics_fad_fad, _uses_solution_values, _uses_solution_gradient)
88 template <
int dim,
int nstate,
typename real>
91 const dealii::LinearAlgebra::distributed::Vector<real> &
target_solution,
92 std::shared_ptr<
Physics::PhysicsBase<dim,nstate,Sacado::Fad::DFad<Sacado::Fad::DFad<real>>> > _physics_fad_fad,
93 const bool _uses_solution_values,
94 const bool _uses_solution_gradient)
95 :
Functional<dim,nstate,real>::
Functional(_dg, _physics_fad_fad, _uses_solution_values, _uses_solution_gradient)
96 , target_solution(target_solution)
100 template <
int dim,
int nstate,
typename real>
101 template <
typename real2>
104 const std::vector< real2 > &soln_coeff,
105 const std::vector< real > &target_soln_coeff,
106 const dealii::FESystem<dim> &fe_solution,
107 const std::vector< real2 > &coords_coeff,
108 const dealii::FESystem<dim> &fe_metric,
109 const dealii::Quadrature<dim> &volume_quadrature)
const 111 const unsigned int n_vol_quad_pts = volume_quadrature.size();
112 const unsigned int n_soln_dofs_cell = soln_coeff.size();
113 const unsigned int n_metric_dofs_cell = coords_coeff.size();
115 real2 volume_local_sum = 0.0;
116 for (
unsigned int iquad=0; iquad<n_vol_quad_pts; ++iquad) {
118 const dealii::Point<dim,double> &ref_point = volume_quadrature.point(iquad);
119 const double quad_weight = volume_quadrature.weight(iquad);
123 dealii::Point<dim,real2> phys_coord;
124 for (
int d=0;d<dim;++d) { phys_coord[d] = 0.0;}
125 std::array< dealii::Tensor<1,dim,real2>, dim > coord_grad;
126 dealii::Tensor<2,dim,real2> metric_jacobian;
127 for (
unsigned int idof=0; idof<n_metric_dofs_cell; ++idof) {
128 const unsigned int axis = fe_metric.system_to_component_index(idof).first;
129 phys_coord[axis] += coords_coeff[idof] * fe_metric.shape_value(idof, ref_point);
130 coord_grad[axis] += coords_coeff[idof] * fe_metric.shape_grad (idof, ref_point);
132 for (
int row=0;row<dim;++row) {
133 for (
int col=0;col<dim;++col) {
134 metric_jacobian[row][col] = coord_grad[row][col];
137 const real2 jacobian_determinant = dealii::determinant(metric_jacobian);
138 dealii::Tensor<2,dim,real2> jacobian_transpose_inverse;
139 jacobian_transpose_inverse = dealii::transpose(dealii::invert(metric_jacobian));
142 std::array<real2, nstate> soln_at_q;
143 std::array<real, nstate> target_soln_at_q;
145 target_soln_at_q.fill(0.0);
146 std::array< dealii::Tensor<1,dim,real2>, nstate > soln_grad_at_q;
147 std::array< dealii::Tensor<1,dim,real2>, nstate > target_soln_grad_at_q;
148 for (
unsigned int idof=0; idof<n_soln_dofs_cell; ++idof) {
149 const unsigned int istate = fe_solution.system_to_component_index(idof).first;
151 soln_at_q[istate] += soln_coeff[idof] * fe_solution.shape_value(idof,ref_point);
152 target_soln_at_q[istate] += target_soln_coeff[idof] * fe_solution.shape_value(idof,ref_point);
155 const dealii::Tensor<1,dim,real2> phys_shape_grad = dealii::contract<1,0>(jacobian_transpose_inverse, fe_solution.shape_grad(idof,ref_point));
156 soln_grad_at_q[istate] += soln_coeff[idof] * phys_shape_grad;
157 target_soln_grad_at_q[istate] += target_soln_coeff[idof] * phys_shape_grad;
160 real2 volume_integrand =
evaluate_volume_integrand(physics, phys_coord, soln_at_q, target_soln_at_q, soln_grad_at_q, target_soln_grad_at_q);
162 (void) jacobian_determinant;
164 volume_local_sum += volume_integrand;
165 if (volume_local_sum != 0.0 && jacobian_determinant < 0) {
166 std::cout <<
"Bad jacobian... setting volume_local_sum *= 1e200" << std::endl;
167 volume_local_sum += 1e200;
170 return volume_local_sum;
173 template <
int dim,
int nstate,
typename real>
176 const std::vector< real > &soln_coeff,
177 const std::vector< real > &target_soln_coeff,
178 const dealii::FESystem<dim> &fe_solution,
179 const std::vector< real > &coords_coeff,
180 const dealii::FESystem<dim> &fe_metric,
181 const dealii::Quadrature<dim> &volume_quadrature)
const 183 return evaluate_volume_cell_functional<real>(physics, soln_coeff, target_soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
186 template <
int dim,
int nstate,
typename real>
189 const std::vector< Sacado::Fad::DFad<Sacado::Fad::DFad<real>> > &soln_coeff,
190 const std::vector< real > &target_soln_coeff,
191 const dealii::FESystem<dim> &fe_solution,
192 const std::vector< Sacado::Fad::DFad<Sacado::Fad::DFad<real>> > &coords_coeff,
193 const dealii::FESystem<dim> &fe_metric,
194 const dealii::Quadrature<dim> &volume_quadrature)
const 196 return evaluate_volume_cell_functional<Sacado::Fad::DFad<Sacado::Fad::DFad<real>>>(
physics_fad_fad, soln_coeff, target_soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
199 template <
int dim,
int nstate,
typename real>
200 template <
typename real2>
203 const unsigned int boundary_id,
204 const std::vector< real2 > &soln_coeff,
205 const std::vector< real > &target_soln_coeff,
206 const dealii::FESystem<dim> &fe_solution,
207 const std::vector< real2 > &coords_coeff,
208 const dealii::FESystem<dim> &fe_metric,
209 const dealii::Quadrature<dim-1> &fquadrature,
210 const unsigned int face_number)
const 212 const dealii::Quadrature<dim> face_quadrature = dealii::QProjector<dim>::project_to_face( dealii::ReferenceCell::get_hypercube(dim), fquadrature, face_number);
213 const dealii::Tensor<1,dim,real> ref_unit_normal = dealii::GeometryInfo<dim>::unit_normal_vector[face_number];
215 const unsigned int n_face_quad_pts = face_quadrature.size();
216 const unsigned int n_soln_dofs_cell = soln_coeff.size();
217 const unsigned int n_metric_dofs_cell = coords_coeff.size();
219 real2 face_local_sum = 0.0;
220 for (
unsigned int iquad=0; iquad<n_face_quad_pts; ++iquad) {
222 const dealii::Point<dim,double> &ref_point = face_quadrature.point(iquad);
223 const double quad_weight = face_quadrature.weight(iquad);
227 dealii::Point<dim,real2> phys_coord;
228 for (
int d=0;d<dim;++d) { phys_coord[d] = 0.0;}
229 std::array< dealii::Tensor<1,dim,real2>, dim > coord_grad;
230 dealii::Tensor<2,dim,real2> metric_jacobian;
231 for (
unsigned int idof=0; idof<n_metric_dofs_cell; ++idof) {
232 const unsigned int axis = fe_metric.system_to_component_index(idof).first;
233 phys_coord[axis] += coords_coeff[idof] * fe_metric.shape_value(idof, ref_point);
234 coord_grad[axis] += coords_coeff[idof] * fe_metric.shape_grad (idof, ref_point);
236 for (
int row=0;row<dim;++row) {
237 for (
int col=0;col<dim;++col) {
238 metric_jacobian[row][col] = coord_grad[row][col];
241 const real2 jacobian_determinant = dealii::determinant(metric_jacobian);
242 dealii::Tensor<2,dim,real2> jacobian_transpose_inverse;
243 jacobian_transpose_inverse = dealii::transpose(dealii::invert(metric_jacobian));
246 std::array<real2, nstate> soln_at_q;
247 std::array<real, nstate> target_soln_at_q;
249 target_soln_at_q.fill(0.0);
250 std::array< dealii::Tensor<1,dim,real2>, nstate > soln_grad_at_q;
251 std::array< dealii::Tensor<1,dim,real2>, nstate > target_soln_grad_at_q;
252 for (
unsigned int idof=0; idof<n_soln_dofs_cell; ++idof) {
253 const unsigned int istate = fe_solution.system_to_component_index(idof).first;
255 soln_at_q[istate] += soln_coeff[idof] * fe_solution.shape_value(idof,ref_point);
256 target_soln_at_q[istate] += target_soln_coeff[idof] * fe_solution.shape_value(idof,ref_point);
259 const dealii::Tensor<1,dim,real2> phys_shape_grad = dealii::contract<1,0>(jacobian_transpose_inverse, fe_solution.shape_grad(idof,ref_point));
260 soln_grad_at_q[istate] += soln_coeff[idof] * phys_shape_grad;
261 target_soln_grad_at_q[istate] += target_soln_coeff[idof] * phys_shape_grad;
265 const dealii::Tensor<1,dim,real2> phys_normal = vmult(jacobian_transpose_inverse, ref_unit_normal);
266 const real2 area =
norm(phys_normal);
267 const dealii::Tensor<1,dim,real2> phys_unit_normal = phys_normal/area;
268 real2 boundary_integrand =
evaluate_boundary_integrand(physics, boundary_id, phys_coord, phys_unit_normal, soln_at_q, target_soln_at_q, soln_grad_at_q, target_soln_grad_at_q);
270 real2 surface_jacobian_determinant = area*jacobian_determinant;
272 face_local_sum += boundary_integrand * surface_jacobian_determinant * quad_weight;
273 if (face_local_sum != 0.0 && jacobian_determinant < 0) {
274 std::cout <<
"Bad jacobian... setting face_local_sum *= 1e40" << std::endl;
275 face_local_sum += 1e40;
279 return face_local_sum;
282 template <
int dim,
int nstate,
typename real>
285 const unsigned int boundary_id,
286 const std::vector< real > &soln_coeff,
287 const std::vector< real > &target_soln_coeff,
288 const dealii::FESystem<dim> &fe_solution,
289 const std::vector< real > &coords_coeff,
290 const dealii::FESystem<dim> &fe_metric,
291 const dealii::Quadrature<dim-1> &face_quadrature,
292 const unsigned int face_number)
const 294 return evaluate_boundary_cell_functional<real>(physics, boundary_id, soln_coeff, target_soln_coeff, fe_solution, coords_coeff, fe_metric, face_quadrature, face_number);
297 template <
int dim,
int nstate,
typename real>
300 const unsigned int boundary_id,
301 const std::vector< Sacado::Fad::DFad<Sacado::Fad::DFad<real>> > &soln_coeff,
302 const std::vector< real > &target_soln_coeff,
303 const dealii::FESystem<dim> &fe_solution,
304 const std::vector< Sacado::Fad::DFad<Sacado::Fad::DFad<real>> > &coords_coeff,
305 const dealii::FESystem<dim> &fe_metric,
306 const dealii::Quadrature<dim-1> &face_quadrature,
307 const unsigned int face_number)
const 309 return evaluate_boundary_cell_functional<Sacado::Fad::DFad<Sacado::Fad::DFad<real>>>(
physics_fad_fad, boundary_id, soln_coeff, target_soln_coeff, fe_solution, coords_coeff, fe_metric, face_quadrature, face_number);
312 template <
int dim,
int nstate,
typename real>
314 const bool compute_dIdW,
315 const bool compute_dIdX,
316 const bool compute_d2I)
318 using FadType = Sacado::Fad::DFad<real>;
319 using FadFadType = Sacado::Fad::DFad<FadType>;
321 bool actually_compute_value =
true;
322 bool actually_compute_dIdW = compute_dIdW;
323 bool actually_compute_dIdX = compute_dIdX;
324 bool actually_compute_d2I = compute_d2I;
329 if (!actually_compute_value && !actually_compute_dIdW && !actually_compute_dIdX && !actually_compute_d2I) {
334 const dealii::FESystem<dim,dim> &fe_metric =
dg->high_order_grid->fe_system;
335 const unsigned int n_metric_dofs_cell = fe_metric.dofs_per_cell;
336 std::vector<dealii::types::global_dof_index> cell_metric_dofs_indices(n_metric_dofs_cell);
339 const unsigned int max_dofs_per_cell =
dg->dof_handler.get_fe_collection().max_dofs_per_cell();
340 std::vector<dealii::types::global_dof_index> cell_soln_dofs_indices(max_dofs_per_cell);
341 std::vector<FadFadType> soln_coeff(max_dofs_per_cell);
342 std::vector<real> target_soln_coeff(max_dofs_per_cell);
343 std::vector<real> local_dIdw(max_dofs_per_cell);
345 std::vector<real> local_dIdX(n_metric_dofs_cell);
347 const auto mapping = (*(
dg->high_order_grid->mapping_fe_field));
348 dealii::hp::MappingCollection<dim> mapping_collection(mapping);
350 dealii::hp::FEFaceValues<dim,dim> fe_values_collection_face (mapping_collection,
dg->fe_collection,
dg->face_quadrature_collection, this->face_update_flags);
354 dg->solution.update_ghost_values();
355 auto metric_cell =
dg->high_order_grid->dof_handler_grid.begin_active();
356 auto soln_cell =
dg->dof_handler.begin_active();
358 real local_functional = 0.0;
360 for( ; soln_cell !=
dg->dof_handler.end(); ++soln_cell, ++metric_cell) {
361 if(!soln_cell->is_locally_owned())
continue;
364 const unsigned int i_mapp = 0;
365 const unsigned int i_fele = soln_cell->active_fe_index();
366 const unsigned int i_quad = i_fele;
370 const dealii::FESystem<dim,dim> &fe_solution =
dg->fe_collection[i_fele];
371 const unsigned int n_soln_dofs_cell = fe_solution.n_dofs_per_cell();
372 cell_soln_dofs_indices.resize(n_soln_dofs_cell);
373 soln_cell->get_dof_indices(cell_soln_dofs_indices);
374 soln_coeff.resize(n_soln_dofs_cell);
375 target_soln_coeff.resize(n_soln_dofs_cell);
378 metric_cell->get_dof_indices (cell_metric_dofs_indices);
379 std::vector< FadFadType > coords_coeff(n_metric_dofs_cell);
380 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
381 coords_coeff[idof] =
dg->high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
385 unsigned int n_total_indep = 0;
386 if (actually_compute_dIdW || actually_compute_d2I) n_total_indep += n_soln_dofs_cell;
387 if (actually_compute_dIdX || actually_compute_d2I) n_total_indep += n_metric_dofs_cell;
388 unsigned int i_derivative = 0;
389 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof) {
390 const real val =
dg->solution[cell_soln_dofs_indices[idof]];
391 soln_coeff[idof] = val;
392 if (actually_compute_dIdW || actually_compute_d2I) soln_coeff[idof].diff(i_derivative++, n_total_indep);
394 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof) {
396 target_soln_coeff[idof] = val;
398 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
399 const real val =
dg->high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
400 coords_coeff[idof] = val;
401 if (actually_compute_dIdX || actually_compute_d2I) coords_coeff[idof].diff(i_derivative++, n_total_indep);
403 AssertDimension(i_derivative, n_total_indep);
404 if (actually_compute_d2I) {
405 unsigned int i_derivative = 0;
406 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof) {
407 const real val =
dg->solution[cell_soln_dofs_indices[idof]];
408 soln_coeff[idof].val() = val;
409 soln_coeff[idof].val().diff(i_derivative++, n_total_indep);
411 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
412 const real val =
dg->high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
413 coords_coeff[idof].val() = val;
414 coords_coeff[idof].val().diff(i_derivative++, n_total_indep);
417 AssertDimension(i_derivative, n_total_indep);
420 const dealii::Quadrature<dim> &volume_quadrature =
dg->volume_quadrature_collection[i_quad];
424 volume_local_sum.resizeAndZero(n_total_indep);
430 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
431 auto face = soln_cell->face(iface);
433 if(face->at_boundary()){
435 const unsigned int boundary_id = face->boundary_id();
442 local_functional += volume_local_sum.val().val();
445 this->
set_derivatives(actually_compute_dIdW, actually_compute_dIdX, actually_compute_d2I, volume_local_sum, cell_soln_dofs_indices, cell_metric_dofs_indices);
451 if (actually_compute_dIdW)
dIdw.compress(dealii::VectorOperation::add);
452 if (actually_compute_dIdX)
dIdX.compress(dealii::VectorOperation::add);
453 if (actually_compute_d2I) {
454 d2IdWdW->compress(dealii::VectorOperation::add);
455 d2IdWdX->compress(dealii::VectorOperation::add);
456 d2IdXdX->compress(dealii::VectorOperation::add);
462 template <
int dim,
int nstate,
typename real>
466 const double stepsize)
469 double local_sum_old;
470 double local_sum_new;
473 dealii::LinearAlgebra::distributed::Vector<real>
dIdw;
476 dealii::IndexSet locally_owned_dofs = dg.
dof_handler.locally_owned_dofs();
477 dIdw.reinit(locally_owned_dofs, MPI_COMM_WORLD);
480 const unsigned int max_dofs_per_cell = dg.
dof_handler.get_fe_collection().max_dofs_per_cell();
481 std::vector<dealii::types::global_dof_index> cell_soln_dofs_indices(max_dofs_per_cell);
482 std::vector<dealii::types::global_dof_index> neighbor_dofs_indices(max_dofs_per_cell);
483 std::vector<real> soln_coeff(max_dofs_per_cell);
484 std::vector<real> target_soln_coeff(max_dofs_per_cell);
485 std::vector<real> local_dIdw(max_dofs_per_cell);
488 dealii::hp::MappingCollection<dim> mapping_collection(mapping);
494 auto metric_cell = dg.
high_order_grid->dof_handler_grid.begin_active();
496 for( ; cell != dg.
dof_handler.end(); ++cell, ++metric_cell) {
497 if(!cell->is_locally_owned())
continue;
500 const unsigned int i_mapp = 0;
501 const unsigned int i_fele = cell->active_fe_index();
502 const unsigned int i_quad = i_fele;
506 const dealii::FESystem<dim,dim> &fe_solution = dg.
fe_collection[i_fele];
507 const unsigned int n_soln_dofs_cell = fe_solution.n_dofs_per_cell();
508 cell_soln_dofs_indices.resize(n_soln_dofs_cell);
509 cell->get_dof_indices(cell_soln_dofs_indices);
510 soln_coeff.resize(n_soln_dofs_cell);
511 target_soln_coeff.resize(n_soln_dofs_cell);
512 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof) {
513 soln_coeff[idof] = dg.
solution[cell_soln_dofs_indices[idof]];
514 target_soln_coeff[idof] =
target_solution[cell_soln_dofs_indices[idof]];
518 const dealii::FESystem<dim,dim> &fe_metric = dg.
high_order_grid->fe_system;
519 const unsigned int n_metric_dofs_cell = fe_metric.dofs_per_cell;
520 std::vector<dealii::types::global_dof_index> cell_metric_dofs_indices(n_metric_dofs_cell);
521 metric_cell->get_dof_indices (cell_metric_dofs_indices);
522 std::vector<real> coords_coeff(n_metric_dofs_cell);
523 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
524 coords_coeff[idof] = dg.
high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
531 local_sum_old = this->
evaluate_volume_cell_functional(physics, soln_coeff, target_soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
534 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
535 auto face = cell->face(iface);
537 if(face->at_boundary()){
538 const unsigned int boundary_id = face->boundary_id();
545 local_dIdw.resize(n_soln_dofs_cell);
546 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof){
548 for(
unsigned int idof2 = 0; idof2 < n_soln_dofs_cell; ++idof2){
549 soln_coeff[idof2] = dg.
solution[cell_soln_dofs_indices[idof2]];
551 soln_coeff[idof] += stepsize;
555 local_sum_new = this->
evaluate_volume_cell_functional(physics, soln_coeff, target_soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
558 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
559 auto face = cell->face(iface);
561 if(face->at_boundary()){
562 const unsigned int boundary_id = face->boundary_id();
568 local_dIdw[idof] = (local_sum_new-local_sum_old)/stepsize;
571 dIdw.add(cell_soln_dofs_indices, local_dIdw);
574 dIdw.compress(dealii::VectorOperation::add);
579 template <
int dim,
int nstate,
typename real>
583 const double stepsize)
586 double local_sum_old;
587 double local_sum_new;
590 dealii::LinearAlgebra::distributed::Vector<real> dIdX_FD;
594 const unsigned int max_dofs_per_cell = dg.
dof_handler.get_fe_collection().max_dofs_per_cell();
595 std::vector<dealii::types::global_dof_index> cell_soln_dofs_indices(max_dofs_per_cell);
596 std::vector<dealii::types::global_dof_index> neighbor_dofs_indices(max_dofs_per_cell);
597 std::vector<real> soln_coeff(max_dofs_per_cell);
598 std::vector<real> target_soln_coeff(max_dofs_per_cell);
599 std::vector<real> local_dIdX(max_dofs_per_cell);
602 dealii::hp::MappingCollection<dim> mapping_collection(mapping);
608 auto metric_cell = dg.
high_order_grid->dof_handler_grid.begin_active();
610 for( ; cell != dg.
dof_handler.end(); ++cell, ++metric_cell) {
611 if(!cell->is_locally_owned())
continue;
614 const unsigned int i_mapp = 0;
615 const unsigned int i_fele = cell->active_fe_index();
616 const unsigned int i_quad = i_fele;
620 const dealii::FESystem<dim,dim> &fe_solution = dg.
fe_collection[i_fele];
621 const unsigned int n_soln_dofs_cell = fe_solution.n_dofs_per_cell();
622 cell_soln_dofs_indices.resize(n_soln_dofs_cell);
623 cell->get_dof_indices(cell_soln_dofs_indices);
624 soln_coeff.resize(n_soln_dofs_cell);
625 target_soln_coeff.resize(n_soln_dofs_cell);
626 for(
unsigned int idof = 0; idof < n_soln_dofs_cell; ++idof) {
627 soln_coeff[idof] = dg.
solution[cell_soln_dofs_indices[idof]];
628 target_soln_coeff[idof] =
target_solution[cell_soln_dofs_indices[idof]];
632 const dealii::FESystem<dim,dim> &fe_metric = dg.
high_order_grid->fe_system;
633 const unsigned int n_metric_dofs_cell = fe_metric.dofs_per_cell;
634 std::vector<dealii::types::global_dof_index> cell_metric_dofs_indices(n_metric_dofs_cell);
635 metric_cell->get_dof_indices (cell_metric_dofs_indices);
636 std::vector<real> coords_coeff(n_metric_dofs_cell);
637 for (
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof) {
638 coords_coeff[idof] = dg.
high_order_grid->volume_nodes[cell_metric_dofs_indices[idof]];
645 local_sum_old = this->
evaluate_volume_cell_functional(physics, soln_coeff, target_soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
648 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
649 auto face = cell->face(iface);
651 if(face->at_boundary()){
652 const unsigned int boundary_id = face->boundary_id();
659 local_dIdX.resize(n_metric_dofs_cell);
660 for(
unsigned int idof = 0; idof < n_metric_dofs_cell; ++idof){
662 for(
unsigned int idof2 = 0; idof2 < n_metric_dofs_cell; ++idof2){
663 coords_coeff[idof2] = dg.
high_order_grid->volume_nodes[cell_metric_dofs_indices[idof2]];
665 coords_coeff[idof] += stepsize;
668 local_sum_new = this->
evaluate_volume_cell_functional(physics, soln_coeff, target_soln_coeff, fe_solution, coords_coeff, fe_metric, volume_quadrature);
671 for(
unsigned int iface = 0; iface < dealii::GeometryInfo<dim>::faces_per_cell; ++iface){
672 auto face = cell->face(iface);
674 if(face->at_boundary()){
675 const unsigned int boundary_id = face->boundary_id();
681 local_dIdX[idof] = (local_sum_new-local_sum_old)/stepsize;
684 dIdX_FD.add(cell_metric_dofs_indices, local_dIdX);
687 dIdX_FD.compress(dealii::VectorOperation::add);
std::shared_ptr< dealii::TrilinosWrappers::SparseMatrix > d2IdXdX
Sparse matrix for storing the functional partial second derivatives.
const bool uses_solution_gradient
Will evaluate solution gradient at quadrature points.
dealii::LinearAlgebra::distributed::Vector< real > dIdX
Vector for storing the derivatives with respect to each grid DoF.
TargetFunctional base class.
const bool uses_solution_values
Will evaluate solution values at quadrature points.
dealii::LinearAlgebra::distributed::Vector< real > dIdw
Vector for storing the derivatives with respect to each solution DoF.
Base class from which Advection, Diffusion, ConvectionDiffusion, and Euler is derived.
virtual real evaluate_boundary_integrand(const PHiLiP::Physics::PhysicsBase< dim, nstate, real > &, const unsigned int, const dealii::Point< dim, real > &, const dealii::Tensor< 1, dim, real > &, const std::array< real, nstate > &soln_at_q, const std::array< real, nstate > &target_soln_at_q, const std::array< dealii::Tensor< 1, dim, real >, nstate > &, const std::array< dealii::Tensor< 1, dim, real >, nstate > &) const
Virtual function for computation of cell face functional term.
std::shared_ptr< dealii::TrilinosWrappers::SparseMatrix > d2IdWdW
Sparse matrix for storing the functional partial second derivatives.
dealii::LinearAlgebra::distributed::Vector< real > evaluate_dIdX_finiteDifferences(DGBase< dim, real > &dg, const PHiLiP::Physics::PhysicsBase< dim, nstate, real > &physics, const double stepsize)
virtual real evaluate_volume_integrand(const PHiLiP::Physics::PhysicsBase< dim, nstate, real > &, const dealii::Point< dim, real > &, const std::array< real, nstate > &soln_at_q, const std::array< real, nstate > &target_soln_at_q, const std::array< dealii::Tensor< 1, dim, real >, nstate > &, const std::array< dealii::Tensor< 1, dim, real >, nstate > &) const
Virtual function for computation of cell volume functional term.
Files for the baseline physics.
virtual real evaluate_functional(const bool compute_dIdW=false, const bool compute_dIdX=false, const bool compute_d2I=false) override
Evaluates the functional derivative with respect to the solution variable.
real2 evaluate_boundary_cell_functional(const Physics::PhysicsBase< dim, nstate, real2 > &physics, const unsigned int boundary_id, const std::vector< real2 > &soln_coeff, const std::vector< real > &target_soln_coeff, const dealii::FESystem< dim > &fe_solution, const std::vector< real2 > &coords_coeff, const dealii::FESystem< dim > &fe_metric, const dealii::Quadrature< dim-1 > &face_quadrature, const unsigned int face_number) const
Templated function to evaluate a cell's face functional.
void allocate_dIdX(dealii::LinearAlgebra::distributed::Vector< real > &dIdX) const
Allocate and setup the derivative dIdX vector.
dealii::LinearAlgebra::distributed::Vector< double > solution
Current modal coefficients of the solution.
TargetFunctional(std::shared_ptr< DGBase< dim, real >> dg_input, const bool uses_solution_values=true, const bool uses_solution_gradient=true)
Constructor.
Sacado::Fad::DFad< real > FadType
Sacado AD type for first derivatives.
dealii::hp::QCollection< dim-1 > face_quadrature_collection
Quadrature used to evaluate face integrals.
const dealii::LinearAlgebra::distributed::Vector< real > target_solution
Solution used to evaluate target functional.
static std::shared_ptr< ModelBase< dim, nstate, real > > create_Model(const Parameters::AllParameters *const parameters_input)
Factory to return the correct model given input parameters.
std::shared_ptr< HighOrderGrid< dim, real, MeshType > > high_order_grid
High order grid that will provide the MappingFEField.
real2 evaluate_volume_cell_functional(const Physics::PhysicsBase< dim, nstate, real2 > &physics, const std::vector< real2 > &soln_coeff, const std::vector< real > &target_soln_coeff, const dealii::FESystem< dim > &fe_solution, const std::vector< real2 > &coords_coeff, const dealii::FESystem< dim > &fe_metric, const dealii::Quadrature< dim > &volume_quadrature) const
Templated function to evaluate a cell's volume functional.
dealii::LinearAlgebra::distributed::Vector< real > evaluate_dIdw_finiteDifferences(DGBase< dim, real > &dg, const PHiLiP::Physics::PhysicsBase< dim, nstate, real > &physics, const double stepsize)
real current_functional_value
Store the functional value from the last time evaluate_functional() was called.
static std::shared_ptr< PhysicsBase< dim, nstate, real > > create_Physics(const Parameters::AllParameters *const parameters_input, std::shared_ptr< ModelBase< dim, nstate, real > > model_input=nullptr)
Factory to return the correct physics given input file.
void need_compute(bool &compute_value, bool &compute_dIdW, bool &compute_dIdX, bool &compute_d2I)
Checks which derivatives actually need to be recomputed.
dealii::DoFHandler< dim > dof_handler
Finite Element Collection to represent the high-order grid.
Sacado::Fad::DFad< FadType > FadFadType
Sacado AD type that allows 2nd derivatives.
std::shared_ptr< Physics::PhysicsBase< dim, nstate, FadFadType > > physics_fad_fad
Physics that should correspond to the one in DGBase.
std::shared_ptr< dealii::TrilinosWrappers::SparseMatrix > d2IdWdX
Sparse matrix for storing the functional partial second derivatives.
std::shared_ptr< DGBase< dim, real, dealii::parallel::distributed::Triangulation< dim > > > dg
Smart pointer to DGBase.
DGBase is independent of the number of state variables.
real1 norm(const dealii::Tensor< 1, dim, real1 > x)
Returns norm of dealii::Tensor<1,dim,real>
dealii::hp::QCollection< dim > volume_quadrature_collection
Finite Element Collection to represent the high-order grid.
void allocate_derivatives(const bool compute_dIdW, const bool compute_dIdX, const bool compute_d2I)
Allocate and setup the derivative vectors/matrices.
void set_derivatives(const bool compute_dIdW, const bool compute_dIdX, const bool compute_d2I, const Sacado::Fad::DFad< Sacado::Fad::DFad< real >> volume_local_sum, std::vector< dealii::types::global_dof_index > cell_soln_dofs_indices, std::vector< dealii::types::global_dof_index > cell_metric_dofs_indices)
Set the derivative vectors/matrices.
const dealii::hp::FECollection< dim > fe_collection
Finite Element Collection for p-finite-element to represent the solution.