[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
euler_naca0012_optimization.cpp
1 #include <stdlib.h> /* srand, rand */
2 #include <iostream>
3 
4 #include <deal.II/grid/grid_generator.h>
5 
6 #include <deal.II/numerics/vector_tools.h>
7 
8 #include <deal.II/optimization/rol/vector_adaptor.h>
9 
10 #include "Teuchos_GlobalMPISession.hpp"
11 #include "ROL_Algorithm.hpp"
12 #include "ROL_Reduced_Objective_SimOpt.hpp"
13 #include "ROL_OptimizationSolver.hpp"
14 #include "ROL_LineSearchStep.hpp"
15 #include "ROL_StatusTest.hpp"
16 
17 #include "ROL_SingletonVector.hpp"
18 #include <ROL_AugmentedLagrangian_SimOpt.hpp>
19 
20 #include "euler_naca0012_optimization.hpp"
21 
22 #include "physics/initial_conditions/initial_condition_function.h"
23 #include "physics/euler.h"
24 #include "dg/dg_factory.hpp"
25 #include "ode_solver/ode_solver_factory.h"
26 
27 #include "functional/target_boundary_functional.h"
28 
29 #include "mesh/grids/gaussian_bump.h"
30 #include "mesh/free_form_deformation.h"
31 
32 #include "optimization/rol_to_dealii_vector.hpp"
33 #include "optimization/flow_constraints.hpp"
34 #include "optimization/rol_objective.hpp"
35 #include "optimization/constraintfromobjective_simopt.hpp"
36 #include "optimization/design_parameterization/ffd_parameterization.hpp"
37 
38 #include "optimization/full_space_step.hpp"
39 
40 #include "mesh/gmsh_reader.hpp"
41 #include "functional/lift_drag.hpp"
42 #include "functional/target_wall_pressure.hpp"
43 
44 #include "global_counter.hpp"
45 
46 namespace PHiLiP {
47 namespace Tests {
48 
49 double check_max_rel_error(std::vector<std::vector<double>> rol_check_results) {
50  double max_rel_err = 999999;
51  for (unsigned int i = 0; i < rol_check_results.size(); ++i) {
52  const double abs_val_ad = std::abs(rol_check_results[i][1]);
53  const double abs_val_fd = std::abs(rol_check_results[i][2]);
54  const double abs_err = std::abs(rol_check_results[i][3]);
55  const double rel_err = abs_err / std::max(abs_val_ad,abs_val_fd);
56  max_rel_err = std::min(max_rel_err, rel_err);
57  }
58  return max_rel_err;
59 }
60 
61 enum OptimizationAlgorithm { full_space_birosghattas, full_space_composite_step, reduced_space_bfgs, reduced_space_newton };
62 enum BirosGhattasPreconditioner { P2, P2A, P4, P4A, identity };
63 
64 //const std::vector<BirosGhattasPreconditioner> precond_list { P2, P2A, P4, P4A };
65 //const std::vector<OptimizationAlgorithm> opt_list { full_space_birosghattas, reduced_space_newton };
66 //const std::vector<BirosGhattasPreconditioner> precond_list { P2, P2A, P4, P4A };
67 const std::vector<BirosGhattasPreconditioner> precond_list { P2A };//, P2, P4, P4A };
68 //const std::vector<BirosGhattasPreconditioner> precond_list { P2A };
69 const std::vector<OptimizationAlgorithm> opt_list { reduced_space_bfgs, full_space_birosghattas, reduced_space_newton };
70 //const std::vector<OptimizationAlgorithm> opt_list { full_space_birosghattas, reduced_space_bfgs, reduced_space_newton };
71 //const std::vector<OptimizationAlgorithm> opt_list { reduced_space_newton };
72 //const std::vector<OptimizationAlgorithm> opt_list { full_space_birosghattas, reduced_space_bfgs};
73 //const std::vector<OptimizationAlgorithm> opt_list { reduced_space_bfgs};
74 
75 const unsigned int POLY_START = 0;
76 const unsigned int POLY_END = 1; // Can do until at least P2
77 
78 const unsigned int n_des_var_start = 10;//20;
79 const unsigned int n_des_var_end = 20;//100;
80 const unsigned int n_des_var_step = 10;//20;
81 
82 const int max_design_cycle = 1000;
83 
84 const double FD_TOL = 1e-6;
85 const double CONSISTENCY_ABS_TOL = 1e-10;
86 
87 const std::string line_search_curvature =
88  "Null Curvature Condition";
89  //"Goldstein Conditions";
90  //"Strong Wolfe Conditions";
91 const std::string line_search_method =
92  // "Cubic Interpolation";
93  // "Iteration Scaling";
94  "Backtracking";
95 
96 template <int dim, int nstate>
98  :
99  TestsBase::TestsBase(parameters_input)
100 {}
101 
102 template<int dim, int nstate>
104 ::run_test () const
105 {
106  int test_error = 0;
107  std::filebuf filebuffer;
108  if (this->mpi_rank == 0) filebuffer.open ("optimization.log", std::ios::out);
109  if (this->mpi_rank == 0) filebuffer.close();
110 
111  for (unsigned int poly_degree = POLY_START; poly_degree <= POLY_END; ++poly_degree) {
112  for (unsigned int n_des_var = n_des_var_start; n_des_var <= n_des_var_end; n_des_var += n_des_var_step) {
113  //for (unsigned int n_des_var = n_des_var_start; n_des_var <= n_des_var_end; n_des_var *= 2) {
114  // assert(n_des_var%2 == 0);
115  // assert(n_des_var>=2);
116  // const unsigned int nx_ffd = n_des_var / 2 + 2;
117  const unsigned int nx_ffd = n_des_var + 2;
118  test_error += optimize(nx_ffd, poly_degree);
119  }
120  }
121  return test_error;
122 }
123 
124 template<int dim, int nstate>
125 int check_flow_constraints(
126  const unsigned int nx_ffd,
127  ROL::Ptr<FlowConstraints<dim>> flow_constraints,
128  ROL::Ptr<ROL::Vector<double>> des_var_sim_rol_p,
129  ROL::Ptr<ROL::Vector<double>> des_var_ctl_rol_p,
130  ROL::Ptr<ROL::Vector<double>> des_var_adj_rol_p)
131 {
132  Physics::Euler<dim,nstate,double> euler_physics_double
134  1,
135  1.4,
136  0.8,
137  1.25,
138  0.0);
139  FreeStreamInitialConditions<dim,nstate,double> initial_conditions(euler_physics_double);
140 
141  int test_error = 0;
142  // Temporary vectors
143  const auto temp_sim = des_var_sim_rol_p->clone();
144  const auto temp_ctl = des_var_ctl_rol_p->clone();
145  const auto v1 = temp_sim->clone();
146  const auto v2 = temp_ctl->clone();
147 
148  const auto jv1 = temp_sim->clone();
149  const auto jv2 = temp_sim->clone();
150 
151  v1->zero();
152  v1->setScalar(1.0);
153  v2->zero();
154  v2->setScalar(1.0);
155 
156  std::vector<double> steps;
157  for (int i = -2; i > -12; i--) {
158  steps.push_back(std::pow(10,i));
159  }
160  const int order = 2;
161 
162  const ROL::Ptr<ROL::Vector_SimOpt<double>> des_var_rol_p = ROL::makePtr<ROL::Vector_SimOpt<double>>(des_var_sim_rol_p, des_var_ctl_rol_p);
163 
164  Teuchos::RCP<std::ostream> outStream;
165  ROL::nullstream bhs; // outputs nothing
166  const unsigned int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
167  std::filebuf filebuffer;
168  if (mpi_rank == 0) filebuffer.open ("flow_constraints_check"+std::to_string(nx_ffd)+".log",std::ios::out);
169  std::ostream ostr(&filebuffer);
170  if (mpi_rank == 0) outStream = ROL::makePtrFromRef(ostr);
171  else if (mpi_rank == 1) outStream = ROL::makePtrFromRef(std::cout);
172  else outStream = ROL::makePtrFromRef(bhs);
173 
174  *outStream << "flow_constraints->checkApplyJacobian_1..." << std::endl;
175  *outStream << "Checks dRdW * v1 against R(w+h*v1,x)/h ..." << std::endl;
176  {
177  std::vector<std::vector<double>> results
178  = flow_constraints->checkApplyJacobian_1(*temp_sim, *temp_ctl, *v1, *jv1, steps, true, *outStream, order);
179 
180  const double max_rel_err = check_max_rel_error(results);
181  if (max_rel_err > FD_TOL) {
182  test_error++;
183  *outStream << "Failed flow_constraints->checkApplyJacobian_1..." << std::endl;
184  }
185  }
186 
187  *outStream << "flow_constraints->checkApplyJacobian_2..." << std::endl;
188  *outStream << "Checks dRdX * v2 against R(w,x+h*v2)/h ..." << std::endl;
189  {
190  std::vector<std::vector<double>> results
191  = flow_constraints->checkApplyJacobian_2(*temp_sim, *temp_ctl, *v2, *jv2, steps, true, *outStream, order);
192 
193  const double max_rel_err = check_max_rel_error(results);
194  if (max_rel_err > FD_TOL) {
195  test_error++;
196  *outStream << "Failed flow_constraints->checkApplyJacobian_2..." << std::endl;
197  }
198  }
199 
200  *outStream << "flow_constraints->checkInverseJacobian_1..." << std::endl;
201  *outStream << "Checks || v - Jinv J v || == 0 ..." << std::endl;
202  {
203  const double v_minus_Jinv_J_v = flow_constraints->checkInverseJacobian_1(*jv1, *v1, *temp_sim, *temp_ctl, true, *outStream);
204  const double normalized_v_minus_Jinv_J_v = v_minus_Jinv_J_v / v1->norm();
205  if (normalized_v_minus_Jinv_J_v > CONSISTENCY_ABS_TOL) {
206  test_error++;
207  *outStream << "Failed flow_constraints->checkInverseJacobian_1..." << std::endl;
208  }
209  }
210 
211  *outStream << "flow_constraints->checkInverseAdjointJacobian_1..." << std::endl;
212  *outStream << "Checks || v - Jtinv Jt v || == 0 ..." << std::endl;
213  {
214  const double v_minus_Jinv_J_v = flow_constraints->checkInverseAdjointJacobian_1(*jv1, *v1, *temp_sim, *temp_ctl, true, *outStream);
215  const double normalized_v_minus_Jinv_J_v = v_minus_Jinv_J_v / v1->norm();
216  if (normalized_v_minus_Jinv_J_v > CONSISTENCY_ABS_TOL) {
217  test_error++;
218  *outStream << "Failed flow_constraints->checkInverseAdjointJacobian_1..." << std::endl;
219  }
220 
221  }
222 
223  *outStream << "flow_constraints->checkAdjointConsistencyJacobian..." << std::endl;
224  *outStream << "Checks (w J v) versus (v Jt w) ..." << std::endl;
225  {
226  const auto w = des_var_adj_rol_p->clone();
227  const auto v = des_var_rol_p->clone();
228  const auto x = des_var_rol_p->clone();
229  const auto temp_Jv = des_var_adj_rol_p->clone();
230  const auto temp_Jtw = des_var_rol_p->clone();
231  const bool printToStream = true;
232  const double wJv_minus_vJw = flow_constraints->checkAdjointConsistencyJacobian (*w, *v, *x, *temp_Jv, *temp_Jtw, printToStream, *outStream);
233  if (wJv_minus_vJw > CONSISTENCY_ABS_TOL) {
234  test_error++;
235  *outStream << "Failed flow_constraints->checkAdjointConsistencyJacobian..." << std::endl;
236  }
237  }
238 
239  *outStream << "flow_constraints->checkApplyAdjointHessian..." << std::endl;
240  *outStream << "Checks (w H v) versus FD approximation ..." << std::endl;
241  {
242  const auto dual = des_var_sim_rol_p->clone();
243  const auto temp_sim_ctl = des_var_rol_p->clone();
244  const auto v3 = des_var_rol_p->clone();
245  const auto hv3 = des_var_rol_p->clone();
246 
247  std::vector<std::vector<double>> results
248  = flow_constraints->checkApplyAdjointHessian(*des_var_rol_p, *dual, *v3, *hv3, steps, true, *outStream, order);
249 
250  const double max_rel_err = check_max_rel_error(results);
251  if (max_rel_err > FD_TOL) {
252  test_error++;
253  *outStream << "Failed flow_constraints->checkApplyAdjointHessian..." << std::endl;
254  }
255  }
256  filebuffer.close();
257 
258  return test_error;
259 }
260 
261 template<int dim, int nstate>
262 int check_objective(
263  const unsigned int nx_ffd,
264  std::shared_ptr < DGBase<dim, double> > dg,
265  ROL::Ptr<ROL::Objective_SimOpt<double>> objective,
266  ROL::Ptr<FlowConstraints<dim>> flow_constraints,
267  ROL::Ptr<ROL::Vector<double>> des_var_sim_rol_p,
268  ROL::Ptr<ROL::Vector<double>> des_var_ctl_rol_p,
269  ROL::Ptr<ROL::Vector<double>> des_var_adj_rol_p)
270 {
271  int test_error = 0;
272  const bool storage = false;
273  const bool useFDHessian = false;
274  auto robj = ROL::makePtr<ROL::Reduced_Objective_SimOpt<double>>( objective, flow_constraints, des_var_sim_rol_p, des_var_ctl_rol_p, des_var_adj_rol_p, storage, useFDHessian);
275  //const bool full_space = true;
276  ROL::OptimizationProblem<double> opt;
277  // Set parameters.
278  Teuchos::ParameterList parlist;
279 
280  Physics::Euler<dim,nstate,double> euler_physics_double
282  1,
283  1.4,
284  0.8,
285  1.25,
286  0.0);
287  FreeStreamInitialConditions<dim,nstate,double> initial_conditions(euler_physics_double);
288 
289  auto des_var_p = ROL::makePtr<ROL::Vector_SimOpt<double>>(des_var_sim_rol_p, des_var_ctl_rol_p);
290 
291  Teuchos::RCP<std::ostream> outStream;
292  ROL::nullstream bhs; // outputs nothing
293  const unsigned int mpi_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD);
294  std::filebuf filebuffer;
295  static int objective_count = 0;
296  if (mpi_rank == 0) filebuffer.open ("objective"+std::to_string(objective_count)+"_check"+std::to_string(nx_ffd)+".log",std::ios::out);
297  std::ostream ostr(&filebuffer);
298  if (mpi_rank == 0) outStream = ROL::makePtrFromRef(ostr);
299  else if (mpi_rank == 1) outStream = ROL::makePtrFromRef(std::cout);
300  else outStream = ROL::makePtrFromRef(bhs);
301 
302  std::vector<double> steps;
303  for (int i = -2; i > -9; i--) {
304  steps.push_back(std::pow(10,i));
305  }
306  const int order = 2;
307  {
308  const auto direction = des_var_p->clone();
309  *outStream << "objective->checkGradient..." << std::endl;
310  std::vector<std::vector<double>> results
311  = objective->checkGradient( *des_var_p, *direction, steps, true, *outStream, order);
312 
313  const double max_rel_err = check_max_rel_error(results);
314  if (max_rel_err > FD_TOL) test_error++;
315  }
316  {
317  const auto direction_1 = des_var_p->clone();
318  auto direction_2 = des_var_p->clone();
319  direction_2->scale(0.5);
320  *outStream << "objective->checkHessVec..." << std::endl;
321  std::vector<std::vector<double>> results
322  = objective->checkHessVec( *des_var_p, *direction_1, steps, true, *outStream, order);
323 
324  const double max_rel_err = check_max_rel_error(results);
325  if (max_rel_err > FD_TOL) test_error++;
326 
327  *outStream << "objective->checkHessSym..." << std::endl;
328  std::vector<double> results_HessSym = objective->checkHessSym( *des_var_p, *direction_1, *direction_2, true, *outStream);
329  double wHv = std::abs(results_HessSym[0]);
330  double vHw = std::abs(results_HessSym[1]);
331  double abs_error = std::abs(wHv - vHw);
332  double rel_error = abs_error / std::max(wHv, vHw);
333  if (rel_error > FD_TOL) test_error++;
334  }
335 
336  {
337  const auto direction_ctl = des_var_ctl_rol_p->clone();
338  *outStream << "robj->checkGradient..." << std::endl;
339  (void) initial_conditions;
340  (void) dg;
341  //dealii::VectorTools::interpolate(dg->dof_handler, initial_conditions, dg->solution);
342  std::vector<std::vector<double>> results
343  = robj->checkGradient( *des_var_ctl_rol_p, *direction_ctl, steps, true, *outStream, order);
344 
345  const double max_rel_err = check_max_rel_error(results);
346  if (max_rel_err > FD_TOL) test_error++;
347 
348  }
349  filebuffer.close();
350 
351  return test_error;
352 }
353 
354 template<int dim, int nstate>
356 ::optimize (const unsigned int nx_ffd, const unsigned int poly_degree) const
357 {
358  int test_error = 0;
359 
360  for (auto const opt_type : opt_list) {
361  for (auto const precond_type : precond_list) {
362 
363  std::string opt_output_name = "";
364  std::string descent_method = "";
365  std::string preconditioner_string = "";
366  switch(opt_type) {
367  case full_space_birosghattas: {
368  opt_output_name = "full_space";
369  switch(precond_type) {
370  case P2: {
371  opt_output_name += "_p2";
372  preconditioner_string = "P2";
373  break;
374  }
375  case P2A: {
376  opt_output_name += "_p2a";
377  preconditioner_string = "P2A";
378  break;
379  }
380  case P4: {
381  opt_output_name += "_p4";
382  preconditioner_string = "P4";
383  break;
384  }
385  case P4A: {
386  opt_output_name += "_p4a";
387  preconditioner_string = "P4A";
388  break;
389  }
390  case identity: {
391  opt_output_name += "_identity";
392  preconditioner_string = "identity";
393  break;
394  }
395  }
396  break;
397  }
398  case full_space_composite_step: {
399  opt_output_name = "full_space_composite_step";
400  break;
401  }
402  case reduced_space_bfgs: {
403  opt_output_name = "reduced_space_bfgs";
404  descent_method = "Quasi-Newton Method";
405  break;
406  }
407  case reduced_space_newton: {
408  opt_output_name = "reduced_space_newton";
409  descent_method = "Newton-Krylov";
410  break;
411  }
412  }
413  opt_output_name = opt_output_name + "_"
414  + "P" + std::to_string(poly_degree);
415 
416  // Output stream
417  ROL::nullstream bhs; // outputs nothing
418  std::filebuf filebuffer;
419  if (this->mpi_rank == 0) filebuffer.open ("optimization_"+opt_output_name+"_"+std::to_string(nx_ffd-2)+".log", std::ios::out);
420  //if (this->mpi_rank == 0) filebuffer.open ("optimization.log", std::ios::out|std::ios::app);
421  std::ostream ostr(&filebuffer);
422 
423  Teuchos::RCP<std::ostream> outStream;
424  if (this->mpi_rank == 0) outStream = ROL::makePtrFromRef(ostr);
425  else if (this->mpi_rank == 1) outStream = ROL::makePtrFromRef(std::cout);
426  else outStream = ROL::makePtrFromRef(bhs);
427 
428 
429  using DealiiVector = dealii::LinearAlgebra::distributed::Vector<double>;
430  using VectorAdaptor = dealii::Rol::VectorAdaptor<DealiiVector>;
431  using MatrixType = dealii::TrilinosWrappers::SparseMatrix;
433  using GridEnum = ManParam::GridEnum;
435 
436  Assert(dim == param.dimension, dealii::ExcDimensionMismatch(dim, param.dimension));
437  Assert(param.pde_type == param.PartialDifferentialEquation::euler, dealii::ExcNotImplemented());
438 
439  ManParam manu_grid_conv_param = param.manufactured_convergence_study_param;
440 
441 
442  Physics::Euler<dim,nstate,double> euler_physics_double
444  &param,
445  param.euler_param.ref_length,
446  param.euler_param.gamma_gas,
447  param.euler_param.mach_inf,
448  param.euler_param.angle_of_attack,
449  param.euler_param.side_slip_angle);
450  FreeStreamInitialConditions<dim,nstate,double> initial_conditions(euler_physics_double);
451 
452  using Triangulation = dealii::parallel::distributed::Triangulation<dim>;
453  std::shared_ptr <Triangulation> grid = std::make_shared<Triangulation> (
454  this->mpi_communicator,
455  typename dealii::Triangulation<dim>::MeshSmoothing(
456  dealii::Triangulation<dim>::smoothing_on_refinement |
457  dealii::Triangulation<dim>::smoothing_on_coarsening));
458 
459 
460  const dealii::Point<dim> ffd_origin(0.0,-0.061);
461  const std::array<double,dim> ffd_rectangle_lengths = {{0.9,0.122}};
462  const std::array<unsigned int,dim> ffd_ndim_control_pts = {{nx_ffd,3}};
463  FreeFormDeformation<dim> ffd( ffd_origin, ffd_rectangle_lengths, ffd_ndim_control_pts);
464 
465  unsigned int n_design_variables = 0;
466  // Vector of ijk indices and dimension.
467  // Each entry in the vector points to a design variable's ijk ctl point and its acting dimension.
468  std::vector< std::pair< unsigned int, unsigned int > > ffd_design_variables_indices_dim;
469  for (unsigned int i_ctl = 0; i_ctl < ffd.n_control_pts; ++i_ctl) {
470 
471  const std::array<unsigned int,dim> ijk = ffd.global_to_grid ( i_ctl );
472  for (unsigned int d_ffd = 0; d_ffd < dim; ++d_ffd) {
473 
474  if ( ijk[0] == 0 // Constrain first column of FFD points.
475  || ijk[0] == ffd_ndim_control_pts[0] - 1 // Constrain last column of FFD points.
476  || ijk[1] == 1 // Constrain middle row of FFD points.
477  || d_ffd == 0 // Constrain x-direction of FFD points.
478  ) {
479  continue;
480  }
481  ++n_design_variables;
482  ffd_design_variables_indices_dim.push_back(std::make_pair(i_ctl, d_ffd));
483  }
484  }
485 
486  const dealii::IndexSet row_part = dealii::Utilities::MPI::create_evenly_distributed_partitioning(MPI_COMM_WORLD,n_design_variables);
487  dealii::IndexSet ghost_row_part(n_design_variables);
488  ghost_row_part.add_range(0,n_design_variables);
489  DealiiVector ffd_design_variables(row_part,ghost_row_part,MPI_COMM_WORLD);
490 
491  ffd.get_design_variables( ffd_design_variables_indices_dim, ffd_design_variables);
492  ffd.set_design_variables( ffd_design_variables_indices_dim, ffd_design_variables);
493 
494  const auto initial_design_variables = ffd_design_variables;
495 
496  // Initial optimization point
497  grid->clear();
498  dealii::GridGenerator::hyper_cube(*grid);
499 
500  ffd_design_variables = initial_design_variables;
501  ffd_design_variables.update_ghost_values();
502  ffd.set_design_variables( ffd_design_variables_indices_dim, ffd_design_variables);
503 
504 
505  DealiiVector target_solution;
506  {
507  for (unsigned int i_ctl = 0; i_ctl < ffd.n_control_pts; ++i_ctl) {
508 
509  const std::array<unsigned int,dim> ijk = ffd.global_to_grid ( i_ctl );
510  if ( ijk[0] == 0 // Constrain first column of FFD points.
511  || ijk[0] == ffd_ndim_control_pts[0] - 1 // Constrain last column of FFD points.
512  || ijk[1] == 1 // Constrain middle row of FFD points.
513  ) continue;
514 
515  dealii::Point<dim> control_pt = ffd.control_pts[i_ctl];
516  double x = control_pt[0];
517  double dy = -0.1*x*x+0.09*x;
518  //double dy = -0.16*x*x+0.16*x;
519  //if (x>0.85) {
520  // continue;
521  //}
522  ffd.control_pts[i_ctl][1] += dy;
523  }
524 
526  //const double target_AoA = 0.5;
527  //const double pi = atan(1.0) * 4.0;
528  //param_target.euler_param.angle_of_attack = target_AoA * pi/170.0;
529  std::shared_ptr < DGBase<dim, double> > dg_target = DGFactory<dim,double>::create_discontinuous_galerkin(&param_target, poly_degree, grid);
530  std::shared_ptr<HighOrderGrid<dim,double>> naca0012_mesh = read_gmsh <dim, dim> ("naca0012.msh",param_target.do_renumber_dofs);
531  dg_target->set_high_order_grid(naca0012_mesh);
532 
533  ffd.deform_mesh (*(dg_target->high_order_grid));
534 
535  dg_target->allocate_system ();
536  dealii::VectorTools::interpolate(dg_target->dof_handler, initial_conditions, dg_target->solution);
537  std::shared_ptr<ODE::ODESolverBase<dim, double>> ode_solver = ODE::ODESolverFactory<dim, double>::create_ODESolver(dg_target);
538  ode_solver->initialize_steady_polynomial_ramping (poly_degree);
539  ode_solver->steady_state();
540 
541  dg_target->output_results_vtk(9998);
542  target_solution = dg_target->solution;
543  }
544  ffd.set_design_variables( ffd_design_variables_indices_dim, ffd_design_variables);
545 
546  std::shared_ptr < DGBase<dim, double> > dg = DGFactory<dim,double>::create_discontinuous_galerkin(&param, poly_degree, grid);
547 
548  //naca0012_mesh->refine_global();
549  std::shared_ptr<HighOrderGrid<dim,double>> naca0012_mesh = read_gmsh <dim, dim> ("naca0012.msh",param.do_renumber_dofs);
550  dg->set_high_order_grid(naca0012_mesh);
551 
552  dg->allocate_system ();
553  dealii::VectorTools::interpolate(dg->dof_handler, initial_conditions, dg->solution);
554  // Create ODE solver and ramp up the solution from p0
555  std::shared_ptr<ODE::ODESolverBase<dim, double>> ode_solver = ODE::ODESolverFactory<dim, double>::create_ODESolver(dg);
556  ode_solver->initialize_steady_polynomial_ramping (poly_degree);
557  // // Solve the steady state problem
558  ode_solver->steady_state();
559 
560  // Reset to initial_grid
561  DealiiVector des_var_sim = dg->solution;
562  DealiiVector des_var_ctl = initial_design_variables;
563  DealiiVector des_var_adj = dg->dual;
564  des_var_adj.add(0.1);
565 
566  const bool has_ownership = false;
567  VectorAdaptor des_var_sim_rol(Teuchos::rcp(&des_var_sim, has_ownership));
568  VectorAdaptor des_var_ctl_rol(Teuchos::rcp(&des_var_ctl, has_ownership));
569  VectorAdaptor des_var_adj_rol(Teuchos::rcp(&des_var_adj, has_ownership));
570 
571  ROL::Ptr<ROL::Vector<double>> des_var_sim_rol_p = ROL::makePtr<VectorAdaptor>(des_var_sim_rol);
572  ROL::Ptr<ROL::Vector<double>> des_var_ctl_rol_p = ROL::makePtr<VectorAdaptor>(des_var_ctl_rol);
573  ROL::Ptr<ROL::Vector<double>> des_var_adj_rol_p = ROL::makePtr<VectorAdaptor>(des_var_adj_rol);
574  auto des_var_p = ROL::makePtr<ROL::Vector_SimOpt<double>>(des_var_sim_rol_p, des_var_ctl_rol_p);
575 
576  ROL::OptimizationProblem<double> opt;
577  Teuchos::ParameterList parlist;
578 
579  TargetWallPressure<dim,nstate,double> target_wall_pressure_functional(dg, target_solution);
580 
583 
584  std::cout << " Current lift = " << lift_functional.evaluate_functional()
585  << ". Current drag = " << drag_functional.evaluate_functional()
586  << std::endl;
587 
588  double lift_target = lift_functional.evaluate_functional() * 1.01;
589  //double lift_target = lift_functional.evaluate_functional() * 2.0;
590  //const double lift_penalty = 1;//0.1;
591  const double lift_penalty = 1;
592 
593 
594  ffd.output_ffd_vtu(8999);
595  std::shared_ptr<BaseParameterization<dim>> design_parameterization =
596  std::make_shared<FreeFormDeformationParameterization<dim>>(dg->high_order_grid, ffd, ffd_design_variables_indices_dim);
597 
598  auto con = ROL::makePtr<FlowConstraints<dim>>(dg, design_parameterization);
599  std::shared_ptr<MatrixType> precomputed_dXvdXp = std::make_shared<MatrixType> ();
600  precomputed_dXvdXp->reinit(con->dXvdXp);
601  precomputed_dXvdXp->copy_from(con->dXvdXp);
602  //int flow_constraints_check_error = check_flow_constraints<dim,nstate>( nx_ffd, con, des_var_sim_rol_p, des_var_ctl_rol_p, des_var_adj_rol_p);
603  std::cout << " Constructing lift ROL objective " << std::endl;
604  auto lift_obj = ROL::makePtr<ROLObjectiveSimOpt<dim,nstate>>( lift_functional, design_parameterization, precomputed_dXvdXp);
605  std::cout << " Constructing lift ROL constraint " << std::endl;
606  auto lift_con = ROL::makePtr<PHiLiP::ConstraintFromObjective_SimOpt<double>> (lift_obj, lift_target);
607 
608  //int objective_check_error = check_objective<dim,nstate>( nx_ffd, dg, lift_obj, con, des_var_sim_rol_p, des_var_ctl_rol_p, des_var_adj_rol_p);
609 
610  std::cout << " Constructing drag ROL objective " << std::endl;
611  auto drag_obj = ROL::makePtr<ROLObjectiveSimOpt<dim,nstate>>( drag_functional, design_parameterization, precomputed_dXvdXp);
612 
613  //objective_check_error = check_objective<dim,nstate>( nx_ffd, dg, drag_obj, con, des_var_sim_rol_p, des_var_ctl_rol_p, des_var_adj_rol_p);
614 
615  std::cout << " Constructing drag quadratic penalty lift ROL objective " << std::endl;
616  ROL::SingletonVector<double> zero_lagrange_mult(0.0);
617  ROL::SingletonVector<double> single_contraint(0.0);
618  ROL::ParameterList empty_parlist;
619 
620  //auto drag_quad_penalty_lift = ROL::makePtr<ROL::AugmentedLagrangian_SimOpt<double>> (drag_obj, lift_con, zero_lagrange_mult, lift_penalty, *des_var_sim_rol_p, *des_var_ctl_rol_p, single_contraint, empty_parlist);
621  //auto obj = drag_quad_penalty_lift;
622 
623  auto pressure_obj = ROL::makePtr<ROLObjectiveSimOpt<dim,nstate>>( target_wall_pressure_functional, design_parameterization, precomputed_dXvdXp);
624  auto obj = pressure_obj;
625 
626  //objective_check_error = check_objective<dim,nstate>( nx_ffd, dg, obj, con, des_var_sim_rol_p, des_var_ctl_rol_p, des_var_adj_rol_p);
627 
628  double tol = 0.0;
629  std::cout << "Drag with quadratic lift penalty = " << obj->value(*des_var_sim_rol_p, *des_var_ctl_rol_p, tol) << std::endl;
630 
631  dg->output_results_vtk(9999);
632 
633 
634  //(void) objective_check_error;
635  //(void) flow_constraints_check_error;
636 
637 
638  double timing_start, timing_end;
639  timing_start = MPI_Wtime();
640  // Verbosity setting
641  parlist.sublist("General").set("Print Verbosity", 1);
642 
643  //parlist.sublist("Status Test").set("Gradient Tolerance", 1e-9);
644  parlist.sublist("Status Test").set("Gradient Tolerance", 1e-7);
645  parlist.sublist("Status Test").set("Iteration Limit", max_design_cycle);
646 
647  parlist.sublist("Step").sublist("Line Search").set("User Defined Initial Step Size",true);
648  parlist.sublist("Step").sublist("Line Search").set("Initial Step Size",3e-1); // Might be needed for p2 BFGS
649  parlist.sublist("Step").sublist("Line Search").set("Initial Step Size",1e-0);
650  parlist.sublist("Step").sublist("Line Search").set("Function Evaluation Limit",30); // 0.5^30 ~ 1e-10
651  parlist.sublist("Step").sublist("Line Search").set("Accept Linesearch Minimizer",true);//false);
652  parlist.sublist("Step").sublist("Line Search").sublist("Line-Search Method").set("Type",line_search_method);
653  parlist.sublist("Step").sublist("Line Search").sublist("Curvature Condition").set("Type",line_search_curvature);
654 
655 
656  parlist.sublist("General").sublist("Secant").set("Type","Limited-Memory BFGS");
657  parlist.sublist("General").sublist("Secant").set("Maximum Storage",max_design_cycle);
658 
659  parlist.sublist("Full Space").set("Preconditioner",preconditioner_string);
660 
661  ROL::Ptr< const ROL::AlgorithmState <double> > algo_state;
662  n_vmult = 0;
663  dRdW_form = 0;
664  dRdW_mult = 0;
665  dRdX_mult = 0;
666  d2R_mult = 0;
667 
668  switch (opt_type) {
669  case full_space_composite_step: {
670  // Full space problem
671  auto dual_sim_p = des_var_sim_rol_p->clone();
672  opt = ROL::OptimizationProblem<double> ( obj, des_var_p, con, dual_sim_p );
673 
674  // Set parameters.
675 
676  parlist.sublist("Step").set("Type","Composite Step");
677  ROL::ParameterList& steplist = parlist.sublist("Step").sublist("Composite Step");
678  steplist.set("Initial Radius", 1e2);
679  steplist.set("Use Constraint Hessian", true); // default is true
680  steplist.set("Output Level", 1);
681 
682  steplist.sublist("Optimality System Solver").set("Nominal Relative Tolerance", 1e-8); // default 1e-8
683  steplist.sublist("Optimality System Solver").set("Fix Tolerance", true);
684  const int cg_iteration_limit = 200;
685  steplist.sublist("Tangential Subproblem Solver").set("Iteration Limit", cg_iteration_limit);
686  steplist.sublist("Tangential Subproblem Solver").set("Relative Tolerance", 1e-2);
687 
688  *outStream << "Starting optimization with " << n_design_variables << "..." << std::endl;
689  ROL::OptimizationSolver<double> solver( opt, parlist );
690  solver.solve( *outStream );
691  algo_state = solver.getAlgorithmState();
692 
693  break;
694  }
695  case reduced_space_bfgs:
696  [[fallthrough]];
697  case reduced_space_newton: {
698  // Reduced space problem
699  const bool storage = true;
700  const bool useFDHessian = false;
701  auto robj = ROL::makePtr<ROL::Reduced_Objective_SimOpt<double>>( obj, con, des_var_sim_rol_p, des_var_ctl_rol_p, des_var_adj_rol_p, storage, useFDHessian);
702  opt = ROL::OptimizationProblem<double> ( robj, des_var_ctl_rol_p );
703  ROL::EProblem problemType = opt.getProblemType();
704  std::cout << ROL::EProblemToString(problemType) << std::endl;
705 
706  parlist.sublist("Step").set("Type","Line Search");
707 
708  parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").set("Type", descent_method);
709  if (descent_method == "Newton-Krylov") {
710  parlist.sublist("General").sublist("Secant").set("Use as Preconditioner", true);
711 
712  //const double em4 = 1e-4, em2 = 1e-2;
713  const double em4 = 1e-5, em2 = 1e-2;
714  //parlist.sublist("General").sublist("Krylov").set("Type","Conjugate Gradients");
715 
716  //const double em4 = 1e-8, em2 = 1e-6;
717  parlist.sublist("General").sublist("Krylov").set("Type","GMRES");
718  parlist.sublist("General").sublist("Krylov").set("Absolute Tolerance", em4);
719  parlist.sublist("General").sublist("Krylov").set("Relative Tolerance", em2);
720  const int cg_iteration_limit = n_design_variables;
721  parlist.sublist("General").sublist("Krylov").set("Iteration Limit", cg_iteration_limit);
722  parlist.sublist("General").set("Inexact Hessian-Times-A-Vector",false);
723  }
724 
725  *outStream << "Starting optimization with " << n_design_variables << "..." << std::endl;
726  ROL::OptimizationSolver<double> solver( opt, parlist );
727  solver.solve( *outStream );
728  algo_state = solver.getAlgorithmState();
729  break;
730  }
731  case full_space_birosghattas: {
732  auto full_space_step = ROL::makePtr<ROL::FullSpace_BirosGhattas<double>>(parlist);
733  auto status_test = ROL::makePtr<ROL::StatusTest<double>>(parlist);
734  const bool printHeader = true;
735  ROL::Algorithm<double> algorithm(full_space_step, status_test, printHeader);
736  //des_var_adj_rol_p->setScalar(1.0);
737  algorithm.run(*des_var_p, *des_var_adj_rol_p, *obj, *con, true, *outStream);
738  algo_state = algorithm.getState();
739 
740  break;
741  }
742  }
743  std::cout << " Current lift = " << lift_functional.evaluate_functional()
744  << ". Current drag = " << drag_functional.evaluate_functional()
745  << ". Penalty = " << lift_penalty
746  << ". Drag with quadratic lift penalty = " << obj->value(*des_var_sim_rol_p, *des_var_ctl_rol_p, tol);
747  static int resulting_optimization = 5000;
748  std::cout << "Outputting final grid resulting_optimization: " << resulting_optimization << std::endl;
749  dg->output_results_vtk(resulting_optimization++);
750 
751 
752  timing_end = MPI_Wtime();
753  *outStream << "The process took " << timing_end - timing_start << " seconds to run." << std::endl;
754 
755  *outStream << "Total n_vmult for algorithm " << n_vmult << std::endl;
756 
757  test_error += algo_state->statusFlag;
758 
759  filebuffer.close();
760 
761  if (opt_type != OptimizationAlgorithm::full_space_birosghattas) break;
762  }
763  }
764 
765  return test_error;
766 }
767 
768 
769 #if PHILIP_DIM==2
771 #endif
772 
773 } // Tests namespace
774 } // PHiLiP namespace
775 
776 
void get_design_variables(const std::vector< std::pair< unsigned int, unsigned int > > &ffd_design_variables_indices_dim, dealii::LinearAlgebra::distributed::Vector< double > &vector_to_copy_into) const
Copies the desired control points from FreeFormDeformation object into vector_to_copy_into.
PartialDifferentialEquation pde_type
Store the PDE type to be solved.
const double mach_inf
Farfield Mach number.
Definition: euler.h:113
Function used to evaluate farfield conservative solution.
const double angle_of_attack
Angle of attack.
Definition: euler.h:118
Parameters related to the manufactured convergence study.
EulerNACAOptimization()=delete
Constructor. Deleted the default constructor since it should not be used.
const MPI_Comm mpi_communicator
MPI communicator.
Definition: tests.h:39
std::vector< dealii::Point< dim > > control_pts
Control points of the FFD box used to deform the geometry.
void deform_mesh(HighOrderGrid< dim, double > &high_order_grid) const
Deform HighOrderGrid using its initial volume_nodes to retrieve the deformed set of volume_nodes...
int optimize(const unsigned int nx_ffd, const unsigned int poly_degree) const
Actual test for which the number of design variables can be inputted.
Files for the baseline physics.
Definition: ADTypes.hpp:10
std::array< unsigned int, dim > global_to_grid(const unsigned int global_ictl) const
Given a control points&#39; global index return its ijk coordinate.
const double side_slip_angle
Sideslip angle.
Definition: euler.h:122
Free form deformation class from Sederberg 1986.
unsigned int dimension
Number of dimensions. Note that it has to match the executable PHiLiP_xD.
Main parameter class that contains the various other sub-parameter classes.
ManufacturedConvergenceStudyParam manufactured_convergence_study_param
Contains parameters for manufactured convergence study.
Use DGBase as a Simulation Constraint ROL::Constraint_SimOpt.
Full-space system preconditioner based on the reduced-space.
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
Definition: tests.h:20
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.
Definition: dg_factory.cpp:10
bool do_renumber_dofs
Flag for renumbering DOFs.
const int mpi_rank
MPI rank.
Definition: tests.h:40
Performs grid convergence for various polynomial degrees.
void output_ffd_vtu(const unsigned int cycle) const
Output a .vtu file of the FFD box to visualize.
int run_test() const
Grid convergence on Euler Gaussian Bump.
real evaluate_functional(const bool compute_dIdW=false, const bool compute_dIdX=false, const bool compute_d2I=false) override
Destructor.
Definition: lift_drag.cpp:106
DGBase is independent of the number of state variables.
Definition: dg_base.hpp:82
const double ref_length
Reference length.
Definition: euler.h:104
const unsigned int n_control_pts
Total number of control points.
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.
Definition: tests.h:17
void set_design_variables(const std::vector< std::pair< unsigned int, unsigned int > > &ffd_design_variables_indices_dim, const dealii::LinearAlgebra::distributed::Vector< double > &vector_to_copy_from)
Copies the desired control points from vector_to_copy_from into FreeFormDeformation object...