1 #include <Epetra_RowMatrixTransposer.h>     6 #include <deal.II/distributed/tria.h>     7 #include <deal.II/distributed/grid_refinement.h>     9 #include <deal.II/grid/grid_generator.h>    10 #include <deal.II/grid/grid_tools.h>    12 #include <deal.II/numerics/vector_tools.h>    14 #include <deal.II/lac/solver_bicgstab.h>    15 #include <deal.II/lac/solver_cg.h>    16 #include <deal.II/lac/solver_gmres.h>    17 #include <deal.II/lac/solver_minres.h>    19 #include <deal.II/lac/full_matrix.h>    21 #include <deal.II/lac/trilinos_block_sparse_matrix.h>    22 #include <deal.II/lac/trilinos_precondition.h>    23 #include <deal.II/lac/trilinos_solver.h>    24 #include <deal.II/lac/trilinos_sparsity_pattern.h>    25 #include <deal.II/lac/trilinos_sparse_matrix.h>    27 #include <deal.II/lac/trilinos_parallel_block_vector.h>    28 #include <deal.II/lac/la_parallel_block_vector.h>    29 #include <deal.II/lac/read_write_vector.h>    31 #include <deal.II/lac/packaged_operation.h>    32 #include <deal.II/lac/trilinos_linear_operator.h>    34 #include "optimization_inverse_manufactured.h"    36 #include "physics/physics_factory.h"    37 #include "physics/physics.h"    38 #include "dg/dg_factory.hpp"    39 #include "ode_solver/ode_solver_factory.h"    41 #include "functional/target_functional.h"    42 #include "functional/adjoint.h"    44 #include "linear_solver/linear_solver.h"    46 #include "testing/full_space_optimization.h"    53 #define AMPLITUDE_OPT 0.1    55 #define HESSIAN_DIAG 1e0    59 dealii::Point<dim> reverse_deformation(dealii::Point<dim> point) {
    60     dealii::Point<dim> new_point = point;
    61     const double amplitude = AMPLITUDE_OPT;
    62  double denom = amplitude;
    64         denom *= std::sin(2.0*dealii::numbers::PI*point[1]);
    67         denom *= std::sin(2.0*dealii::numbers::PI*point[2]);
    70  new_point[0] /= denom;
    74 dealii::Point<dim> target_deformation(dealii::Point<dim> point) {
    75     const double amplitude = AMPLITUDE_OPT;
    76     dealii::Tensor<1,dim,double> disp;
    80         disp[0] *= std::sin(2.0*dealii::numbers::PI*point[1]);
    83         disp[0] *= std::sin(2.0*dealii::numbers::PI*point[2]);
   247 template <
int dim, 
int nstate, 
typename real>
   264   const dealii::LinearAlgebra::distributed::Vector<real> &
target_solution,
   271  template <
typename real2>
   274   const dealii::Point<dim,real2> &,
   275   const std::array<real2,nstate> &,
   276         const std::array<real,nstate> &,
   277   const std::array<dealii::Tensor<1,dim,real2>,nstate> &,
   278   const std::array<dealii::Tensor<1,dim,real2>,nstate> &)
 const   288   const dealii::Point<dim,real> &phys_coord,
   289   const std::array<real,nstate> &soln_at_q,
   290         const std::array<real,nstate> &target_soln_at_q,
   291   const std::array<dealii::Tensor<1,dim,real>,nstate> &soln_grad_at_q,
   292   const std::array<dealii::Tensor<1,dim,real>,nstate> &target_soln_grad_at_q)
 const override   294   return evaluate_volume_integrand<>(physics, phys_coord, soln_at_q, target_soln_at_q, soln_grad_at_q, target_soln_grad_at_q);
   299   const dealii::Point<dim,FadFadType> &phys_coord,
   300   const std::array<FadFadType,nstate> &soln_at_q,
   301         const std::array<real,nstate> &target_soln_at_q,
   302   const std::array<dealii::Tensor<1,dim,FadFadType>,nstate> &soln_grad_at_q,
   303         const std::array<dealii::Tensor<1,dim,FadFadType>,nstate> &target_soln_grad_at_q)
 const override   305   return evaluate_volume_integrand<>(physics, phys_coord, soln_at_q, target_soln_at_q, soln_grad_at_q, target_soln_grad_at_q);
   309 template <
int dim, 
int nstate>
   315 template <
int dim, 
int nstate>
   318     dealii::LinearAlgebra::distributed::Vector<double> solution_no_ghost;
   324 template<
int dim, 
int nstate>
   328  const double amplitude = AMPLITUDE_OPT;
   329     const int poly_degree = 1;
   330     int fail_bool = 
false;
   331  pcout << 
" Running optimization case... " << std::endl;
   337  const unsigned int initial_n_cells = 4;
   340     using Triangulation = dealii::Triangulation<dim>;
   342     using Triangulation = dealii::parallel::distributed::Triangulation<dim>;
   345     std::shared_ptr <Triangulation> grid = std::make_shared<Triangulation> (
   349         typename dealii::Triangulation<dim>::MeshSmoothing(
   350             dealii::Triangulation<dim>::smoothing_on_refinement |
   351             dealii::Triangulation<dim>::smoothing_on_coarsening));
   353  dealii::GridGenerator::subdivided_hyper_cube(*grid, initial_n_cells);
   354  for (
auto cell = grid->begin_active(); cell != grid->end(); ++cell) {
   356   cell->set_material_id(9002);
   357   for (
unsigned int face=0; face<dealii::GeometryInfo<dim>::faces_per_cell; ++face) {
   358    if (cell->face(face)->at_boundary()) cell->face(face)->set_boundary_id (1000);
   364     dg->allocate_system ();
   366  std::shared_ptr<HighOrderGrid<dim,double>> high_order_grid = dg->high_order_grid;
   368  high_order_grid->prepare_for_coarsening_and_refinement();
   370  high_order_grid->execute_coarsening_and_refinement();
   371  high_order_grid->output_results_vtk(high_order_grid->nth_refinement++);
   377  std::vector<dealii::Tensor<1,dim,double>> point_displacements(high_order_grid->locally_relevant_surface_points.size());
   378  const unsigned int n_locally_relevant_surface_nodes = dim * high_order_grid->locally_relevant_surface_points.size();
   379  std::vector<dealii::types::global_dof_index> surface_node_global_indices(n_locally_relevant_surface_nodes);
   380  std::vector<double> surface_node_displacements(n_locally_relevant_surface_nodes);
   382   auto displacement = point_displacements.begin();
   383   auto point = high_order_grid->locally_relevant_surface_points.begin();
   384   auto point_end = high_order_grid->locally_relevant_surface_points.end();
   385   for (;point != point_end; ++point, ++displacement) {
   386    (*displacement)[0] = amplitude * (*point)[0];
   388     (*displacement)[0] *= std::sin(2.0*dealii::numbers::PI*(*point)[1]);
   391     (*displacement)[0] *= std::sin(2.0*dealii::numbers::PI*(*point)[2]);
   395   for (
unsigned int ipoint=0; ipoint<point_displacements.size(); ++ipoint) {
   396    for (
unsigned int d=0;d<dim;++d) {
   397     const std::pair<unsigned int, unsigned int> point_axis = std::make_pair(ipoint,d);
   398     const dealii::types::global_dof_index global_index = high_order_grid->point_and_axis_to_global_index[point_axis];
   399     surface_node_global_indices[inode] = global_index;
   400     surface_node_displacements[inode] = point_displacements[ipoint][d];
   405  const auto initial_grid = high_order_grid->volume_nodes;
   409  using VectorType = dealii::LinearAlgebra::distributed::Vector<double>;
   410  std::function<dealii::Point<dim>(dealii::Point<dim>)> target_transformation = target_deformation<dim>;
   411  VectorType surface_node_displacements_vector = high_order_grid->transform_surface_nodes(target_transformation);
   412  surface_node_displacements_vector -= high_order_grid->surface_nodes;
   413  surface_node_displacements_vector.update_ghost_values();
   425  high_order_grid->volume_nodes += volume_displacements;
   426  high_order_grid->volume_nodes.update_ghost_values();
   427     high_order_grid->update_surface_nodes();
   441  initialize_perturbed_solution(*dg, *physics_double);
   442  dg->output_results_vtk(999);
   443  high_order_grid->output_results_vtk(high_order_grid->nth_refinement++);
   445  ode_solver->steady_state();
   448  const auto target_solution = dg->solution;
   449  const auto target_nodes    = high_order_grid->volume_nodes;
   451  pcout << 
"Target grid: " << std::endl;
   452  dg->output_results_vtk(9999);
   453  high_order_grid->output_results_vtk(9999);
   459   auto displacement = point_displacements.begin();
   460   auto point = high_order_grid->locally_relevant_surface_points.begin();
   461   auto point_end = high_order_grid->locally_relevant_surface_points.end();
   462   for (;point != point_end; ++point, ++displacement) {
   463    if ((*point)[0] > 0.5 && (*point)[1] > 1e-10 && (*point)[1] < 1-1e-10) {
   464     const double final_location = 1.0;
   465     const double current_location = (*point)[0];
   466     (*displacement)[0] = final_location - current_location;
   473   for (
unsigned int ipoint=0; ipoint<point_displacements.size(); ++ipoint) {
   474    for (
unsigned int d=0;d<dim;++d) {
   475     const std::pair<unsigned int, unsigned int> point_axis = std::make_pair(ipoint,d);
   476     const dealii::types::global_dof_index global_index = high_order_grid->point_and_axis_to_global_index[point_axis];
   477     surface_node_global_indices[inode] = global_index;
   478     surface_node_displacements[inode] = point_displacements[ipoint][d];
   495  high_order_grid->volume_nodes = initial_grid;
   496  high_order_grid->volume_nodes.update_ghost_values();
   497     high_order_grid->update_surface_nodes();
   498  pcout << 
"Initial grid: " << std::endl;
   499  dg->output_results_vtk(9998);
   500  high_order_grid->output_results_vtk(9998);
   503  ode_solver->steady_state();
   506  auto error_vector = dg->solution;
   507  error_vector -= target_solution;
   508  const double l2_vector_error = error_vector.l2_norm();
   511  bool compute_dIdW = 
false, compute_dIdX = 
false, compute_d2I = 
true;
   512     const double current_l2_error = inverse_target_functional.
evaluate_functional(compute_dIdW, compute_dIdX, compute_d2I);
   513  pcout << 
"Vector l2_norm of the coefficients: " << l2_vector_error << std::endl;
   514  pcout << 
"Functional l2_norm : " << current_l2_error << std::endl;
   516  pcout << 
"*************************************************************" << std::endl;
   517  pcout << 
"Starting design... " << std::endl;
   518  pcout << 
"Number of state variables: " << dg->dof_handler.n_dofs() << std::endl;
   519  pcout << 
"Number of mesh volume_nodes: " << high_order_grid->dof_handler_grid.n_dofs() << std::endl;
   520  pcout << 
"Number of constraints: " << dg->dof_handler.n_dofs() << std::endl;
   522  const dealii::IndexSet surface_locally_owned_indexset = high_order_grid->surface_nodes.locally_owned_elements();
   523  dealii::TrilinosWrappers::SparseMatrix dRdXs;
   524  dealii::TrilinosWrappers::SparseMatrix d2LdWdXs;
   525  dealii::TrilinosWrappers::SparseMatrix d2LdXsdXs;
   530  dIdXs.reinit(dg->high_order_grid->surface_nodes);
   532  auto grad_lagrangian = dIdXs;
   535  dealii::LinearAlgebra::distributed::BlockVector<double> kkt_rhs(3);
   536     pcout << 
"Evaluating KKT right-hand side: dIdW, dIdX, d2I, Residual..." << std::endl;
   537  compute_dIdW = 
true, compute_dIdX = 
true, compute_d2I = 
true;
   538  (void) inverse_target_functional.
evaluate_functional(compute_dIdW, compute_dIdX, compute_d2I);
   539  bool compute_dRdW = 
false, compute_dRdX = 
false, compute_d2R = 
false;
   540  dg->assemble_residual(compute_dRdW, compute_dRdX, compute_d2R);
   541  for (
unsigned int isurf = 0; isurf < dg->high_order_grid->surface_nodes.size(); ++isurf) {
   542   const auto scalar_product = meshmover.
dXvdXs[isurf] * inverse_target_functional.
dIdX;
   543   if (dIdXs.locally_owned_elements().is_element(isurf)) {
   544    dIdXs[isurf] = scalar_product;
   547  dIdXs.update_ghost_values();
   549  kkt_rhs.block(0) = inverse_target_functional.
dIdw;
   550  kkt_rhs.block(1) = dIdXs;
   551  kkt_rhs.block(2) = dg->right_hand_side;
   554  dealii::LinearAlgebra::distributed::BlockVector<double> kkt_soln(3), p4inv_kkt_rhs(3);
   555  kkt_soln.reinit(kkt_rhs);
   556  p4inv_kkt_rhs.reinit(kkt_rhs);
   558  auto mesh_error = target_nodes;
   559  mesh_error -= high_order_grid->volume_nodes;
   562  double current_kkt_norm = kkt_rhs.l2_norm();
   563  double current_constraint_satisfaction = kkt_rhs.block(2).l2_norm();
   564  double current_mesh_error = mesh_error.l2_norm();
   565  pcout << std::scientific << std::setprecision(5);
   566  pcout << 
"*************************************************************" << std::endl;
   567  pcout << 
"Initial design " << std::endl;
   568  pcout << 
"*************************************************************" << std::endl;
   569  pcout << 
"Current functional: " << current_functional << std::endl;
   570  pcout << 
"Constraint satisfaction: " << current_constraint_satisfaction << std::endl;
   571  pcout << 
"l2norm(Current mesh - optimal mesh): " << current_mesh_error << std::endl;
   572  pcout << 
"Current KKT norm: " << current_kkt_norm << std::endl;
   575  const unsigned int n_des_var = high_order_grid->surface_nodes.size();
   576  dealii::FullMatrix<double> Hessian_inverse = dealii::IdentityMatrix(n_des_var);
   577  const double diagonal_hessian = HESSIAN_DIAG;
   578  Hessian_inverse *= 1.0/diagonal_hessian;
   579  dealii::Vector<double> oldg(n_des_var), currentg(n_des_var), searchD(n_des_var);
   581  const bool use_BFGS = 
true;
   582  const unsigned int bfgs_max_history = n_des_var;
   583  const unsigned int n_max_design = 1000;
   584  const double kkt_tolerance = 1e-10;
   587  dg->set_dual(kkt_soln.block(2));
   589     std::list<VectorType> bfgs_search_s;
   590     std::list<VectorType> bfgs_dgrad_y;
   591     std::list<double> bfgs_denom_rho;
   596   ode_solver->steady_state();
   602   pcout << 
"Evaluating KKT right-hand side: dIdW, dIdX, Residual..." << std::endl;
   603   bool compute_dIdW = 
true, compute_dIdX = 
true, compute_d2I = 
false;
   604   (void) inverse_target_functional.
evaluate_functional(compute_dIdW, compute_dIdX, compute_d2I);
   605   compute_dRdW = 
false, compute_dRdX = 
false, compute_d2R = 
false;
   606   dg->assemble_residual(compute_dRdW, compute_dRdX, compute_d2R);
   607   for (
unsigned int isurf = 0; isurf < dg->high_order_grid->surface_nodes.size(); ++isurf) {
   609    const auto scalar_product = meshmover.
dXvdXs[isurf] * inverse_target_functional.
dIdX;
   610    if (dIdXs.locally_owned_elements().is_element(isurf)) {
   613     const unsigned int surface_index = high_order_grid->surface_to_volume_indices[isurf];
   614     const unsigned int component = high_order_grid->global_index_to_point_and_axis[surface_index].second;
   615     if (component != 0) dIdXs[isurf] = 0.0;
   616     else dIdXs[isurf] = scalar_product;
   619   dIdXs.update_ghost_values();
   622   pcout << 
"Evaluating dRdW..." << std::endl;
   623   compute_dRdW = 
true, compute_dRdX = 
false, compute_d2R = 
false;
   624   dg->assemble_residual(compute_dRdW, compute_dRdX, compute_d2R);
   625   pcout << 
"Evaluating dRdX..." << std::endl;
   626   compute_dRdW = 
false; compute_dRdX = 
true, compute_d2R = 
false;
   627   dg->assemble_residual(compute_dRdW, compute_dRdX, compute_d2R);
   631    dealii::SparsityPattern sparsity_pattern_dRdXs = dg->get_dRdXs_sparsity_pattern ();
   632    const dealii::IndexSet &row_parallel_partitioning_dRdXs = dg->locally_owned_dofs;
   633    const dealii::IndexSet &col_parallel_partitioning_dRdXs = surface_locally_owned_indexset;
   634    dRdXs.reinit(row_parallel_partitioning_dRdXs, col_parallel_partitioning_dRdXs, sparsity_pattern_dRdXs, mpi_communicator);
   636   for (
unsigned int isurf = 0; isurf < high_order_grid->surface_nodes.size(); ++isurf) {
   637    VectorType dRdXs_i(dg->solution);
   638    dg->dRdXv.vmult(dRdXs_i,meshmover.
dXvdXs[isurf]);
   639    for (
unsigned int irow = 0; irow < dg->dof_handler.n_dofs(); ++irow) {
   640     if (dg->locally_owned_dofs.is_element(irow)) {
   641      dRdXs.add(irow, isurf, dRdXs_i[irow]);
   645         dRdXs.compress(dealii::VectorOperation::add);
   648   auto dRdW_T = transpose_trilinos_matrix(dg->system_matrix);
   651   solve_linear (dRdW_T, inverse_target_functional.
dIdw, dg->dual, linear_solver_param);
   653   grad_lagrangian = dIdXs;
   654   grad_lagrangian *= -1.0;
   655   dRdXs.Tvmult_add(grad_lagrangian, dg->dual);
   656   grad_lagrangian *= -1.0;
   658  for (
unsigned int i_design = 0; i_design < n_max_design && current_kkt_norm > kkt_tolerance; i_design++) {
   661   auto search_direction = grad_lagrangian;
   662   if (use_BFGS && bfgs_search_s.size() > 0) {
   663    search_direction = LBFGS(grad_lagrangian, bfgs_search_s, bfgs_dgrad_y, bfgs_denom_rho);
   664    auto descent = search_direction * grad_lagrangian;
   666     search_direction = grad_lagrangian;
   667     bfgs_search_s.pop_front();
   668     bfgs_dgrad_y.pop_front();
   669     bfgs_denom_rho.pop_front();
   672   search_direction *= -1.0;
   673   pcout << 
"Gradient magnitude = " << grad_lagrangian.l2_norm() << 
" Search direction magnitude = " << search_direction.l2_norm() << std::endl;
   674   for (
unsigned int isurf = 0; isurf < dg->high_order_grid->surface_nodes.size(); ++isurf) {
   675    if (search_direction.locally_owned_elements().is_element(isurf)) {
   677     const unsigned int surface_index = high_order_grid->surface_to_volume_indices[isurf];
   678     const unsigned int component = high_order_grid->global_index_to_point_and_axis[surface_index].second;
   679     if (component != 0) search_direction[isurf] = 0.0;
   683   const auto old_solution = dg->solution;
   684   const auto old_volume_nodes = high_order_grid->volume_nodes;
   685   const auto old_surface_nodes = high_order_grid->surface_nodes;
   686   const auto old_functional = current_functional;
   689   double step_length = 1.0;
   690   const unsigned int max_linesearch = 80;
   691   unsigned int i_linesearch = 0;
   692   for (; i_linesearch < max_linesearch; i_linesearch++) {
   694    surface_node_displacements_vector = search_direction;
   695    surface_node_displacements_vector *= step_length;
   698    const auto disp_norm = surface_node_displacements_vector.l2_norm();
   699    if (disp_norm > 1e-2) {
   700     pcout << 
"Displacement of " << disp_norm << 
" too large. Reducing step length" << std::endl;
   705     high_order_grid->volume_nodes += volume_displacements;
   706     high_order_grid->volume_nodes.update_ghost_values();
   707     high_order_grid->update_surface_nodes();
   709     ode_solver->steady_state();
   713     pcout << 
"Linesearch " << i_linesearch+1
   714        << std::scientific << std::setprecision(15)
   715        << 
" step = " << step_length
   716        << 
" Old functional = " << old_functional
   717        << 
" New functional = " << current_functional << std::endl;
   718     pcout << std::fixed << std::setprecision(6);
   720     const double wolfe_c = 1e-4;
   721     double old_func_plus = search_direction*grad_lagrangian;
   722     old_func_plus *= wolfe_c * step_length;
   723     old_func_plus += old_functional;
   725     if (current_functional < old_func_plus) 
break;
   728    dg->solution = old_solution;
   729    high_order_grid->volume_nodes = old_volume_nodes;
   730    high_order_grid->volume_nodes.update_ghost_values();
   731    high_order_grid->update_surface_nodes();
   734   if (i_linesearch == max_linesearch) 
return 1;
   740   pcout << 
"Evaluating KKT right-hand side: dIdW, dIdX, Residual..." << std::endl;
   741   bool compute_dIdW = 
true, compute_dIdX = 
true, compute_d2I = 
false;
   742   (void) inverse_target_functional.
evaluate_functional(compute_dIdW, compute_dIdX, compute_d2I);
   743   compute_dRdW = 
false, compute_dRdX = 
false, compute_d2R = 
false;
   744   dg->assemble_residual(compute_dRdW, compute_dRdX, compute_d2R);
   745   for (
unsigned int isurf = 0; isurf < dg->high_order_grid->surface_nodes.size(); ++isurf) {
   746    const auto scalar_product = meshmover.
dXvdXs[isurf] * inverse_target_functional.
dIdX;
   747    if (dIdXs.locally_owned_elements().is_element(isurf)) {
   749     const unsigned int surface_index = high_order_grid->surface_to_volume_indices[isurf];
   750     const unsigned int component = high_order_grid->global_index_to_point_and_axis[surface_index].second;
   751     if (component != 0) dIdXs[isurf] = 0.0;
   752     else dIdXs[isurf] = scalar_product;
   755   dIdXs.update_ghost_values();
   758   pcout << 
"Evaluating dRdW..." << std::endl;
   759   compute_dRdW = 
true, compute_dRdX = 
false, compute_d2R = 
false;
   760   dg->assemble_residual(compute_dRdW, compute_dRdX, compute_d2R);
   761   pcout << 
"Evaluating dRdX..." << std::endl;
   762   compute_dRdW = 
false; compute_dRdX = 
true, compute_d2R = 
false;
   763   dg->assemble_residual(compute_dRdW, compute_dRdX, compute_d2R);
   767    dealii::SparsityPattern sparsity_pattern_dRdXs = dg->get_dRdXs_sparsity_pattern ();
   768    const dealii::IndexSet &row_parallel_partitioning_dRdXs = dg->locally_owned_dofs;
   769    const dealii::IndexSet &col_parallel_partitioning_dRdXs = surface_locally_owned_indexset;
   770    dRdXs.reinit(row_parallel_partitioning_dRdXs, col_parallel_partitioning_dRdXs, sparsity_pattern_dRdXs, mpi_communicator);
   772   for (
unsigned int isurf = 0; isurf < high_order_grid->surface_nodes.size(); ++isurf) {
   773    VectorType dRdXs_i(dg->solution);
   774    dg->dRdXv.vmult(dRdXs_i,meshmover.
dXvdXs[isurf]);
   775    for (
unsigned int irow = 0; irow < dg->dof_handler.n_dofs(); ++irow) {
   776     if (dg->locally_owned_dofs.is_element(irow)) {
   777      dRdXs.add(irow, isurf, dRdXs_i[irow]);
   781         dRdXs.compress(dealii::VectorOperation::add);
   784   auto dRdW_T = transpose_trilinos_matrix(dg->system_matrix);
   787   solve_linear (dRdW_T, inverse_target_functional.
dIdw, dg->dual, linear_solver_param);
   789   const auto old_grad_lagrangian = grad_lagrangian;
   790   grad_lagrangian = dIdXs;
   791   grad_lagrangian *= -1.0;
   792   dRdXs.Tvmult_add(grad_lagrangian, dg->dual);
   793   grad_lagrangian *= -1.0;
   797    auto s = search_direction;
   799    const auto y = grad_lagrangian - old_grad_lagrangian;
   800    const double curvature = s*y;
   801    if (curvature > 0 && bfgs_max_history > 0) {
   802     bfgs_denom_rho.push_front(1.0/curvature);
   803     bfgs_search_s.push_front(s);
   804     bfgs_dgrad_y.push_front(y);
   807    if (bfgs_search_s.size() > bfgs_max_history) {
   808     bfgs_search_s.pop_back();
   809     bfgs_dgrad_y.pop_back();
   810     bfgs_denom_rho.pop_back();
   815   dg->output_results_vtk(high_order_grid->nth_refinement);
   816   high_order_grid->output_results_vtk(high_order_grid->nth_refinement++);
   818   mesh_error = target_nodes;
   819   mesh_error -= high_order_grid->volume_nodes;
   820   current_kkt_norm = grad_lagrangian.l2_norm();
   821   current_constraint_satisfaction = dg->right_hand_side.l2_norm();
   822   current_mesh_error = mesh_error.l2_norm();
   823   pcout << std::scientific << std::setprecision(5);
   824   pcout << 
"*************************************************************" << std::endl;
   825   pcout << 
"Design iteration " << i_design+1 << std::endl;
   826   pcout << 
"Current functional: " << current_functional << std::endl;
   827   pcout << 
"Constraint satisfaction: " << current_constraint_satisfaction << std::endl;
   828   pcout << 
"l2norm(Current mesh - optimal mesh): " << current_mesh_error << std::endl;
   829   pcout << 
"Current KKT norm: " << current_kkt_norm << std::endl;
  1070  pcout << std::endl << std::endl << std::endl << std::endl;
  1072  high_order_grid->volume_nodes = target_nodes;
  1073  high_order_grid->volume_nodes.update_ghost_values();
  1074     high_order_grid->update_surface_nodes();
  1076  ode_solver->steady_state();
  1078  pcout << 
"Nodes at target volume_nodes should have zero functional l2 error : " << zero_l2_error << std::endl;
  1079  if (zero_l2_error > 1e-10) 
return 1;
  1081  if (current_kkt_norm > kkt_tolerance) 
return 1;
 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. 
Parameters related to the linear solver. 
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. 
const MPI_Comm mpi_communicator
MPI communicator. 
std::pair< unsigned int, double > solve_linear(const dealii::TrilinosWrappers::SparseMatrix &system_matrix, dealii::LinearAlgebra::distributed::Vector< double > &right_hand_side, dealii::LinearAlgebra::distributed::Vector< double > &solution, const Parameters::LinearSolverParam ¶m)
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. 
Main parameter class that contains the various other sub-parameter classes. 
dealii::LinearAlgebra::distributed::Vector< double > solution
Current modal coefficients of the solution. 
dealii::IndexSet locally_owned_dofs
Locally own degrees of freedom. 
Sacado::Fad::DFad< real > FadType
Sacado AD type for first derivatives. 
const Parameters::AllParameters *const all_parameters
Pointer to all parameters. 
static std::shared_ptr< DGBase< dim, real, MeshType > > create_discontinuous_galerkin(const Parameters::AllParameters *const parameters_input, const unsigned int degree, const unsigned int max_degree_input, const unsigned int grid_degree_input, const std::shared_ptr< Triangulation > triangulation_input)
Creates a derived object DG, but returns it as DGBase. 
LinearSolverParam linear_solver_param
Contains parameters for linear solver. 
const dealii::LinearAlgebra::distributed::Vector< real > target_solution
Solution used to evaluate target functional. 
FadFadType evaluate_volume_integrand(const PHiLiP::Physics::PhysicsBase< dim, nstate, FadFadType > &physics, const dealii::Point< dim, FadFadType > &phys_coord, const std::array< FadFadType, nstate > &soln_at_q, const std::array< real, nstate > &target_soln_at_q, const std::array< dealii::Tensor< 1, dim, FadFadType >, nstate > &soln_grad_at_q, const std::array< dealii::Tensor< 1, dim, FadFadType >, nstate > &target_soln_grad_at_q) const override
non-template functions to override the template classes 
real2 evaluate_volume_integrand(const PHiLiP::Physics::PhysicsBase< dim, nstate, real2 > &, const dealii::Point< dim, real2 > &, const std::array< real2, nstate > &, const std::array< real, nstate > &, const std::array< dealii::Tensor< 1, dim, real2 >, nstate > &, const std::array< dealii::Tensor< 1, dim, real2 >, nstate > &) const
Zero out the default inverse target volume functional. 
VectorType get_volume_displacements()
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. 
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. 
OptimizationInverseManufactured(const Parameters::AllParameters *const parameters_input)
Constructor. 
int run_test() const override
Grid convergence on Euler Gaussian Bump. 
dealii::ConditionalOStream pcout
ConditionalOStream. 
Performs grid convergence for various polynomial degrees. 
DGBase is independent of the number of state variables. 
std::shared_ptr< ManufacturedSolutionFunction< dim, real > > manufactured_solution_function
Manufactured solution function. 
static std::shared_ptr< ODESolverBase< dim, real, MeshType > > create_ODESolver(std::shared_ptr< DGBase< dim, real, MeshType > > dg_input)
Creates either implicit or explicit ODE solver based on parameter value(no POD basis given) ...
Base class of all the tests. 
std::vector< dealii::LinearAlgebra::distributed::Vector< double > > dXvdXs
real evaluate_volume_integrand(const PHiLiP::Physics::PhysicsBase< dim, nstate, real > &physics, const dealii::Point< dim, real > &phys_coord, 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 > &soln_grad_at_q, const std::array< dealii::Tensor< 1, dim, real >, nstate > &target_soln_grad_at_q) const override
non-template functions to override the template classes 
BoundaryInverseTarget(std::shared_ptr< DGBase< dim, real >> dg_input, const dealii::LinearAlgebra::distributed::Vector< real > &target_solution, const bool uses_solution_values=true, const bool uses_solution_gradient=true)
Constructor.