MAST
npsol_optimization_interface.cpp
Go to the documentation of this file.
1 /*
2  * MAST: Multidisciplinary-design Adaptation and Sensitivity Toolkit
3  * Copyright (C) 2013-2019 Manav Bhatia
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 // MAST includes
23 #include "base/mast_config.h"
24 
25 extern "C" {
26 
27  extern void sninit_(int* iPrint,
28  int* iSumm,
29  const char* cw,
30  int* lencw,
31  int* iw,
32  int* leniw,
33  double* rw,
34  int* lenrw);
35 
36  extern void sninitf_(const char* printfile,
37  const char* summary_file,
38  int* iPrint,
39  int* iSumm,
40  const char* cw,
41  int* lencw,
42  int* iw,
43  int* leniw,
44  double* rw,
45  int* lenrw);
46 
47  extern void snspec_(int* iSpecs,
48  int* INFO,
49  const char* cw,
50  int* lencw,
51  int* iw,
52  int* leniw,
53  double* rw,
54  int* lenrw);
55 
56  extern void snspecf_(const char* specsfile,
57  int* INFO,
58  const char* cw,
59  int* lencw,
60  int* iw,
61  int* leniw,
62  double* rw,
63  int* lenrw);
64 
65  extern void npopt_(int* n,
66  int* nclin,
67  int* ncnln,
68  int* ldA,
69  int* ldgg,
70  int* ldH,
71  double* A,
72  double* bl,
73  double* bu,
74  void (*)(int* mode,
75  int* ncnln,
76  int* n,
77  int* ldJ,
78  int* needc,
79  double* x,
80  double* c,
81  double* cJac,
82  int* nstate),
83  void (*)(int* mode,
84  int* n,
85  double* x,
86  double* f,
87  double* g,
88  int* nstate),
89  int* INFO,
90  int* majIts,
91  int* iState,
92  double* fCon,
93  double* gCon,
94  double* cMul,
95  double* fObj,
96  double* gObj,
97  double* Hess,
98  double* x,
99  int* iw,
100  int* leniw,
101  double* re,
102  int* lenrw);
103 
104  extern void npoptn_(const char*, int );
105 }
106 
107 
108 
109 
112 _funobj(nullptr),
113 _funcon(nullptr) {
114 
115 #if MAST_ENABLE_SNOPT == 0
116  libmesh_error_msg("MAST configured without SNOPT support.");
117 #endif
118 
119  _exit_message[0] = "Finished successfully";
120  _exit_message[10] = " The problem appears to be infeasible 20 The problem appears to be unbounded 30 Resource limit error";
121  _exit_message[40] = " Terminated after numerical difficulties 50 Error in the user-supplied functions";
122  _exit_message[60] = " Undefined user-supplied functions";
123  _exit_message[70] = " User requested termination";
124  _exit_message[80] = " Insufficient storage allocated";
125  _exit_message[90] = " Input arguments out of range";
126  _exit_message[100] = " Finished successfully (associated with SNOPT auxiliary routines) 110 Errors while processing MPS data";
127  _exit_message[120] = " Errors while estimating Jacobian structure";
128  _exit_message[130] = " Errors while reading the Specs file";
129  _exit_message[140] = " System error";
130 
131  _info_message[1] = "optimality conditions satisfied";
132  _info_message[2] = "feasible point found";
133  _info_message[3] = "requested accuracy could not be achieved";
134  _info_message[11] = "infeasible linear constraints";
135  _info_message[12] = "infeasible linear equality constraints";
136  _info_message[13] = "nonlinear infeasibilities minimized";
137  _info_message[14] = "linear infeasibilities minimized";
138  _info_message[15] = "infeasible linear constraints in QP subproblem";
139  _info_message[16] = "infeasible nonelastic constraints";
140  _info_message[21] = "unbounded objective";
141  _info_message[22] = "constraint violation limit reached";
142  _info_message[31] = "iteration limit reached";
143  _info_message[32] = "major iteration limit reached";
144  _info_message[33] = "the superbasics limit is too small";
145  _info_message[41] = "current point cannot be improved";
146  _info_message[42] = "singular basis";
147  _info_message[43] = "cannot satisfy the general constraints";
148  _info_message[44] = "ill-conditioned null-space basis";
149  _info_message[51] = "incorrect objective derivatives";
150  _info_message[52] = "incorrect constraint derivatives";
151  _info_message[56] = "irregular or badly scaled problem functions";
152  _info_message[61] = "undefined function at the first feasible point";
153  _info_message[62] = "undefined function at the initial point";
154  _info_message[63] = "unable to proceed into undefined region";
155  _info_message[71] = "terminated during function evaluation";
156  _info_message[72] = "terminated during constraint evaluation";
157  _info_message[73] = "terminated during objective evaluation";
158  _info_message[74] = "terminated from monitor routine";
159  _info_message[81] = "work arrays must have at least 500 elements";
160  _info_message[82] = "not enough character storage";
161  _info_message[83] = "not enough integer storage";
162  _info_message[84] = "not enough real storage";
163  _info_message[91] = "invalid input argument";
164  _info_message[92] = "basis file dimensions do not match this problem";
165  _info_message[141] = "wrong number of basic variables";
166  _info_message[142] = "error in basis package";
167 }
168 
169 
170 
171 void
174 
175 #if MAST_ENABLE_SNOPT == 1
177 
178  // make sure that these pointers haven't already been provided
179  libmesh_assert(_funobj == nullptr);
180  libmesh_assert(_funcon == nullptr);
181 
182  _funobj = feval.get_objective_evaluation_function();
183  _funcon = feval.get_constraint_evaluation_function();
184 #endif
185 }
186 
187 
188 
189 void
191 
192 #if MAST_ENABLE_SNOPT == 1
193  // make sure that functions have been provided
194  libmesh_assert(_funobj);
195  libmesh_assert(_funcon);
196 
198 
199  int
200  iPrint = 9,
201  iSpec = 4,
202  iSumm = 6,
203  lencw = 500,
204  N = _feval->n_vars(),
205  NCLIN = 0,
206  NCNLN = _feval->n_eq()+_feval->n_ineq(),
207  NCTOTL = N+NCLIN+NCNLN,
208  LDA = std::max(NCLIN, 1),
209  LDJ = std::max(NCNLN, 1),
210  LDR = N,
211  INFORM = 0, // on exit: Reports result of call to NPSOL
212  // < 0 either funobj or funcon has set this to -ve
213  // 0 => converged to point x
214  // 1 => x satisfies optimality conditions, but sequence of iterates has not converged
215  // 2 => Linear constraints and bounds cannot be satisfied. No feasible solution
216  // 3 => Nonlinear constraints and bounds cannot be satisfied. No feasible solution
217  // 4 => Major iter limit was reached
218  // 6 => x does not satisfy first-order optimality to required accuracy
219  // 7 => function derivatives seem to be incorrect
220  // 9 => input parameter invalid
221  ITER = 0, // iter count
222  LENIW = std::max(1200*(NCTOTL+N) ,1000),
223  LENW = std::max(2400*(NCTOTL+N), 1000);
224 
225  Real
226  F = 0.; // on exit: final objective
227 
228  std::vector<int>
229  IW (LENIW, 0),
230  ISTATE (NCTOTL, 0); // status of constraints l <= r(x) <= u,
231  // -2 => lower bound is violated by more than delta
232  // -1 => upper bound is violated by more than delta
233  // 0 => both bounds are satisfied by more than delta
234  // 1 => lower bound is active (to within delta)
235  // 2 => upper bound is active (to within delta)
236  // 3 => boundars are equal and equality constraint is satisfied
237 
238  std::vector<Real>
239  A (LDA, 0.), // this is used for liear constraints, not currently handled
240  BL (NCTOTL, 0.),
241  BU (NCTOTL, 0.),
242  C (NCNLN, 0.), // on exit: nonlinear constraints
243  CJAC (LDJ* N, 0.), //
244  // on exit: CJAC(i,j) is the partial derivative of ith nonlinear constraint
245  CLAMBDA (NCTOTL, 0.), // on entry: need not be initialized for cold start
246  // on exit: QP multiplier from the QP subproblem, >=0 if istate(j)=1, <0 if istate(j)=2
247  G (N, 0.), // on exit: objective gradient
248  R (LDR*N, 0.), // on entry: need not be initialized if called with Cold Statrt
249  // on exit: information about Hessian, if Hessian=Yes, R is upper Cholesky factor of approx H
250  X (N, 0.), // on entry: initial point
251  // on exit: final estimate of solution
252  W (LENW, 0.), // workspace
253  xmin (N, 0.),
254  xmax (N, 0.);
255 
256 
257  // now setup the lower and upper limits for the variables and constraints
258  _feval->_init_dvar_wrapper(X, xmin, xmax);
259  for (unsigned int i=0; i<N; i++) {
260  BL[i] = xmin[i];
261  BU[i] = xmax[i];
262  }
263 
264  // all constraints are assumed to be g_i(x) <= 0, so that the upper
265  // bound is 0 and lower bound is -infinity
266  for (unsigned int i=0; i<NCNLN; i++) {
267  BL[i+N] = -1.e20;
268  BU[i+N] = 0.;
269  }
270 
271  std::string cw(lencw*8,' ');
272 // nm = "List";
273 // npoptn_(nm.c_str(), (int)nm.length());
274 // nm = "Verify level 3";
275 // npoptn_(nm.c_str(), (int)nm.length());
276 
277  sninit_(&iPrint,
278  &iSumm,
279  cw.c_str(),
280  &lencw,
281  &IW[0],
282  &LENIW,
283  &W[0],
284  &LENW);
285 
286  snspec_(&iSpec, &INFORM, cw.c_str(), &lencw, &IW[0], &LENIW, &W[0], &LENW);
287 
288  if (INFORM != 101) libmesh_error();
289 
290  npopt_(&N,
291  &NCLIN,
292  &NCNLN,
293  &LDA,
294  &LDJ,
295  &LDR,
296  &A[0],
297  &BL[0],
298  &BU[0],
299  _funcon,
300  _funobj,
301  &INFORM,
302  &ITER,
303  &ISTATE[0],
304  &C[0],
305  &CJAC[0],
306  &CLAMBDA[0],
307  &F,
308  &G[0],
309  &R[0],
310  &X[0],
311  &IW[0],
312  &LENIW,
313  &W[0],
314  &LENW);
315 
317 
318 #endif // MAST_ENABLE_SNOPT 1
319 }
320 
321 
322 void
324 
325  int
326  exit = (INFORM%10)*10; // remove the last signifncant digit
327 
328  libmesh_assert(_exit_message.count(exit));
329  libmesh_assert(_info_message.count(INFORM));
330 
331  libMesh::out
332  << "SNOPT EXIT :" << exit << std::endl
333  << " " << _exit_message[exit] << std::endl
334  << " INFO :" << INFORM << std::endl
335  << " " << _info_message[INFORM] << std::endl << std::endl;
336 }
337 
338 
void npopt_(int *n, int *nclin, int *ncnln, int *ldA, int *ldgg, int *ldH, double *A, double *bl, double *bu, void(*)(int *mode, int *ncnln, int *n, int *ldJ, int *needc, double *x, double *c, double *cJac, int *nstate), void(*)(int *mode, int *n, double *x, double *f, double *g, int *nstate), int *INFO, int *majIts, int *iState, double *fCon, double *gCon, double *cMul, double *fObj, double *gObj, double *Hess, double *x, int *iw, int *leniw, double *re, int *lenrw)
void sanitize_parallel()
make sure that the analysis is setup consistently across all parallel processes
void snspec_(int *iSpecs, int *INFO, const char *cw, int *lencw, int *iw, int *leniw, double *rw, int *lenrw)
void sninitf_(const char *printfile, const char *summary_file, int *iPrint, int *iSumm, const char *cw, int *lencw, int *iw, int *leniw, double *rw, int *lenrw)
std::map< int, std::string > _exit_message
void sninit_(int *iPrint, int *iSumm, const char *cw, int *lencw, int *iw, int *leniw, double *rw, int *lenrw)
libMesh::Real Real
void snspecf_(const char *specsfile, int *INFO, const char *cw, int *lencw, int *iw, int *leniw, double *rw, int *lenrw)
std::map< int, std::string > _info_message
unsigned int n_ineq() const
virtual void attach_function_evaluation_object(MAST::FunctionEvaluation &feval)
Provides the basic interface API for classes the provide implement optimization problems.
virtual void attach_function_evaluation_object(MAST::FunctionEvaluation &feval)
unsigned int n_vars() const
void(* _funobj)(int *mode, int *n, double *x, double *f, double *g, int *nstate)
void(* _funcon)(int *mode, int *ncnln, int *n, int *ldJ, int *needc, double *x, double *c, double *cJac, int *nstate)
MAST::FunctionEvaluation * _feval
virtual void _init_dvar_wrapper(std::vector< Real > &x, std::vector< Real > &xmin, std::vector< Real > &xmax)
This serves as a wrapper around init_dvar() and makes sure that the derived class&#39;s implementation pr...
unsigned int n_eq() const
void npoptn_(const char *, int)