From 51ef2200656abe1eb024d84d9c831f331476d2c6 Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Sun, 10 May 2009 21:00:47 +0000 Subject: [PATCH] IPOpt solver moved from ag-common to dune-solvers [[Imported from SVN: r2429]] --- Makefile.am | 7 +- configure.ac | 9 +- dune-solvers/Makefile.am | 7 + dune-solvers/iterationsteps/Makefile.am | 9 + dune-solvers/norms/Makefile.am | 7 + dune-solvers/solvers/Makefile.am | 7 + dune-solvers/solvers/quadraticipopt.hh | 605 +++++++++++++++++++++ dune-solvers/transferoperators/Makefile.am | 10 + m4/ipopt.m4 | 97 ++++ 9 files changed, 750 insertions(+), 8 deletions(-) create mode 100644 dune-solvers/Makefile.am create mode 100644 dune-solvers/iterationsteps/Makefile.am create mode 100644 dune-solvers/norms/Makefile.am create mode 100644 dune-solvers/solvers/Makefile.am create mode 100644 dune-solvers/solvers/quadraticipopt.hh create mode 100644 dune-solvers/transferoperators/Makefile.am create mode 100644 m4/ipopt.m4 diff --git a/Makefile.am b/Makefile.am index 68eb1740..a6aa5e04 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,13 +3,10 @@ # we need the module file to be able to build via dunecontrol EXTRA_DIST=dune.module -DIST_SUBDIRS = doc src m4 - -SUBDIRS = src m4 +SUBDIRS = src m4 dune-solvers if BUILD_DOCS -# TODO: set up documentation tree automatically -#SUBDIRS += doc +SUBDIRS += doc endif # don't follow the full GNU-standard diff --git a/configure.ac b/configure.ac index 95b8d267..d4a970ff 100644 --- a/configure.ac +++ b/configure.ac @@ -7,9 +7,7 @@ AC_CONFIG_SRCDIR([src/dune_solvers.cc]) AM_CONFIG_HEADER([config.h]) -# we need no more than the standard DE-stuff -# this module depends on dune-common dune-grid dune-istl -# this implies checking for [dune-common], [dune-grid], [dune-istl] +# Run all checks DUNE_CHECK_ALL # Create a symlink dune --> . in the main module directory @@ -23,6 +21,11 @@ LIBS="$DUNE_LIBS" AC_CONFIG_FILES([ Makefile src/Makefile + dune-solvers/Makefile + dune-solvers/iterationsteps/Makefile + dune-solvers/norms/Makefile + dune-solvers/solvers/Makefile + dune-solvers/transferoperators/Makefile doc/Makefile doc/doxygen/Makefile m4/Makefile diff --git a/dune-solvers/Makefile.am b/dune-solvers/Makefile.am new file mode 100644 index 00000000..89ba8da5 --- /dev/null +++ b/dune-solvers/Makefile.am @@ -0,0 +1,7 @@ + +SUBDIRS = iterationsteps norms solvers transferoperators + +dune_solversdir = $(includedir)/dune/dune-solvers +dune_solvers_HEADERS = boxconstraint.hh numproc.hh + +include $(top_srcdir)/am/global-rules diff --git a/dune-solvers/iterationsteps/Makefile.am b/dune-solvers/iterationsteps/Makefile.am new file mode 100644 index 00000000..9422dcf3 --- /dev/null +++ b/dune-solvers/iterationsteps/Makefile.am @@ -0,0 +1,9 @@ +SUBDIRS = + +iterationstepsdir = $(includedir)/dune/dune-solvers/iterationsteps +iterationsteps_HEADERS = amgstep.hh blockgsstep.hh blockgsstep.cc iterationstep.hh \ + lineariterationstep.hh mmgstep.hh mmgstep.cc multigridstep.hh multigridstep.cc \ + projectedblockgsstep.hh projectedblockgsstep.cc truncatedblockgsstep.hh \ + truncatedsaddlepointgsstep.hh trustregiongsstep.cc trustregiongsstep.hh + +include $(top_srcdir)/am/global-rules \ No newline at end of file diff --git a/dune-solvers/norms/Makefile.am b/dune-solvers/norms/Makefile.am new file mode 100644 index 00000000..2ec1e08d --- /dev/null +++ b/dune-solvers/norms/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = + +normsdir = $(includedir)/dune/dune-solvers/norms +norms_HEADERS = blocknorm.hh diagnorm.hh energynorm.hh fullnorm.hh h1seminorm.hh \ + norm.hh pnorm.hh sumnorm.hh + +include $(top_srcdir)/am/global-rules \ No newline at end of file diff --git a/dune-solvers/solvers/Makefile.am b/dune-solvers/solvers/Makefile.am new file mode 100644 index 00000000..46b64fb0 --- /dev/null +++ b/dune-solvers/solvers/Makefile.am @@ -0,0 +1,7 @@ +SUBDIRS = + +solversdir = $(includedir)/dune/dune-solvers/solvers +solvers_HEADERS = cgsolver.cc cgsolver.hh iterativesolver.cc iterativesolver.hh \ + loopsolver.cc loopsolver.hh solver.hh tcgsolver.cc tcgsolver.hh + +include $(top_srcdir)/am/global-rules \ No newline at end of file diff --git a/dune-solvers/solvers/quadraticipopt.hh b/dune-solvers/solvers/quadraticipopt.hh new file mode 100644 index 00000000..6cea09a3 --- /dev/null +++ b/dune-solvers/solvers/quadraticipopt.hh @@ -0,0 +1,605 @@ +#ifndef DUNE_QUADRATIC_IPOPT_SOLVER_HH +#define DUNE_QUADRATIC_IPOPT_SOLVER_HH + +/** \file + \brief A wrapper for the IPOpt solver for quadratic optimization problem + with box constraints. +*/ +#include <algorithm> +#include <vector> + +#include <dune/common/exceptions.hh> +#include <dune/common/bitsetvector.hh> +#include <dune/common/fmatrix.hh> + +#include <dune/istl/bcrsmatrix.hh> +#include <dune/istl/bvector.hh> + +#include <dune-solvers/boxconstraint.hh> +#include <dune-solvers/solvers/iterativesolver.hh> + +/** \todo Undef those because they clash. I think this is an IPOPT bug. + (their config.h is included by a header). */ +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION + +#include "coin/IpTNLP.hpp" +#include "coin/IpIpoptApplication.hpp" + +template <class MatrixType, class VectorType> +class QuadraticIPOptProblem : public Ipopt::TNLP +{ + enum {blocksize = VectorType::block_type::size}; + + typedef typename VectorType::field_type field_type; + +public: + /** default constructor */ + QuadraticIPOptProblem(const MatrixType* hessian, VectorType* x, const VectorType* rhs, + const Dune::BitSetVector<blocksize>* dirichletNodes, + std::vector<BoxConstraint<field_type, blocksize> >* obstacles) + : hessian_(hessian), x_(x), rhs_(rhs), + dirichletNodes_(dirichletNodes), obstacles_(obstacles) + {} + + /** default destructor */ + virtual ~QuadraticIPOptProblem() {}; + + /**@name Overloaded from TNLP */ + //@{ + /** Method to return some info about the nlp */ + virtual bool get_nlp_info(Ipopt::Index& n, Ipopt::Index& m, Ipopt::Index& nnz_jac_g, + Ipopt::Index& nnz_h_lag, IndexStyleEnum& index_style); + + /** Method to return the bounds for my problem */ + virtual bool get_bounds_info(Ipopt::Index n, Ipopt::Number* x_l, Ipopt::Number* x_u, + Ipopt::Index m, Ipopt::Number* g_l, Ipopt::Number* g_u); + + /** Method to return the starting point for the algorithm */ + virtual bool get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number* x, + bool init_z, Ipopt::Number* z_L, Ipopt::Number* z_U, + Ipopt::Index m, bool init_lambda, + Ipopt::Number* lambda); + + /** Method to return the objective value */ + virtual bool eval_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number& obj_value); + + /** Method to return the gradient of the objective */ + virtual bool eval_grad_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number* grad_f); + + /** Method to return the constraint residuals */ + virtual bool eval_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Index m, Ipopt::Number* g); + + /** Method to return: + * 1) The structure of the jacobian (if "values" is NULL) + * 2) The values of the jacobian (if "values" is not NULL) + */ + virtual bool eval_jac_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, + Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index* iRow, Ipopt::Index *jCol, + Ipopt::Number* values); + + /** Method to return: + * 1) The structure of the hessian of the lagrangian (if "values" is NULL) + * 2) The values of the hessian of the lagrangian (if "values" is not NULL) + */ + virtual bool eval_h(Ipopt::Index n, const Ipopt::Number* x, bool new_x, + Ipopt::Number obj_factor, Ipopt::Index m, const Ipopt::Number* lambda, + bool new_lambda, Ipopt::Index nele_hess, Ipopt::Index* iRow, + Ipopt::Index* jCol, Ipopt::Number* values); + + //@} + + /** @name Solution Methods */ + //@{ + /** This method is called when the algorithm is complete so the TNLP can store/write the solution */ + virtual void finalize_solution(Ipopt::SolverReturn status, + Ipopt::Index n, const Ipopt::Number* x, const Ipopt::Number* z_L, const Ipopt::Number* z_U, + Ipopt::Index m, const Ipopt::Number* g, const Ipopt::Number* lambda, + Ipopt::Number obj_value, + const Ipopt::IpoptData* ip_data, + Ipopt::IpoptCalculatedQuantities* ip_cq); + //@} + + // ///////////////////////////////// + // Data + // ///////////////////////////////// + + const MatrixType* hessian_; + + VectorType* x_; + + const VectorType* rhs_; + + const Dune::BitSetVector<blocksize>* dirichletNodes_; + + std::vector<BoxConstraint<field_type, blocksize> >* obstacles_; + +private: + /**@name Methods to block default compiler methods. + */ + //@{ + // QuadraticIPOptProblem(); + QuadraticIPOptProblem(const QuadraticIPOptProblem&); + QuadraticIPOptProblem& operator=(const QuadraticIPOptProblem&); + //@} +}; + +// returns the size of the problem +template <class MatrixType, class VectorType> +bool QuadraticIPOptProblem<MatrixType,VectorType>:: +get_nlp_info(Ipopt::Index& n, Ipopt::Index& m, Ipopt::Index& nnz_jac_g, + Ipopt::Index& nnz_h_lag, IndexStyleEnum& index_style) +{ + // The problem described in HS071_NLP.hpp has 4 variables, x[0] through x[3] + n = x_->dim(); + + // No equality constraints: Dirichlet conditions are actually inequality constraints + m = 0; + + // hence the constraint jacobian is empty + nnz_jac_g = 0; + + // We only need the lower left corner of the Hessian (since it is symmetric) + if (!hessian_) + DUNE_THROW(SolverError, "No Hessian matrix has been supplied!"); + + nnz_h_lag = 0; + + for (int rowIdx=0; rowIdx<hessian_->N(); rowIdx++) { + + const typename MatrixType::row_type& row = (*hessian_)[rowIdx]; + + typename MatrixType::row_type::ConstIterator cIt = row.begin(); + typename MatrixType::row_type::ConstIterator cEndIt = row.end(); + + for (; cIt!=cEndIt; ++cIt) { + + if (rowIdx > cIt.index()) { + + nnz_h_lag += blocksize*blocksize; + + } else if (rowIdx == cIt.index()) { + + nnz_h_lag += ((blocksize+1)*blocksize) / 2; + + } + + } + + } + + // use the C style indexing (0-based) + index_style = Ipopt::TNLP::C_STYLE; + + return true; +} + + +// returns the variable bounds +template <class MatrixType, class VectorType> +bool QuadraticIPOptProblem<MatrixType,VectorType>:: +get_bounds_info(Ipopt::Index n, Ipopt::Number* x_l, Ipopt::Number* x_u, + Ipopt::Index m, Ipopt::Number* g_l, Ipopt::Number* g_u) +{ + // here, the n and m we gave IPOPT in get_nlp_info are passed back to us. + // If desired, we could assert to make sure they are what we think they are. + assert(n == x_->dim()); + assert(m == 0); + + if (obstacles_) { + + for (int i=0; i<x_->size(); i++) { + + for (size_t j=0; j<blocksize; j++) { + + // Simply copy the values. If they exceed a certain limit they are + // considered 'off'. + x_l[i*blocksize+j] = (*obstacles_)[i].lower(j); + x_u[i*blocksize+j] = (*obstacles_)[i].upper(j); + + } + + } + + } else { + + // unset all bounds + for (int i=0; i<x_->dim(); i++) { + x_l[i] = -std::numeric_limits<double>::max(); + x_u[i] = std::numeric_limits<double>::max(); + } + + } + + if (dirichletNodes_) { + + for (int i=0; i<x_->size(); i++) { + + for (size_t j=0; j<blocksize; j++) { + + if ( (*dirichletNodes_)[i][j]) + x_l[i*blocksize+j] = x_u[i*blocksize+j] = (*this->x_)[i][j]; + + } + + } + + } + + return true; +} + +// returns the initial point for the problem +template <class MatrixType, class VectorType> +bool QuadraticIPOptProblem<MatrixType,VectorType>:: +get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number* x, + bool init_z, Ipopt::Number* z_L, Ipopt::Number* z_U, + Ipopt::Index m, bool init_lambda, Ipopt::Number* lambda) +{ + // Here, we assume we only have starting values for x, if you code + // your own NLP, you can provide starting values for the dual variables + // if you wish + assert(init_x == true); + assert(init_z == false); + assert(init_lambda == false); + + // initialize to the given starting point + for (int i=0; i<x_->size(); i++) + for (int j=0; j<blocksize; j++) + x[i*blocksize+j] = (*x_)[i][j]; + + return true; +} + +// returns the value of the objective function +template <class MatrixType, class VectorType> +bool QuadraticIPOptProblem<MatrixType,VectorType>:: +eval_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number& obj_value) +{ +// std::cout << "x:" << std::endl; +// for (int i=0; i<n; i++) +// std::cout << x[i] << std::endl; + + // Init return value + obj_value = 0; + + //////////////////////////////////// + // Compute x^T*A*x + //////////////////////////////////// + + for (int rowIdx=0; rowIdx<hessian_->N(); rowIdx++) { + + const typename MatrixType::row_type& row = (*hessian_)[rowIdx]; + + typename MatrixType::row_type::ConstIterator cIt = row.begin(); + typename MatrixType::row_type::ConstIterator cEndIt = row.end(); + + for (; cIt!=cEndIt; ++cIt) { + + // Multiply block + for (int i=0; i<blocksize; i++) + for (int j=0; j<blocksize; j++) + obj_value += x[rowIdx*blocksize+i] * x[cIt.index()*blocksize+j] * (*cIt)[i][j]; + + } + + } + + //std::cout << "bilinear form: " << *f << std::endl; + + // because J = 1/2 * A(x,x) - b(x) + obj_value *= 0.5; + + // -b(x) + for (int i=0; i<rhs_->size(); i++) + for (int j=0; j<blocksize; j++) + obj_value -= x[i*blocksize+j] * (*rhs_)[i][j]; + + //std::cout << "IPOPT Energy: " << obj_value << std::endl; + //exit(0); + + return true; +} + +// return the gradient of the objective function grad_{x} f(x) +template <class MatrixType, class VectorType> +bool QuadraticIPOptProblem<MatrixType,VectorType>:: +eval_grad_f(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Number* grad_f) +{ + //std::cout << "### eval_grad_f ###" << std::endl; + + // \nabla J = A(x,.) - b(x) + for (int i=0; i<n; i++) + grad_f[i] = 0; + + for (int i=0; i<hessian_->N(); i++) { + + const typename MatrixType::row_type& row = (*hessian_)[i]; + + typename MatrixType::row_type::ConstIterator cIt = row.begin(); + typename MatrixType::row_type::ConstIterator cEndIt = row.end(); + + for (; cIt!=cEndIt; ++cIt) { + + for (int j=0; j<blocksize; j++) + for (int k=0; k<blocksize; k++) + grad_f[i*blocksize+j] += (*cIt)[j][k] * x[cIt.index()*blocksize+k]; + + } + + } + + // g = g - b + for (int i=0; i<rhs_->size(); i++) + for (int j=0; j<blocksize; j++) + grad_f[i*blocksize+j] -= (*rhs_)[i][j]; + +// for (int i=0; i<n; i++) +// printf("%d: x = %g, rhs = %g, g = %g\n", i, x[i], (*rhs_)[i/blocksize][i%blocksize], grad_f[i]); + return true; +} + +// return the value of the constraints: g(x) +template <class MatrixType, class VectorType> +bool QuadraticIPOptProblem<MatrixType,VectorType>:: +eval_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, Ipopt::Index m, Ipopt::Number* g) +{ + return true; +} + +// return the structure or values of the jacobian +template <class MatrixType, class VectorType> +bool QuadraticIPOptProblem<MatrixType,VectorType>:: +eval_jac_g(Ipopt::Index n, const Ipopt::Number* x, bool new_x, + Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index* iRow, Ipopt::Index *jCol, + Ipopt::Number* values) +{ + return true; +} + +//return the structure or values of the hessian +template <class MatrixType, class VectorType> +bool QuadraticIPOptProblem<MatrixType,VectorType>:: +eval_h(Ipopt::Index n, const Ipopt::Number* x, bool new_x, + Ipopt::Number obj_factor, Ipopt::Index m, const Ipopt::Number* lambda, + bool new_lambda, Ipopt::Index nele_hess, Ipopt::Index* iRow, + Ipopt::Index* jCol, Ipopt::Number* values) +{ + if (values == NULL) { + + // return the structure. This is a symmetric matrix, fill the lower left + // triangle only. + + int idx = 0; + + // Loop over all matrix rows + for (int rowIdx=0; rowIdx<hessian_->N(); rowIdx++) { + + const typename MatrixType::row_type& row = (*hessian_)[rowIdx]; + + typename MatrixType::row_type::ConstIterator cIt = row.begin(); + typename MatrixType::row_type::ConstIterator cEndIt = row.end(); + + // Loop over all columns in this row + for (; cIt!=cEndIt; ++cIt) { + + // Current entry on the lower left triangular matrix and not on the diagonal + // --> copy it completely + if (rowIdx > cIt.index()) { + + for (int i=0; i<blocksize; i++) { + + for (int j=0; j<blocksize; j++) { + + iRow[idx] = rowIdx*blocksize + i; + jCol[idx] = cIt.index()*blocksize + j; + idx++; + + } + + } + + } else if (rowIdx == cIt.index()) { + + // Current entry is on the diagonal + // --> copy only its lower triangular half + for (int i=0; i<blocksize; i++) { + + for (int j=0; j<i+1; j++) { + + iRow[idx] = rowIdx*blocksize + i; + jCol[idx] = cIt.index()*blocksize + j; + idx++; + + } + + } + + } + + } + + } + + assert(idx == nele_hess); +// for (int i=0; i<nele_hess; i++) +// printf("%d %d \n", iRow[i], jCol[i]); + + } else { + + // return the values. This is a symmetric matrix, fill the lower left + // triangle only + + int idx = 0; + + // Loop over all matrix rows + for (int rowIdx=0; rowIdx<hessian_->N(); rowIdx++) { + + const typename MatrixType::row_type& row = (*hessian_)[rowIdx]; + + typedef typename MatrixType::row_type::ConstIterator ColumnIterator; + + ColumnIterator cIt = row.begin(); + ColumnIterator cEndIt = row.end(); + + // Loop over all columns in this row + for (; cIt!=cEndIt; ++cIt) { + + // Current entry on the lower left triangular matrix and not on the diagonal + // --> copy it completely + if (rowIdx > cIt.index()) { + + for (int i=0; i<blocksize; i++) + for (int j=0; j<blocksize; j++) { + //printf("%d %d %g\n", rowIdx*blocksize + i, cIt.index()*blocksize+j,(*cIt)[i][j]); + values[idx++] = obj_factor * (*cIt)[i][j]; + } + + } else if (rowIdx == cIt.index()) { + + // Current entry is on the diagonal + // --> copy only its lower triangular half + for (int i=0; i<blocksize; i++) + for (int j=0; j<i+1; j++) { + //printf("%d %d %g\n", rowIdx*blocksize + i, cIt.index()*blocksize+j,(*cIt)[i][j]); + values[idx++] = obj_factor * (*cIt)[i][j]; + } + } + + } + + } + + assert(idx == nele_hess); + +// for (int i=0; i<nele_hess; i++) +// printf("%g\n", values[i]); + + } + + return true; +} + +template <class MatrixType, class VectorType> +void QuadraticIPOptProblem<MatrixType,VectorType>:: +finalize_solution(Ipopt::SolverReturn status, + Ipopt::Index n, const Ipopt::Number* x, const Ipopt::Number* z_L, const Ipopt::Number* z_U, + Ipopt::Index m, const Ipopt::Number* g, const Ipopt::Number* lambda, + Ipopt::Number obj_value, + const Ipopt::IpoptData* ip_data, + Ipopt::IpoptCalculatedQuantities* ip_cq) +{ + // here is where we would store the solution to variables, or write to a file, etc + // so we could use the solution. + + for (int i=0; i<x_->size(); i++) + for (int j=0; j<blocksize; j++) + (*x_)[i][j] = x[i*blocksize+j]; + +} + + +template <class MatrixType, class VectorType> +class QuadraticIPOptSolver : public IterativeSolver<VectorType> +{ + + enum {blocksize = VectorType::block_type::size}; + + typedef typename VectorType::field_type field_type; + + typedef Dune::FieldMatrix<field_type, blocksize, blocksize> MatrixBlock; + typedef Dune::FieldVector<field_type, blocksize> VectorBlock; + + +public: + + /** \brief Default constructor */ + QuadraticIPOptSolver () : IterativeSolver<VectorType>(1e-8, 100, NumProc::FULL), + hessian_(NULL), rhs_(NULL), ignoreNodes_(NULL), + obstacles_(NULL) + {} + + /** \brief Constructor for a linear problem */ + QuadraticIPOptSolver (const MatrixType& hessian, + VectorType& x, + const VectorType& rhs) + : IterativeSolver<VectorType>(1e-8, 100, NumProc::FULL), + hessian_(&hessian), rhs_(&rhs), ignoreNodes_(NULL), obstacles_(NULL) + { + this->x_ = &x; + } + + void setProblem(const MatrixType& hessian, + VectorType& x, + const VectorType& rhs) { + hessian_ = &hessian; + x_ = &x; + rhs_ = &rhs; + } + + virtual void solve(); + + /////////////////////////////////////////////////////// + // Data + /////////////////////////////////////////////////////// + + const MatrixType* hessian_; + + VectorType* x_; + + const VectorType* rhs_; + + const Dune::BitSetVector<blocksize>* ignoreNodes_; + + std::vector<BoxConstraint<field_type,blocksize> >* obstacles_; + +}; + +template <class MatrixType, class VectorType> +void QuadraticIPOptSolver<MatrixType,VectorType>::solve() +{ + // Create a new instance of your nlp + // (use a SmartPtr, not raw) + Ipopt::SmartPtr<Ipopt::TNLP> mynlp + = new QuadraticIPOptProblem<MatrixType,VectorType>(hessian_, x_, rhs_, + ignoreNodes_, obstacles_); + + // Create a new instance of IpoptApplication + // (use a SmartPtr, not raw) + Ipopt::SmartPtr<Ipopt::IpoptApplication> app = new Ipopt::IpoptApplication(); + + // Change some options + app->Options()->SetNumericValue("tol", this->tolerance_); + app->Options()->SetIntegerValue("max_iter", this->maxIterations_); + app->Options()->SetStringValue("mu_strategy", "adaptive"); + app->Options()->SetStringValue("output_file", "ipopt.out"); + switch (this->verbosity_) { + case NumProc::QUIET: + app->Options()->SetIntegerValue("print_level", -2); + break; + case NumProc::REDUCED: + app->Options()->SetIntegerValue("print_level", 5); + break; + case NumProc::FULL: + app->Options()->SetIntegerValue("print_level", 12); + } + + // Intialize the IpoptApplication and process the options + Ipopt::ApplicationReturnStatus status; + status = app->Initialize(); + if (status != Ipopt::Solve_Succeeded) + DUNE_THROW(Dune::Exception, "IPOpt: Error during initialization!"); + + // Ask Ipopt to solve the problem + status = app->OptimizeTNLP(mynlp); + + // As the SmartPtrs go out of scope, the reference count + // will be decremented and the objects will automatically + // be deleted. + +} + +#endif diff --git a/dune-solvers/transferoperators/Makefile.am b/dune-solvers/transferoperators/Makefile.am new file mode 100644 index 00000000..a486dab3 --- /dev/null +++ b/dune-solvers/transferoperators/Makefile.am @@ -0,0 +1,10 @@ +SUBDIRS = + +transferoperatorsdir = $(includedir)/dune/dune-solvers/transferoperators +transferoperators_HEADERS = compressedmultigridtransfer.hh multigridtransfer.hh \ + truncatedcompressedmgtransfer.hh truncatedmgtransfer.hh densemultigridtransfer.hh \ + mandelobsrestrictor.cc obstaclerestrictor.hh truncateddensemgtransfer.cc \ + genericmultigridtransfer.hh mandelobsrestrictor.hh truncatedcompressedmgtransfer.cc \ + truncateddensemgtransfer.hh + +include $(top_srcdir)/am/global-rules \ No newline at end of file diff --git a/m4/ipopt.m4 b/m4/ipopt.m4 new file mode 100644 index 00000000..44b5007f --- /dev/null +++ b/m4/ipopt.m4 @@ -0,0 +1,97 @@ +# searches for ipopt headers and libs + +AC_DEFUN([DUNE_IPOPT],[ + AC_REQUIRE([AC_PROG_CXX]) + + AC_ARG_WITH(ipopt, + AC_HELP_STRING([--with-ipopt=PATH],[directory with IPOpt inside])) + +# store values +ac_save_LDFLAGS="$LDFLAGS" +ac_save_CPPFLAGS="$CPPFLAGS" +ac_save_LIBS="$LIBS" + +## do nothing if --without-amiramesh is used +if test x$with_ipopt != xno ; then + +# is --with-ipopt=bla used? +if test "x$with_ipopt" != x ; then + if ! test -d $with_ipopt; then + AC_MSG_WARN([IPOpt directory $with_ipopt does not exist]) + else + # expand tilde / other stuff + IPOPTROOT=`cd $with_ipopt && pwd` + fi +fi +if test "x$IPOPTROOT" = x; then + # use some default value... + IPOPTROOT="/usr/local/ipopt" +fi + +IPOPT_LIB_PATH="$IPOPTROOT/lib" +IPOPT_INCLUDE_PATH="$IPOPTROOT/include" + +LDFLAGS="$LDFLAGS -L$IPOPT_LIB_PATH" +CPPFLAGS="$CPPFLAGS -I$IPOPT_INCLUDE_PATH" + +AC_LANG_PUSH([C++]) + +# check for header +AC_CHECK_HEADER([coin/IpIpoptApplication.hpp], + [IPOPT_CPPFLAGS="-I$IPOPT_INCLUDE_PATH" + HAVE_IPOPT="1"], + AC_MSG_WARN([IpIpoptApplication.hpp not found in $IPOPT_INCLUDE_PATH/coin])) + +CPPFLAGS="$IPOPT_CPPFLAGS" + +# if header is found... +if test x$HAVE_IPOPT = x1 ; then + LIBS="$LIBS -lipopt -llapack -lblas -lgfortran" + + AC_LINK_IFELSE(AC_LANG_PROGRAM( + [#include "coin/IpIpoptApplication.hpp"], + [Ipopt::SmartPtr<Ipopt::IpoptApplication> app = new Ipopt::IpoptApplication();]), + [IPOPT_LIBS="-lipopt -llapack -lblas -lgfortran" + IPOPT_LDFLAGS="-L$IPOPT_LIB_PATH" + LIBS="$LIBS $IPOPT_LIBS"], + [HAVE_IPOPT="0" + AC_MSG_WARN(IPOpt not found!)]) +fi + +AC_LANG_POP([C++]) + +## end of ipopt check (--without wasn't set) +fi + +with_ipopt="no" +# survived all tests? +if test x$HAVE_IPOPT = x1 ; then + AC_SUBST(IPOPT_LIBS, $IPOPT_LIBS) + AC_SUBST(IPOPT_LDFLAGS, $IPOPT_LDFLAGS) + AC_SUBST(IPOPT_CPPFLAGS, $IPOPT_CPPFLAGS) + AC_DEFINE(HAVE_IPOPT, 1, [Define to 1 if IPOpt library is found]) + + # add to global list + DUNE_PKG_LDFLAGS="$DUNE_PKG_LDFLAGS $IPOPT_LDFLAGS" + DUNE_PKG_LIBS="$DUNE_PKG_LIBS $IPOPT_LIBS" + DUNE_PKG_CPPFLAGS="$DUNE_PKG_CPPFLAGS $IPOPT_CPPFLAGS" + + # set variable for summary + with_ipopt="yes" +else + AC_SUBST(IPOPT_LIBS, "") + AC_SUBST(IPOPT_LDFLAGS, "") + AC_SUBST(IPOPT_CPPFLAGS, "") +fi + +# also tell automake +AM_CONDITIONAL(IPOPT, test x$HAVE_IPOPT = x1) + +# reset old values +LIBS="$ac_save_LIBS" +CPPFLAGS="$ac_save_CPPFLAGS" +LDFLAGS="$ac_save_LDFLAGS" + +DUNE_ADD_SUMMARY_ENTRY([IPOpt],[$with_ipopt]) + +]) -- GitLab