libMesh
tao_optimization_solver.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 #include "libmesh/libmesh_common.h"
21 
22 #if defined(LIBMESH_HAVE_PETSC_TAO) && !defined(LIBMESH_USE_COMPLEX_NUMBERS)
23 
24 
25 // C++ includes
26 
27 // Local Includes
28 #include "libmesh/libmesh_logging.h"
29 #include "libmesh/petsc_vector.h"
30 #include "libmesh/petsc_matrix.h"
31 #include "libmesh/dof_map.h"
32 #include "libmesh/tao_optimization_solver.h"
33 #include "libmesh/equation_systems.h"
34 
35 namespace libMesh
36 {
37 
38 //--------------------------------------------------------------------
39 // Functions with C linkage to pass to Tao. Tao will call these
40 // methods as needed.
41 //
42 // Since they must have C linkage they have no knowledge of a namespace.
43 // Give them an obscure name to avoid namespace pollution.
44 extern "C"
45 {
46 
47  //---------------------------------------------------------------
48  // This function is called by Tao to evaluate objective function at x
49  PetscErrorCode
50  __libmesh_tao_objective (Tao /*tao*/, Vec x, PetscReal * objective, void * ctx)
51  {
52  PetscFunctionBegin;
53 
54  LOG_SCOPE("objective()", "TaoOptimizationSolver");
55 
56  libmesh_assert(x);
57  libmesh_assert(objective);
59 
60  // ctx should be a pointer to the solver (it was passed in as void *)
62  static_cast<TaoOptimizationSolver<Number> *> (ctx);
63 
64  OptimizationSystem & sys = solver->system();
65 
66  // We'll use current_local_solution below, so let's ensure that it's consistent
67  // with the vector x that was passed in.
68  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
69  PetscVector<Number> X(x, sys.comm());
70 
71  // Perform a swap so that sys.solution points to the input vector
72  // "x", update sys.current_local_solution based on "x", then swap
73  // back.
74  X.swap(X_sys);
75  sys.update();
76  X.swap(X_sys);
77 
78  // Enforce constraints (if any) exactly on the
79  // current_local_solution. This is the solution vector that is
80  // actually used in the computation of the objective function
81  // below, and is not locked by debug-enabled PETSc the way that
82  // the solution vector is.
83  sys.get_dof_map().enforce_constraints_exactly(sys, sys.current_local_solution.get());
84 
85  if (solver->objective_object != nullptr)
86  (*objective) = PS(solver->objective_object->objective(*(sys.current_local_solution), sys));
87  else
88  libmesh_error_msg("Objective function not defined in __libmesh_tao_objective");
89 
90  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
91  }
92 
93 
94 
95  //---------------------------------------------------------------
96  // This function is called by Tao to evaluate the gradient at x
97  PetscErrorCode
98  __libmesh_tao_gradient(Tao /*tao*/, Vec x, Vec g, void * ctx)
99  {
100  PetscFunctionBegin;
101 
102  LOG_SCOPE("gradient()", "TaoOptimizationSolver");
103 
104  libmesh_assert(x);
105  libmesh_assert(g);
107 
108  // ctx should be a pointer to the solver (it was passed in as void *)
110  static_cast<TaoOptimizationSolver<Number> *> (ctx);
111 
112  OptimizationSystem & sys = solver->system();
113 
114  // We'll use current_local_solution below, so let's ensure that it's consistent
115  // with the vector x that was passed in.
116  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
117  PetscVector<Number> X(x, sys.comm());
118 
119  // Perform a swap so that sys.solution points to the input vector
120  // "x", update sys.current_local_solution based on "x", then swap
121  // back.
122  X.swap(X_sys);
123  sys.update();
124  X.swap(X_sys);
125 
126  // We'll also pass the gradient in to the assembly routine
127  // so let's make a PETSc vector for that too.
128  PetscVector<Number> gradient(g, sys.comm());
129 
130  // Clear the gradient prior to assembly
131  gradient.zero();
132 
133  // Enforce constraints exactly on the current_local_solution.
134  sys.get_dof_map().enforce_constraints_exactly(sys, sys.current_local_solution.get());
135 
136  if (solver->gradient_object != nullptr)
137  solver->gradient_object->gradient(*(sys.current_local_solution), gradient, sys);
138  else
139  libmesh_error_msg("Gradient function not defined in __libmesh_tao_gradient");
140 
141  gradient.close();
142 
143  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
144  }
145 
146  //---------------------------------------------------------------
147  // This function is called by Tao to evaluate the Hessian at x
148  PetscErrorCode
149  __libmesh_tao_hessian(Tao /*tao*/, Vec x, Mat h, Mat pc, void * ctx)
150  {
151  PetscFunctionBegin;
152 
153  LOG_SCOPE("hessian()", "TaoOptimizationSolver");
154 
155  libmesh_assert(x);
156  libmesh_assert(h);
157  libmesh_assert(pc);
159 
160  // ctx should be a pointer to the solver (it was passed in as void *)
162  static_cast<TaoOptimizationSolver<Number> *> (ctx);
163 
164  OptimizationSystem & sys = solver->system();
165 
166  // We'll use current_local_solution below, so let's ensure that it's consistent
167  // with the vector x that was passed in.
168  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
169  PetscVector<Number> X(x, sys.comm());
170 
171  // Perform a swap so that sys.solution points to the input vector
172  // "x", update sys.current_local_solution based on "x", then swap
173  // back.
174  X.swap(X_sys);
175  sys.update();
176  X.swap(X_sys);
177 
178  // Let's also wrap pc and h in PetscMatrix objects for convenience
179  PetscMatrix<Number> PC(pc, sys.comm());
180  PetscMatrix<Number> hessian(h, sys.comm());
181  PC.attach_dof_map(sys.get_dof_map());
182  hessian.attach_dof_map(sys.get_dof_map());
183 
184  // Enforce constraints exactly on the current_local_solution.
185  sys.get_dof_map().enforce_constraints_exactly(sys, sys.current_local_solution.get());
186 
187  if (solver->hessian_object != nullptr)
188  {
189  // Following PetscNonlinearSolver by passing in PC. It's not clear
190  // why we pass in PC and not hessian though?
191  solver->hessian_object->hessian(*(sys.current_local_solution), PC, sys);
192  }
193  else
194  libmesh_error_msg("Hessian function not defined in __libmesh_tao_hessian");
195 
196  PC.close();
197  hessian.close();
198 
199  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
200  }
201 
202 
203  //---------------------------------------------------------------
204  // This function is called by Tao to evaluate the equality constraints at x
205  PetscErrorCode
206  __libmesh_tao_equality_constraints(Tao /*tao*/, Vec x, Vec ce, void * ctx)
207  {
208  PetscFunctionBegin;
209 
210  LOG_SCOPE("equality_constraints()", "TaoOptimizationSolver");
211 
212  libmesh_assert(x);
213  libmesh_assert(ce);
215 
216  // ctx should be a pointer to the solver (it was passed in as void *)
218  static_cast<TaoOptimizationSolver<Number> *> (ctx);
219 
220  OptimizationSystem & sys = solver->system();
221 
222  // We'll use current_local_solution below, so let's ensure that it's consistent
223  // with the vector x that was passed in.
224  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
225  PetscVector<Number> X(x, sys.comm());
226 
227  // Perform a swap so that sys.solution points to the input vector
228  // "x", update sys.current_local_solution based on "x", then swap
229  // back.
230  X.swap(X_sys);
231  sys.update();
232  X.swap(X_sys);
233 
234  // We'll also pass the constraints vector ce into the assembly routine
235  // so let's make a PETSc vector for that too.
236  PetscVector<Number> eq_constraints(ce, sys.comm());
237 
238  // Clear the gradient prior to assembly
239  eq_constraints.zero();
240 
241  // Enforce constraints exactly on the current_local_solution.
242  sys.get_dof_map().enforce_constraints_exactly(sys, sys.current_local_solution.get());
243 
244  if (solver->equality_constraints_object != nullptr)
245  solver->equality_constraints_object->equality_constraints(*(sys.current_local_solution), eq_constraints, sys);
246  else
247  libmesh_error_msg("Constraints function not defined in __libmesh_tao_equality_constraints");
248 
249  eq_constraints.close();
250 
251  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
252  }
253 
254  //---------------------------------------------------------------
255  // This function is called by Tao to evaluate the Jacobian of the
256  // equality constraints at x
257  PetscErrorCode
258  __libmesh_tao_equality_constraints_jacobian(Tao /*tao*/, Vec x, Mat J, Mat Jpre, void * ctx)
259  {
260  PetscFunctionBegin;
261 
262  LOG_SCOPE("equality_constraints_jacobian()", "TaoOptimizationSolver");
263 
264  libmesh_assert(x);
265  libmesh_assert(J);
266  libmesh_assert(Jpre);
267 
268  // ctx should be a pointer to the solver (it was passed in as void *)
270  static_cast<TaoOptimizationSolver<Number> *> (ctx);
271 
272  OptimizationSystem & sys = solver->system();
273 
274  // We'll use current_local_solution below, so let's ensure that it's consistent
275  // with the vector x that was passed in.
276  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
277  PetscVector<Number> X(x, sys.comm());
278 
279  // Perform a swap so that sys.solution points to the input vector
280  // "x", update sys.current_local_solution based on "x", then swap
281  // back.
282  X.swap(X_sys);
283  sys.update();
284  X.swap(X_sys);
285 
286  // Let's also wrap J and Jpre in PetscMatrix objects for convenience
287  PetscMatrix<Number> J_petsc(J, sys.comm());
288  PetscMatrix<Number> Jpre_petsc(Jpre, sys.comm());
289 
290  // Enforce constraints exactly on the current_local_solution.
291  sys.get_dof_map().enforce_constraints_exactly(sys, sys.current_local_solution.get());
292 
293  if (solver->equality_constraints_jacobian_object != nullptr)
294  solver->equality_constraints_jacobian_object->equality_constraints_jacobian(*(sys.current_local_solution), J_petsc, sys);
295  else
296  libmesh_error_msg("Constraints function not defined in __libmesh_tao_equality_constraints_jacobian");
297 
298  J_petsc.close();
299  Jpre_petsc.close();
300 
301  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
302  }
303 
304  //---------------------------------------------------------------
305  // This function is called by Tao to evaluate the inequality constraints at x
306  PetscErrorCode
307  __libmesh_tao_inequality_constraints(Tao /*tao*/, Vec x, Vec cineq, void * ctx)
308  {
309  PetscFunctionBegin;
310 
311  LOG_SCOPE("inequality_constraints()", "TaoOptimizationSolver");
312 
313  libmesh_assert(x);
314  libmesh_assert(cineq);
316 
317  // ctx should be a pointer to the solver (it was passed in as void *)
319  static_cast<TaoOptimizationSolver<Number> *> (ctx);
320 
321  OptimizationSystem & sys = solver->system();
322 
323  // We'll use current_local_solution below, so let's ensure that it's consistent
324  // with the vector x that was passed in.
325  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
326  PetscVector<Number> X(x, sys.comm());
327 
328  // Perform a swap so that sys.solution points to the input vector
329  // "x", update sys.current_local_solution based on "x", then swap
330  // back.
331  X.swap(X_sys);
332  sys.update();
333  X.swap(X_sys);
334 
335  // We'll also pass the constraints vector ce into the assembly routine
336  // so let's make a PETSc vector for that too.
337  PetscVector<Number> ineq_constraints(cineq, sys.comm());
338 
339  // Clear the gradient prior to assembly
340  ineq_constraints.zero();
341 
342  // Enforce constraints exactly on the current_local_solution.
343  sys.get_dof_map().enforce_constraints_exactly(sys, sys.current_local_solution.get());
344 
345  if (solver->inequality_constraints_object != nullptr)
346  solver->inequality_constraints_object->inequality_constraints(*(sys.current_local_solution), ineq_constraints, sys);
347  else
348  libmesh_error_msg("Constraints function not defined in __libmesh_tao_inequality_constraints");
349 
350  ineq_constraints.close();
351 
352  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
353  }
354 
355  //---------------------------------------------------------------
356  // This function is called by Tao to evaluate the Jacobian of the
357  // equality constraints at x
358  PetscErrorCode
359  __libmesh_tao_inequality_constraints_jacobian(Tao /*tao*/, Vec x, Mat J, Mat Jpre, void * ctx)
360  {
361  PetscFunctionBegin;
362 
363  LOG_SCOPE("inequality_constraints_jacobian()", "TaoOptimizationSolver");
364 
365  libmesh_assert(x);
366  libmesh_assert(J);
367  libmesh_assert(Jpre);
368 
369  // ctx should be a pointer to the solver (it was passed in as void *)
371  static_cast<TaoOptimizationSolver<Number> *> (ctx);
372 
373  OptimizationSystem & sys = solver->system();
374 
375  // We'll use current_local_solution below, so let's ensure that it's consistent
376  // with the vector x that was passed in.
377  PetscVector<Number> & X_sys = *cast_ptr<PetscVector<Number> *>(sys.solution.get());
378  PetscVector<Number> X(x, sys.comm());
379 
380  // Perform a swap so that sys.solution points to the input vector
381  // "x", update sys.current_local_solution based on "x", then swap
382  // back.
383  X.swap(X_sys);
384  sys.update();
385  X.swap(X_sys);
386 
387  // Let's also wrap J and Jpre in PetscMatrix objects for convenience
388  PetscMatrix<Number> J_petsc(J, sys.comm());
389  PetscMatrix<Number> Jpre_petsc(Jpre, sys.comm());
390 
391  // Enforce constraints exactly on the current_local_solution.
392  sys.get_dof_map().enforce_constraints_exactly(sys, sys.current_local_solution.get());
393 
394  if (solver->inequality_constraints_jacobian_object != nullptr)
395  solver->inequality_constraints_jacobian_object->inequality_constraints_jacobian(*(sys.current_local_solution), J_petsc, sys);
396  else
397  libmesh_error_msg("Constraints function not defined in __libmesh_tao_inequality_constraints_jacobian");
398 
399  J_petsc.close();
400  Jpre_petsc.close();
401 
402  PetscFunctionReturn(LIBMESH_PETSC_SUCCESS);
403  }
404 
405 } // end extern "C"
406 //---------------------------------------------------------------------
407 
408 
409 
410 //---------------------------------------------------------------------
411 // TaoOptimizationSolver<> methods
412 template <typename T>
414  OptimizationSolver<T>(system_in),
415  _reason(TAO_CONVERGED_USER) // Arbitrary initial value...
416 {
417 }
418 
419 
420 
421 template <typename T>
423 {
425 }
426 
427 
428 
429 template <typename T>
431 {
432  if (this->initialized())
433  {
434  this->_is_initialized = false;
435 
436  PetscErrorCode ierr = TaoDestroy(&_tao);
437  if (ierr)
438  libmesh_warning("Warning: TaoDestroy returned a non-zero error code which we ignored.");
439  }
440 }
441 
442 
443 
444 template <typename T>
446 {
447  // Initialize the data structures if not done so already.
448  if (!this->initialized())
449  {
450  this->_is_initialized = true;
451 
452  LibmeshPetscCall(TaoCreate(this->comm().get(),&_tao));
453  }
454 }
455 
456 template <typename T>
458 {
459  LOG_SCOPE("solve()", "TaoOptimizationSolver");
460 
461  this->init ();
462 
463  this->system().solution->zero();
464 
465  PetscMatrixBase<T> * hessian = cast_ptr<PetscMatrixBase<T> *>(this->system().matrix);
466  // PetscVector<T> * gradient = cast_ptr<PetscVector<T> *>(this->system().rhs);
467  PetscVector<T> * x = cast_ptr<PetscVector<T> *>(this->system().solution.get());
468  PetscVector<T> * ceq = cast_ptr<PetscVector<T> *>(this->system().C_eq.get());
469  PetscMatrixBase<T> * ceq_jac = cast_ptr<PetscMatrixBase<T> *>(this->system().C_eq_jac.get());
470  PetscVector<T> * cineq = cast_ptr<PetscVector<T> *>(this->system().C_ineq.get());
471  PetscMatrixBase<T> * cineq_jac = cast_ptr<PetscMatrixBase<T> *>(this->system().C_ineq_jac.get());
472  PetscVector<T> * lb = cast_ptr<PetscVector<T> *>(&this->system().get_vector("lower_bounds"));
473  PetscVector<T> * ub = cast_ptr<PetscVector<T> *>(&this->system().get_vector("upper_bounds"));
474 
475  // Set the starting guess to zero.
476  x->zero();
477 
478  // Workaround for bug where TaoSetFromOptions *reset*
479  // programmatically set tolerance and max. function evaluation
480  // values when "-tao_type ipm" was specified on the command line: we
481  // call TaoSetFromOptions twice (both before and after setting
482  // custom options programmatically)
483  LibmeshPetscCall(TaoSetFromOptions(_tao));
484 
485  // Set convergence tolerances
486  // f(X) - f(X*) (estimated) <= fatol
487  // |f(X) - f(X*)| (estimated) / |f(X)| <= frtol
488  // ||g(X)|| <= gatol
489  // ||g(X)|| / |f(X)| <= grtol
490  // ||g(X)|| / ||g(X0)|| <= gttol
491  // Command line equivalents: -tao_fatol, -tao_frtol, -tao_gatol, -tao_grtol, -tao_gttol
492  // Releases up to 3.7.0 had fatol and frtol, after that they were removed.
493 #if PETSC_VERSION_LESS_THAN(3,7,0)
494  LibmeshPetscCall(TaoSetTolerances(_tao,
495  /*fatol=*/PETSC_DEFAULT,
496  /*frtol=*/PETSC_DEFAULT,
497  /*gatol=*/PETSC_DEFAULT,
498  /*grtol=*/this->objective_function_relative_tolerance,
499  /*gttol=*/PETSC_DEFAULT));
500 #else
501  LibmeshPetscCall(TaoSetTolerances(_tao,
502  /*gatol=*/PETSC_DEFAULT,
503  /*grtol=*/this->objective_function_relative_tolerance,
504  /*gttol=*/PETSC_DEFAULT));
505 #endif
506 
507  // Set the max-allowed number of objective function evaluations
508  // Command line equivalent: -tao_max_funcs
509  LibmeshPetscCall(TaoSetMaximumFunctionEvaluations(_tao, this->max_objective_function_evaluations));
510 
511  // Set the max-allowed number of optimization iterations.
512  // Command line equivalent: -tao_max_it
513  // Not implemented for now as it seems fairly similar to
514  // LibmeshPetscCall(TaoSetMaximumIterations(_tao, 4));
515 
516  // Set solution vec and an initial guess
517 #if PETSC_VERSION_LESS_THAN(3,17,0)
518  LibmeshPetscCall(TaoSetInitialVector(_tao, x->vec()));
519 #else
520  LibmeshPetscCall(TaoSetSolution(_tao, x->vec()));
521 #endif
522 
523  // We have to have an objective function
524  libmesh_assert( this->objective_object );
525 
526  // Set routines for objective, gradient, hessian evaluation
527 #if PETSC_VERSION_LESS_THAN(3,17,0)
528  LibmeshPetscCall(TaoSetObjectiveRoutine(_tao, __libmesh_tao_objective, this));
529 #else
530  LibmeshPetscCall(TaoSetObjective(_tao, __libmesh_tao_objective, this));
531 #endif
532 
533  if (this->gradient_object)
534 #if PETSC_VERSION_LESS_THAN(3,17,0)
535  LibmeshPetscCall(TaoSetGradientRoutine(_tao, __libmesh_tao_gradient, this));
536 #else
537  LibmeshPetscCall(TaoSetGradient(_tao, NULL, __libmesh_tao_gradient, this));
538 #endif
539 
540  if (this->hessian_object)
541 #if PETSC_VERSION_LESS_THAN(3,17,0)
542  LibmeshPetscCall(TaoSetHessianRoutine(_tao, hessian->mat(), hessian->mat(), __libmesh_tao_hessian, this));
543 #else
544  LibmeshPetscCall(TaoSetHessian(_tao, hessian->mat(), hessian->mat(), __libmesh_tao_hessian, this));
545 #endif
546 
547  if (this->lower_and_upper_bounds_object)
548  {
549  // Need to actually compute the bounds vectors first
550  this->lower_and_upper_bounds_object->lower_and_upper_bounds(this->system());
551 
552  LibmeshPetscCall(TaoSetVariableBounds(_tao,
553  lb->vec(),
554  ub->vec()));
555  }
556 
557  if (this->equality_constraints_object)
558  LibmeshPetscCall(TaoSetEqualityConstraintsRoutine(_tao, ceq->vec(), __libmesh_tao_equality_constraints, this));
559 
560  if (this->equality_constraints_jacobian_object)
561  LibmeshPetscCall(TaoSetJacobianEqualityRoutine(_tao,
562  ceq_jac->mat(),
563  ceq_jac->mat(),
565  this));
566 
567  // Optionally set inequality constraints
568  if (this->inequality_constraints_object)
569  LibmeshPetscCall(TaoSetInequalityConstraintsRoutine(_tao, cineq->vec(), __libmesh_tao_inequality_constraints, this));
570 
571  // Optionally set inequality constraints Jacobian
572  if (this->inequality_constraints_jacobian_object)
573  LibmeshPetscCall(TaoSetJacobianInequalityRoutine(_tao,
574  cineq_jac->mat(),
575  cineq_jac->mat(),
577  this));
578 
579  // Check for Tao command line options
580  LibmeshPetscCall(TaoSetFromOptions(_tao));
581 
582  // Perform the optimization
583  LibmeshPetscCall(TaoSolve(_tao));
584 
585  // Enforce constraints exactly now that the solve is done. We have
586  // been enforcing them on the current_local_solution during the
587  // solve, but now need to be sure they are enforced on the parallel
588  // solution vector as well.
589  this->system().get_dof_map().enforce_constraints_exactly(this->system());
590 
591  // Store the convergence/divergence reason
592  LibmeshPetscCall(TaoGetConvergedReason(_tao, &_reason));
593 }
594 
595 
596 template <typename T>
598 {
599  LOG_SCOPE("get_dual_variables()", "TaoOptimizationSolver");
600 
601  PetscVector<T> * lambda_eq_petsc =
602  cast_ptr<PetscVector<T> *>(this->system().lambda_eq.get());
603  PetscVector<T> * lambda_ineq_petsc =
604  cast_ptr<PetscVector<T> *>(this->system().lambda_ineq.get());
605 
606  Vec lambda_eq_petsc_vec = lambda_eq_petsc->vec();
607  Vec lambda_ineq_petsc_vec = lambda_ineq_petsc->vec();
608 
609  LibmeshPetscCall(TaoGetDualVariables(_tao,
610  &lambda_eq_petsc_vec,
611  &lambda_ineq_petsc_vec));
612 }
613 
614 
615 template <typename T>
617 {
618  libMesh::out << "Tao optimization solver convergence/divergence reason: "
619  << TaoConvergedReasons[this->get_converged_reason()] << std::endl;
620 }
621 
622 
623 
624 template <typename T>
626 {
627  if (this->initialized())
628  LibmeshPetscCall(TaoGetConvergedReason(_tao, &_reason));
629 
630  return static_cast<int>(_reason);
631 }
632 
633 
634 //------------------------------------------------------------------
635 // Explicit instantiations
636 template class LIBMESH_EXPORT TaoOptimizationSolver<Number>;
637 
638 } // namespace libMesh
639 
640 
641 
642 #endif // #if defined(LIBMESH_HAVE_PETSC_TAO) && !defined(LIBMESH_USE_COMPLEX_NUMBERS)
OptimizationSystem::ComputeObjective * objective_object
Object that computes the objective function f(X) at the input iterate X.
This class provides a nice interface to PETSc&#39;s Vec object.
Definition: petsc_vector.h:73
This class provides an interface to the Tao optimization solvers.
virtual void gradient(const NumericVector< Number > &X, NumericVector< Number > &grad_f, sys_type &S)=0
This function will be called to compute the gradient of the objective function, and must be implement...
virtual void zero() override
Set all entries to zero.
Definition: petsc_vector.h:912
This class provides a nice interface to the PETSc C-based data structures for parallel, sparse matrices.
virtual void solve() override
Call the Tao solver.
virtual void hessian(const NumericVector< Number > &X, SparseMatrix< Number > &H_f, sys_type &S)=0
This function will be called to compute the Hessian of the objective function, and must be implemente...
virtual void inequality_constraints_jacobian(const NumericVector< Number > &X, SparseMatrix< Number > &C_ineq_jac, sys_type &S)=0
This function will be called to evaluate the Jacobian of C_ineq(X).
const Parallel::Communicator & comm() const
OptimizationSystem::ComputeGradient * gradient_object
Object that computes the gradient grad_f(X) of the objective function at the input iterate X...
virtual int get_converged_reason() override
The libMesh namespace provides an interface to certain functionality in the library.
virtual void print_converged_reason() override
Prints a useful message about why the latest optimization solve con(di)verged.
OptimizationSystem::ComputeHessian * hessian_object
Object that computes the Hessian H_f(X) of the objective function at the input iterate X...
virtual void swap(NumericVector< T > &v) override
Swaps the contents of this with v.
OptimizationSystem::ComputeInequalityConstraints * inequality_constraints_object
Object that computes the inequality constraints vector C_ineq(X).
PetscErrorCode __libmesh_tao_gradient(Tao tao, Vec x, Vec g, void *ctx)
PetscScalar PS(T val)
Definition: petsc_macro.h:168
PetscErrorCode __libmesh_tao_hessian(Tao tao, Vec x, Mat h, Mat pc, void *ctx)
OptimizationSystem::ComputeEqualityConstraintsJacobian * equality_constraints_jacobian_object
Object that computes the Jacobian of C_eq(X).
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:257
TaoOptimizationSolver(sys_type &system)
Constructor.
This System subclass enables us to assemble an objective function, gradient, Hessian and bounds for o...
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
libmesh_assert(ctx)
virtual void equality_constraints(const NumericVector< Number > &X, NumericVector< Number > &C_eq, sys_type &S)=0
This function will be called to evaluate the equality constraints vector C_eq(X). ...
PetscErrorCode __libmesh_tao_objective(Tao tao, Vec x, PetscReal *objective, void *ctx)
virtual void clear() noexcept override
Release all memory and clear data structures.
const sys_type & system() const
void attach_dof_map(const DofMap &dof_map)
Set a pointer to the DofMap to use.
Definition: sparse_matrix.C:72
virtual Number objective(const NumericVector< Number > &X, sys_type &S)=0
This function will be called to compute the objective function to be minimized, and must be implement...
virtual void equality_constraints_jacobian(const NumericVector< Number > &X, SparseMatrix< Number > &C_eq_jac, sys_type &S)=0
This function will be called to evaluate the Jacobian of C_eq(X).
This base class can be inherited from to provide interfaces to optimization solvers from different pa...
OStreamProxy out
PetscErrorCode __libmesh_tao_equality_constraints_jacobian(Tao tao, Vec x, Mat J, Mat Jpre, void *ctx)
This class provides a nice interface to the PETSc C-based AIJ data structures for parallel...
Definition: petsc_matrix.h:61
bool initialized()
Checks that library initialization has been done.
Definition: libmesh.C:276
void * ctx
PetscErrorCode __libmesh_tao_equality_constraints(Tao tao, Vec x, Vec ce, void *ctx)
PetscErrorCode __libmesh_tao_inequality_constraints_jacobian(Tao tao, Vec x, Mat J, Mat Jpre, void *ctx)
PetscFunctionReturn(LIBMESH_PETSC_SUCCESS)
PetscErrorCode __libmesh_tao_inequality_constraints(Tao tao, Vec x, Vec cineq, void *ctx)
virtual void init() override
Initialize data structures if not done so already.
virtual void get_dual_variables() override
Get the current values of dual variables associated with inequality and equality constraints.
virtual void inequality_constraints(const NumericVector< Number > &X, NumericVector< Number > &C_ineq, sys_type &S)=0
This function will be called to evaluate the equality constraints vector C_ineq(X).
OptimizationSystem::ComputeInequalityConstraintsJacobian * inequality_constraints_jacobian_object
Object that computes the Jacobian of C_ineq(X).
OptimizationSystem::ComputeEqualityConstraints * equality_constraints_object
Object that computes the equality constraints vector C_eq(X).