4 #include <deal.II/grid/grid_generator.h> 6 #include <deal.II/numerics/vector_tools.h> 8 #include <deal.II/optimization/rol/vector_adaptor.h> 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" 17 #include "euler_bump_optimization.h" 19 #include "physics/initial_conditions/initial_condition_function.h" 20 #include "physics/euler.h" 21 #include "dg/dg_factory.hpp" 22 #include "ode_solver/ode_solver_factory.h" 24 #include "functional/target_boundary_functional.h" 26 #include "mesh/grids/gaussian_bump.h" 27 #include "mesh/free_form_deformation.h" 29 #include "optimization/rol_to_dealii_vector.hpp" 30 #include "optimization/flow_constraints.hpp" 31 #include "optimization/rol_objective.hpp" 32 #include "optimization/design_parameterization/ffd_parameterization.hpp" 34 #include "optimization/full_space_step.hpp" 36 #include "global_counter.hpp" 41 enum OptimizationAlgorithm { full_space_birosghattas, full_space_composite_step, reduced_space_bfgs, reduced_space_newton };
46 const std::vector<BirosGhattasPreconditioner> precond_list { P2, P2A, P4, P4A };
47 const std::vector<OptimizationAlgorithm> opt_list { full_space_birosghattas, reduced_space_bfgs, reduced_space_newton };
50 const double BUMP_HEIGHT = 0.0625;
51 const double TARGET_BUMP_HEIGHT = 0.5*BUMP_HEIGHT;
52 const double CHANNEL_LENGTH = 3.0;
53 const double CHANNEL_HEIGHT = 0.8;
54 const unsigned int NY_CELL = 5;
55 const unsigned int NX_CELL = 10*NY_CELL;
57 const unsigned int POLY_START = 0;
58 const unsigned int POLY_END = 1;
60 const unsigned int n_des_var_start = 20;
61 const unsigned int n_des_var_end = 40;
62 const unsigned int n_des_var_step = 20;
64 const int max_design_cycle = 1000;
65 const int cg_iteration_limit = 200;
67 const std::string line_search_curvature =
68 "Null Curvature Condition";
71 const std::string line_search_method =
76 template <
int dim,
int nstate>
82 template<
int dim,
int nstate>
87 std::filebuf filebuffer;
88 if (this->
mpi_rank == 0) filebuffer.open (
"optimization.log", std::ios::out);
89 if (this->
mpi_rank == 0) filebuffer.close();
91 for (
unsigned int poly_degree = POLY_START; poly_degree <= POLY_END; ++poly_degree) {
92 for (
unsigned int n_des_var = n_des_var_start; n_des_var <= n_des_var_end; n_des_var += n_des_var_step) {
97 const unsigned int nx_ffd = n_des_var + 2;
104 template<
int dim,
int nstate>
110 for (
auto const opt_type : opt_list) {
111 for (
auto const precond_type : precond_list) {
113 std::string opt_output_name =
"";
114 std::string descent_method =
"";
115 std::string preconditioner_string =
"";
117 case full_space_birosghattas: {
118 opt_output_name =
"full_space";
119 switch(precond_type) {
121 opt_output_name +=
"_p2";
122 preconditioner_string =
"P2";
126 opt_output_name +=
"_p2a";
127 preconditioner_string =
"P2A";
131 opt_output_name +=
"_p4";
132 preconditioner_string =
"P4";
136 opt_output_name +=
"_p4a";
137 preconditioner_string =
"P4A";
141 opt_output_name +=
"_identity";
142 preconditioner_string =
"identity";
148 case full_space_composite_step: {
149 opt_output_name =
"full_space_composite_step";
152 case reduced_space_bfgs: {
153 opt_output_name =
"reduced_space_bfgs";
154 descent_method =
"Quasi-Newton Method";
157 case reduced_space_newton: {
158 opt_output_name =
"reduced_space_newton";
159 descent_method =
"Newton-Krylov";
163 opt_output_name = opt_output_name +
"_" 164 + std::to_string(NX_CELL) +
"X" + std::to_string(NY_CELL) +
"_" 165 +
"P" + std::to_string(poly_degree);
169 std::filebuf filebuffer;
170 if (this->
mpi_rank == 0) filebuffer.open (
"optimization_"+opt_output_name+
"_"+std::to_string(nx_ffd-2)+
".log", std::ios::out);
172 std::ostream ostr(&filebuffer);
174 Teuchos::RCP<std::ostream> outStream;
175 if (this->
mpi_rank == 0) outStream = ROL::makePtrFromRef(ostr);
176 else if (this->
mpi_rank == 1) outStream = ROL::makePtrFromRef(std::cout);
177 else outStream = ROL::makePtrFromRef(bhs);
180 using DealiiVector = dealii::LinearAlgebra::distributed::Vector<double>;
181 using VectorAdaptor = dealii::Rol::VectorAdaptor<DealiiVector>;
183 using GridEnum = ManParam::GridEnum;
187 Assert(param.
pde_type == param.PartialDifferentialEquation::euler, dealii::ExcNotImplemented());
196 param.euler_param.gamma_gas,
202 std::vector<unsigned int> n_subdivisions(dim);
210 n_subdivisions[1] = NY_CELL;
211 n_subdivisions[0] = NX_CELL;
213 using Triangulation = dealii::parallel::distributed::Triangulation<dim>;
214 std::shared_ptr <Triangulation> grid = std::make_shared<Triangulation> (
216 typename dealii::Triangulation<dim>::MeshSmoothing(
217 dealii::Triangulation<dim>::smoothing_on_refinement |
218 dealii::Triangulation<dim>::smoothing_on_coarsening));
221 const dealii::Point<dim> ffd_origin(-1.4,-0.1);
222 const std::array<double,dim> ffd_rectangle_lengths = {{2.8,0.6}};
223 const std::array<unsigned int,dim> ffd_ndim_control_pts = {{nx_ffd,2}};
226 unsigned int n_design_variables = 0;
229 std::vector< std::pair< unsigned int, unsigned int > > ffd_design_variables_indices_dim;
230 for (
unsigned int i_ctl = 0; i_ctl < ffd.
n_control_pts; ++i_ctl) {
232 const std::array<unsigned int,dim> ijk = ffd.
global_to_grid ( i_ctl );
233 for (
unsigned int d_ffd = 0; d_ffd < dim; ++d_ffd) {
236 || ijk[0] == ffd_ndim_control_pts[0] - 1
242 ++n_design_variables;
243 ffd_design_variables_indices_dim.push_back(std::make_pair(i_ctl, d_ffd));
247 const dealii::IndexSet row_part = dealii::Utilities::MPI::create_evenly_distributed_partitioning(MPI_COMM_WORLD,n_design_variables);
248 dealii::IndexSet ghost_row_part(n_design_variables);
249 ghost_row_part.add_range(0,n_design_variables);
250 DealiiVector ffd_design_variables(row_part,ghost_row_part,MPI_COMM_WORLD);
255 const auto initial_design_variables = ffd_design_variables;
258 DealiiVector target_bump_solution;
261 Grids::gaussian_bump(*grid, n_subdivisions, CHANNEL_LENGTH, CHANNEL_HEIGHT, 0.5*BUMP_HEIGHT);
266 dg->allocate_system ();
267 dealii::VectorTools::interpolate(dg->dof_handler, initial_conditions, dg->solution);
270 ode_solver->initialize_steady_polynomial_ramping (poly_degree);
272 ode_solver->steady_state();
274 dg->output_results_vtk(9998);
276 target_bump_solution = dg->solution;
279 double timing_start = MPI_Wtime();
281 DealiiVector target_ffd_solution;
285 Grids::gaussian_bump(*grid, n_subdivisions, CHANNEL_LENGTH, CHANNEL_HEIGHT, BUMP_HEIGHT);
287 ffd_design_variables = initial_design_variables;
288 ffd_design_variables.update_ghost_values();
293 dg->allocate_system ();
294 dealii::VectorTools::interpolate(dg->dof_handler, initial_conditions, dg->solution);
297 ode_solver->initialize_steady_polynomial_ramping (poly_degree);
299 ode_solver->steady_state();
301 dg->output_results_vtk(9999);
302 dg->set_dual(dg->solution);
305 DealiiVector des_var_sim = dg->solution;
306 DealiiVector des_var_ctl = initial_design_variables;
307 DealiiVector des_var_adj = dg->dual;
309 const bool has_ownership =
false;
310 VectorAdaptor des_var_sim_rol(Teuchos::rcp(&des_var_sim, has_ownership));
311 VectorAdaptor des_var_ctl_rol(Teuchos::rcp(&des_var_ctl, has_ownership));
312 VectorAdaptor des_var_adj_rol(Teuchos::rcp(&des_var_adj, has_ownership));
314 ROL::Ptr<ROL::Vector<double>> des_var_sim_rol_p = ROL::makePtr<VectorAdaptor>(des_var_sim_rol);
315 ROL::Ptr<ROL::Vector<double>> des_var_ctl_rol_p = ROL::makePtr<VectorAdaptor>(des_var_ctl_rol);
316 ROL::Ptr<ROL::Vector<double>> des_var_adj_rol_p = ROL::makePtr<VectorAdaptor>(des_var_adj_rol);
319 const bool functional_uses_solution_values =
true, functional_uses_solution_gradient =
false;
321 std::shared_ptr<BaseParameterization<dim>> design_parameterization =
322 std::make_shared<FreeFormDeformationParameterization<dim>>(dg->high_order_grid, ffd, ffd_design_variables_indices_dim);
324 auto obj = ROL::makePtr<ROLObjectiveSimOpt<dim,nstate>>(target_bump_functional, design_parameterization);
325 auto con = ROL::makePtr<FlowConstraints<dim>>(dg, design_parameterization);
326 const bool storage =
false;
327 const bool useFDHessian =
false;
328 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);
330 ROL::OptimizationProblem<double> opt = ROL::OptimizationProblem<double> ( robj, des_var_ctl_rol_p );
331 ROL::EProblem problemType = opt.getProblemType();
332 std::cout << ROL::EProblemToString(problemType) << std::endl;
334 Teuchos::ParameterList parlist;
335 parlist.sublist(
"Status Test").set(
"Gradient Tolerance", 1e-5);
336 parlist.sublist(
"Status Test").set(
"Iteration Limit", max_design_cycle);
338 parlist.sublist(
"Step").set(
"Type",
"Line Search");
339 parlist.sublist(
"Step").sublist(
"Line Search").sublist(
"Descent Method").set(
"Type",
"Quasi-Newton Method");
340 parlist.sublist(
"Step").sublist(
"Line Search").set(
"Initial Step Size",0.1);
341 parlist.sublist(
"Step").sublist(
"Line Search").set(
"User Defined Initial Step Size",
true);
342 parlist.sublist(
"Step").sublist(
"Line Search").sublist(
"Line-Search Method").set(
"Type",line_search_method);
343 parlist.sublist(
"Step").sublist(
"Line Search").sublist(
"Curvature Condition").set(
"Type",line_search_curvature);
345 parlist.sublist(
"General").sublist(
"Secant").set(
"Type",
"Limited-Memory BFGS");
346 parlist.sublist(
"General").sublist(
"Secant").set(
"Maximum Storage",max_design_cycle);
348 *outStream <<
"Starting optimization with " << n_design_variables <<
"..." << std::endl;
349 *outStream <<
"Optimizing FFD points to obtain target Gaussian bump..." << std::endl;
350 ROL::OptimizationSolver<double> solver( opt, parlist );
351 solver.solve( *outStream );
353 ROL::Ptr< const ROL::AlgorithmState <double> > algo_state = solver.getAlgorithmState();
355 test_error += algo_state->statusFlag;
357 target_ffd_solution = dg->solution;
359 *outStream <<
" Done target optimization..." << std::endl;
360 *outStream <<
" Resetting problem to initial conditions and target previous FFD points "<< std::endl;
361 *outStream <<
" and aim for machine precision functional value...." << std::endl;
362 double timing_end = MPI_Wtime();
363 *outStream <<
"The process took " << timing_end - timing_start <<
" seconds to run." << std::endl;
367 Grids::gaussian_bump(*grid, n_subdivisions, CHANNEL_LENGTH, CHANNEL_HEIGHT, BUMP_HEIGHT);
369 ffd_design_variables = initial_design_variables;
370 ffd_design_variables.update_ghost_values();
375 dg->allocate_system ();
376 dealii::VectorTools::interpolate(dg->dof_handler, initial_conditions, dg->solution);
380 ode_solver->initialize_steady_polynomial_ramping (poly_degree);
382 ode_solver->steady_state();
385 DealiiVector des_var_sim = dg->solution;
386 DealiiVector des_var_ctl = initial_design_variables;
387 DealiiVector des_var_adj = dg->dual;
389 const bool has_ownership =
false;
390 VectorAdaptor des_var_sim_rol(Teuchos::rcp(&des_var_sim, has_ownership));
391 VectorAdaptor des_var_ctl_rol(Teuchos::rcp(&des_var_ctl, has_ownership));
392 VectorAdaptor des_var_adj_rol(Teuchos::rcp(&des_var_adj, has_ownership));
394 ROL::Ptr<ROL::Vector<double>> des_var_sim_rol_p = ROL::makePtr<VectorAdaptor>(des_var_sim_rol);
395 ROL::Ptr<ROL::Vector<double>> des_var_ctl_rol_p = ROL::makePtr<VectorAdaptor>(des_var_ctl_rol);
396 ROL::Ptr<ROL::Vector<double>> des_var_adj_rol_p = ROL::makePtr<VectorAdaptor>(des_var_adj_rol);
398 ROL::OptimizationProblem<double> opt;
399 Teuchos::ParameterList parlist;
402 const bool functional_uses_solution_values =
true, functional_uses_solution_gradient =
false;
404 std::shared_ptr<BaseParameterization<dim>> design_parameterization =
405 std::make_shared<FreeFormDeformationParameterization<dim>>(dg->high_order_grid, ffd, ffd_design_variables_indices_dim);
407 auto obj = ROL::makePtr<ROLObjectiveSimOpt<dim,nstate>>( target_ffd_functional, design_parameterization);
408 auto con = ROL::makePtr<FlowConstraints<dim>>(dg, design_parameterization);
410 timing_start = MPI_Wtime();
412 parlist.sublist(
"General").set(
"Print Verbosity", 1);
413 auto des_var_p = ROL::makePtr<ROL::Vector_SimOpt<double>>(des_var_sim_rol_p, des_var_ctl_rol_p);
415 parlist.sublist(
"Status Test").set(
"Gradient Tolerance", 1e-9);
416 parlist.sublist(
"Status Test").set(
"Iteration Limit", max_design_cycle);
418 parlist.sublist(
"Step").sublist(
"Line Search").set(
"User Defined Initial Step Size",
true);
419 parlist.sublist(
"Step").sublist(
"Line Search").set(
"Initial Step Size",1e-0);
420 parlist.sublist(
"Step").sublist(
"Line Search").set(
"Function Evaluation Limit",30);
421 parlist.sublist(
"Step").sublist(
"Line Search").set(
"Accept Linesearch Minimizer",
true);
422 parlist.sublist(
"Step").sublist(
"Line Search").sublist(
"Line-Search Method").set(
"Type",line_search_method);
423 parlist.sublist(
"Step").sublist(
"Line Search").sublist(
"Curvature Condition").set(
"Type",line_search_curvature);
426 parlist.sublist(
"General").sublist(
"Secant").set(
"Type",
"Limited-Memory BFGS");
427 parlist.sublist(
"General").sublist(
"Secant").set(
"Maximum Storage",max_design_cycle);
429 parlist.sublist(
"Full Space").set(
"Preconditioner",preconditioner_string);
431 ROL::Ptr< const ROL::AlgorithmState <double> > algo_state;
439 case full_space_composite_step: {
441 auto dual_sim_p = des_var_sim_rol_p->clone();
442 opt = ROL::OptimizationProblem<double> ( obj, des_var_p, con, dual_sim_p );
446 parlist.sublist(
"Step").set(
"Type",
"Composite Step");
447 ROL::ParameterList& steplist = parlist.sublist(
"Step").sublist(
"Composite Step");
448 steplist.set(
"Initial Radius", 1e2);
449 steplist.set(
"Use Constraint Hessian",
true);
450 steplist.set(
"Output Level", 1);
452 steplist.sublist(
"Optimality System Solver").set(
"Nominal Relative Tolerance", 1e-8);
453 steplist.sublist(
"Optimality System Solver").set(
"Fix Tolerance",
true);
454 steplist.sublist(
"Tangential Subproblem Solver").set(
"Iteration Limit", cg_iteration_limit);
455 steplist.sublist(
"Tangential Subproblem Solver").set(
"Relative Tolerance", 1e-2);
457 *outStream <<
"Starting optimization with " << n_design_variables <<
"..." << std::endl;
458 ROL::OptimizationSolver<double> solver( opt, parlist );
459 solver.solve( *outStream );
460 algo_state = solver.getAlgorithmState();
464 case reduced_space_bfgs:
466 case reduced_space_newton: {
468 const bool storage =
true;
469 const bool useFDHessian =
false;
470 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);
471 opt = ROL::OptimizationProblem<double> ( robj, des_var_ctl_rol_p );
472 ROL::EProblem problemType = opt.getProblemType();
473 std::cout << ROL::EProblemToString(problemType) << std::endl;
475 parlist.sublist(
"Step").set(
"Type",
"Line Search");
477 parlist.sublist(
"Step").sublist(
"Line Search").sublist(
"Descent Method").set(
"Type", descent_method);
478 if (descent_method ==
"Newton-Krylov") {
479 parlist.sublist(
"General").sublist(
"Secant").set(
"Use as Preconditioner",
true);
481 const double em4 = 1e-8, em2 = 1e-6;
483 parlist.sublist(
"General").sublist(
"Krylov").set(
"Type",
"GMRES");
484 parlist.sublist(
"General").sublist(
"Krylov").set(
"Absolute Tolerance", em4);
485 parlist.sublist(
"General").sublist(
"Krylov").set(
"Relative Tolerance", em2);
486 parlist.sublist(
"General").sublist(
"Krylov").set(
"Iteration Limit", cg_iteration_limit);
487 parlist.sublist(
"General").set(
"Inexact Hessian-Times-A-Vector",
false);
490 *outStream <<
"Starting optimization with " << n_design_variables <<
"..." << std::endl;
491 ROL::OptimizationSolver<double> solver( opt, parlist );
492 solver.solve( *outStream );
493 algo_state = solver.getAlgorithmState();
496 case full_space_birosghattas: {
497 auto full_space_step = ROL::makePtr<ROL::FullSpace_BirosGhattas<double>>(parlist);
498 auto status_test = ROL::makePtr<ROL::StatusTest<double>>(parlist);
499 const bool printHeader =
true;
500 ROL::Algorithm<double> algorithm(full_space_step, status_test, printHeader);
502 algorithm.run(*des_var_p, *des_var_adj_rol_p, *obj, *con,
true, *outStream);
503 algo_state = algorithm.getState();
510 timing_end = MPI_Wtime();
511 *outStream <<
"The process took " << timing_end - timing_start <<
" seconds to run." << std::endl;
513 *outStream <<
"Total n_vmult for algorithm " << n_vmult << std::endl;
515 test_error += algo_state->statusFlag;
519 if (opt_type != OptimizationAlgorithm::full_space_birosghattas)
break;
PartialDifferentialEquation pde_type
Store the PDE type to be solved.
const double mach_inf
Farfield Mach number.
Function used to evaluate farfield conservative solution.
const double angle_of_attack
Angle of attack.
Parameters related to the manufactured convergence study.
const MPI_Comm mpi_communicator
MPI communicator.
Files for the baseline physics.
const double side_slip_angle
Sideslip angle.
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.
Full-space system preconditioner based on the reduced-space.
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.
EulerBumpOptimization()=delete
Constructor. Deleted the default constructor since it should not be used.
const int mpi_rank
MPI rank.
Performs grid convergence for various polynomial degrees.
int run_test() const
Grid convergence on Euler Gaussian Bump.
int optimize_target_bump(const unsigned int nx_ffd, const unsigned int poly_degree) const
Actual test for which the number of design variables can be inputted.
const double ref_length
Reference length.
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.