1 /* _______________________________________________________________________
2
3 DAKOTA: Design Analysis Kit for Optimization and Terascale Applications
4 Copyright 2014-2020 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
5 This software is distributed under the GNU Lesser General Public License.
6 For more information, see the README file in the top Dakota directory.
7 _______________________________________________________________________ */
8
9 #ifdef _WIN32
10 #include "dakota_windows.h"
11 #define dlopen(x,y) LoadLibrary(x)
12 #define find_dlsym(a,b,c) (a = (dl_constructor_t)GetProcAddress((HINSTANCE)(b),c))
13 #define dlclose(x) FreeLibrary((HMODULE)x)
14 #define NO_DLERROR
15 #else
16 #include <dlfcn.h>
17 #define find_dlsym(a,b,c) (a = (dl_constructor_t)dlsym(b,c))
18 #undef NO_DLERROR
19 #endif
20 #include <stdarg.h>
21 #include "DLSolver.hpp"
22 #include "ProblemDescDB.hpp"
23
24 #ifdef DLSOLVER_DEBUG_UNLOCK
25 // This is only needed for the simplest example, dlsolvers/dl_npsol.C,
26 // which uses as much of DAKOTA's machinery for NPSOL as possible.
27 // (This machinery is compiled into DAKOTA unless configured with --without-npsol).
28 // The corresponding dl_npsol.dll is not loaded until the database is locked,
29 // but dl_npsol.dll then invokes "new NPSOLOptimizer(...)", which needs to
30 // have the database unlocked. Note that unlocking then may give wrong results
31 // in multi-specification runs. The configure machinery does not know about
32 // compilation with -DDLSOLVER_DEBUG_UNLOCK, since it is only meant for use
33 // in special cases by knowledgeable developers.
34 #define DEBUG_unlock probDescDB.unlock();
35 #define DEBUG_lock probDescDB.lock();
36 #else
37 #define DEBUG_unlock /*default: do nothing*/
38 #define DEBUG_lock /*default: do nothing*/
39 #endif
40
41 #define NO_DAKOTA_DLSOLVER_FUNCS_INLINE
42 #include "DLSfuncs.hpp"
43
44 namespace Dakota {
45
46 static RealVector const *
continuous_lower_bounds1(Optimizer1 * o)47 continuous_lower_bounds1(Optimizer1 *o)
48 { return &o->M->continuous_lower_bounds(); }
49
50 static RealVector const *
continuous_upper_bounds1(Optimizer1 * o)51 continuous_upper_bounds1(Optimizer1 *o)
52 { return &o->M->continuous_upper_bounds(); }
53
54 static RealVector const *
nonlinear_ineq_constraint_lower_bounds1(Optimizer1 * o)55 nonlinear_ineq_constraint_lower_bounds1(Optimizer1 *o)
56 { return &o->M->nonlinear_ineq_constraint_lower_bounds(); }
57
58 static RealVector const *
nonlinear_ineq_constraint_upper_bounds1(Optimizer1 * o)59 nonlinear_ineq_constraint_upper_bounds1(Optimizer1 *o)
60 { return &o->M->nonlinear_ineq_constraint_upper_bounds(); }
61
62 static RealVector const *
nonlinear_eq_constraint_targets1(Optimizer1 * o)63 nonlinear_eq_constraint_targets1(Optimizer1 *o)
64 { return &o->M->nonlinear_eq_constraint_targets(); }
65
66 static RealVector const *
linear_ineq_constraint_lower_bounds1(Optimizer1 * o)67 linear_ineq_constraint_lower_bounds1(Optimizer1 *o)
68 { return &o->M->linear_ineq_constraint_lower_bounds(); }
69
70 static RealVector const *
linear_ineq_constraint_upper_bounds1(Optimizer1 * o)71 linear_ineq_constraint_upper_bounds1(Optimizer1 *o)
72 { return &o->M->linear_ineq_constraint_upper_bounds(); }
73
74 static RealVector const *
linear_eq_constraint_targets1(Optimizer1 * o)75 linear_eq_constraint_targets1(Optimizer1 *o)
76 { return &o->M->linear_eq_constraint_targets(); }
77
78 static RealMatrix const *
linear_eq_constraint_coeffs1(Optimizer1 * o)79 linear_eq_constraint_coeffs1(Optimizer1 *o)
80 { return &o->M->linear_eq_constraint_coeffs(); }
81
82 static RealMatrix const *
linear_ineq_constraint_coeffs1(Optimizer1 * o)83 linear_ineq_constraint_coeffs1(Optimizer1 *o)
84 { return &o->M->linear_ineq_constraint_coeffs(); }
85
86 static void
ComputeResponses1(Optimizer1 * o,int mode,int n,double * x)87 ComputeResponses1(Optimizer1 *o, int mode, int n, double *x)
88 {
89 // without the printf, g++ generates incorrect code
90 if (n < 0)
91 printf("ComputeResponses1 has o = #%x, mode = %d, n = %d, x = #%x\n",
92 o, mode, n, x);
93 RealVector lx(n);
94 copy_data(x, n, lx);
95 o->M->continuous_variables(lx);
96 o->activeSet_()->request_values(mode);
97 o->M->evaluate(*o->activeSet_());
98 }
99
100 static void
GetFuncs1(Optimizer1 * o,int m0,int m1,double * f)101 GetFuncs1(Optimizer1 *o, int m0, int m1, double *f)
102 {
103 Response const *R = &o->M->current_response();
104 RealVector const *RV = &R->function_values();
105 for(int i = m0; i < m1; i++)
106 f[i-m0] = (*RV)[i];
107 }
108
109 static void
GetGrads1(Optimizer1 * o,int m0,int m1,int n,int is,int js,double * g)110 GetGrads1(Optimizer1 *o, int m0, int m1, int n, int is, int js, double *g)
111 {
112 int i, i1, j;
113 Response const *R = &o->M->current_response();
114 RealMatrix const *RM = &R->function_gradients();
115 Real const *RV;
116
117 for(i1 = 0, i = m0; i < m1; i++, i1 += is) {
118 RV = (*RM)[i];
119 for(j = 0; j < n; j++)
120 g[i1 + j*js] = RV[j];
121 }
122 }
123
124 static void
GetContVars1(Optimizer1 * o,int n,double * x)125 GetContVars1(Optimizer1 *o, int n, double *x)
126 { memcpy(x, &o->M->continuous_variables()[0], n*sizeof(double)); }
127
128 static void
SetBestContVars1(Optimizer1 * o,int n,double * x)129 SetBestContVars1(Optimizer1 *o, int n, double *x)
130 {
131 int i;
132 RealVector X(n);
133 for(i = 0; i < n; i++)
134 X[i] = x[i];
135 o->bestVariables_()->continuous_variables(X);
136 }
137
138 static void
SetBestDiscVars1(Optimizer1 * o,int n,int * x)139 SetBestDiscVars1(Optimizer1 *o, int n, int *x)
140 {
141 int i;
142 IntVector X(n);
143 for(i = 0; i < n; i++)
144 X[i] = x[i];
145 o->bestVariables_()->discrete_int_variables(X);
146 }
147
148 static void
SetBestRespFns1(Optimizer1 * o,int n,double * x)149 SetBestRespFns1(Optimizer1 *o, int n, double *x)
150 {
151 int i;
152 RealVector X(n);
153 for(i = 0; i < n; i++)
154 X[i] = x[i];
155 o->bestResponse_()->function_values(X);
156 }
157
158 static double
Get_Real1(Optimizer1 * o,const char * name)159 Get_Real1(Optimizer1*o, const char* name)
160 {
161 return o->problem_description_db().get_real(name);
162 }
163
164 static int
Get_Int1(Optimizer1 * o,const char * name)165 Get_Int1(Optimizer1*o, const char* name)
166 {
167 return o->problem_description_db().get_int(name);
168 }
169
170 static bool
Get_Bool1(Optimizer1 * o,const char * name)171 Get_Bool1(Optimizer1*o, const char* name)
172 {
173 return o->problem_description_db().get_bool(name);
174 }
175
176 Dakota_funcs DakFuncs0 = {
177 fprintf,
178 abort_handler,
179 dlsolver_option,
180 continuous_lower_bounds1,
181 continuous_upper_bounds1,
182 nonlinear_ineq_constraint_lower_bounds1,
183 nonlinear_ineq_constraint_upper_bounds1,
184 nonlinear_eq_constraint_targets1,
185 linear_ineq_constraint_lower_bounds1,
186 linear_ineq_constraint_upper_bounds1,
187 linear_eq_constraint_targets1,
188 linear_ineq_constraint_coeffs1,
189 linear_eq_constraint_coeffs1,
190 ComputeResponses1,
191 GetFuncs1,
192 GetGrads1,
193 GetContVars1,
194 SetBestContVars1,
195 SetBestDiscVars1,
196 SetBestRespFns1,
197 Get_Real1,
198 Get_Int1,
199 Get_Bool1
200 };
201
202 void
cleanup()203 DLSolver::cleanup()
204 {
205 void *h;
206 if (h = dlLib) {
207 dlLib = NULL;
208 if (dl_destructor)
209 (*dl_destructor)(&dl_Optimizer);
210 dlclose(h);
211 if (pdlLib)
212 *pdlLib = 0;
213 }
214 if (details) {
215 delete[] details;
216 details = 0;
217 }
218 if (DF) {
219 delete DF;
220 DF = 0;
221 }
222 }
223
224 void
botch(const char * fmt,...)225 DLSolver::botch(const char *fmt, ...)
226 {
227 va_list ap;
228 va_start(ap, fmt);
229 fprintf(stderr, "\nDLSolver Error: ");
230 vfprintf(stderr, fmt, ap);
231 putc('\n', stderr);
232 va_end(ap);
233 fflush(stderr);
234 cleanup();
235 abort_handler(-1);
236 }
237
DLSolver(Model & model)238 DLSolver::DLSolver(Model& model):
239 Optimizer1(model, std::shared_ptr<TraitsBase>(new DLSolverTraits())),
240 dl_core_run(0), dl_destructor(0), dlLib(0)
241 {
242 const String &dlDetails = probDescDB.get_string("method.dl_solver.dlDetails");
243 char *s, *s0;
244 size_t L;
245 void *h, **vp;
246
247 DF = 0;
248 L = strlen(s0 = dlDetails.data()) + 1;
249 details = s = new char[L];
250 if (!s)
251 botch("new(%lu) failure in DLSolver::DLSolver.", (unsigned long) L);
252 memcpy(s, s0, L);
253 vp = probDescDB.get_voidss("method.dl_solver.dlLib");
254 pdlLib = *vp ? vp : 0;
255 }
256
~DLSolver()257 DLSolver::~DLSolver()
258 { cleanup(); }
259
260 void
core_run()261 DLSolver::core_run()
262 {
263 Dakota_funcs *df;
264 Dakota_probsize ps;
265 char *s, *s0;
266 typedef void* (*dl_constructor_t)(Optimizer1*, Dakota_funcs*,
267 dl_core_run_t*, dl_destructor_t*);
268 dl_constructor_t dl_constructor;
269 void *h;
270 if (!dl_core_run) { // Load the shared library if this is
271 // the first core_run() invocation.
272 df = DF = new Dakota_funcs;
273 if (!df)
274 botch("new Dakota_Funcs failure");
275 memcpy(df, &DakFuncs0, sizeof(Dakota_funcs));
276 for(s0 = s = details; *s > ' '; s++);
277 if (s == s0)
278 botch("dlDetails not given for dl_solver.");
279 if (*s)
280 *s++ = 0;
281 if (pdlLib)
282 h = *pdlLib;
283 else
284 h = dlopen(s0, RTLD_NOW/*RTLD_LAZY*/);
285 if (!h)
286 #ifdef NO_DLERROR
287 botch("dlopen(\"%s\") failure", s0);
288 #else
289 botch("dlopen(\"%s\") failure:\n%s", s0, dlerror());
290 #endif
291 dlLib = h;
292 if (!(find_dlsym(dl_constructor, h, "dl_constructor")))
293 botch("dlsym(\"dl_constructor\") failed in \"%s\"", s0);
294 while(*s && *s <= ' ')
295 ++s;
296 options = s;
297 df->Stderr = stderr;
298 df->dakota_cerr = dakota_cerr;
299 df->dakota_cout = dakota_cout;
300 DEBUG_unlock
301 dl_Optimizer = (*dl_constructor)(this, df, &dl_core_run, &dl_destructor);
302 DEBUG_lock
303 }
304 if (dl_core_run) {
305 df = DF;
306 df->Stderr = stderr;
307 df->dakota_cerr = dakota_cerr;
308 df->dakota_cout = dakota_cout;
309 ps.n_var = numContinuousVars_();
310 ps.n_linc = numLinearConstraints_();
311 ps.n_nlinc = numNonlinearConstraints_();
312 ps.n_obj = numObjectiveFunctions_();
313 ps.maxfe = maxFunctionEvals_();
314 ps.numgflag = vendorNumericalGradFlag_();
315 ps.objrecast = localObjectiveRecast_();
316 df->ps = &ps;
317 M = iteratedModel_();
318 (*dl_core_run)(dl_Optimizer, this, options);
319 }
320 else
321 botch("dl_core_run is null in core_run");
322 }
323
324 int
dlsolver_option(Opt_Info * Oi)325 dlsolver_option(Opt_Info *Oi)
326 {
327 char *in, *in0, *s, *val0;
328 int c;
329
330 if (!(in = Oi->begin))
331 return 0;
332 while(*in <= ' ')
333 if (!*in++)
334 return 0;
335 Oi->name = in0 = in;
336 for(; (c = *in) > ' '; ++in) {
337 if (c == '_')
338 *in = Oi->und_repl;
339 else if (c == '=') {
340 *in = Oi->eq_repl;
341 break;
342 }
343 }
344 Oi->name_len = in - in0;
345 if (c == '=')
346 ++in;
347 if (!*in) {
348 no_val:
349 Oi->val = 0;
350 Oi->val_len = 0;
351 Oi->begin = in;
352 Oi->all_len = Oi->name_len;
353 return 1;
354 }
355 for(; (c = *in) <= ' '; ++in) {
356 if (!c)
357 goto no_val;
358 }
359 if (c == '=') {
360 *in++ = Oi->eq_repl;
361 while((c = *++in) <= ' ') {
362 if (!c)
363 goto no_val;
364 }
365 }
366 Oi->val = val0 = in;
367 if (c == '\'') {
368 for(s = in;;) {
369 c = *++in;
370 if (c == '\'') {
371 if (*++in != '\'')
372 break;
373 }
374 else if (!c)
375 break;
376 *s++ = c;
377 }
378 *s = 0;
379 Oi->val_len = s - val0;
380 }
381 else {
382 while(*++in > ' ');
383 Oi->val_len = in - val0;
384 }
385 while((c = *in) && c <= ' ')
386 ++in;
387 Oi->begin = in;
388 Oi->all_len = in - in0;
389 return 1;
390 }
391
392 } // namespace Dakota
393