/[ascend]/trunk/base/generic/compiler/extfunc.h
ViewVC logotype

Contents of /trunk/base/generic/compiler/extfunc.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 914 - (show annotations) (download) (as text)
Sat Oct 28 05:27:58 2006 UTC (18 years ago) by johnpye
File MIME type: text/x-chdr
File size: 21622 byte(s)
Fixed prototype for extpy_destroy
Dubious fix for the message about directory node in doc/SConscript (is $ expansion happening?)

1 /*
2 ASCEND modelling environment
3 Copyright (C) 1990, 1993, 1994 Thomas Guthrie Epperly, Kirk Andre Abbott
4 Copyright (C) 2006 Benjamin Allan
5 Copyright (C) 2006 Carnegie Mellon University
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21 *//**
22 @file
23 External Functions Module.
24
25 This module implements the ExternalFunc structure referenced by
26 black and glass box structures and external methods.
27 The ExternalFunc structure stores the number of input and
28 output parameters (formal)
29 as well as 'help' string and 'name' string' for each of these 'calls'.
30
31 This header also provides functions for ExternalFunc library maintenance.
32 This allows ASCEND to maintain a list of the ExternalFunc requests derived
33 from statements in the model(s). When compilation completes, I suppose
34 it should be possible to alert the user about any external functions
35 that were not able to be resolved.
36
37 @todo Complete documentation of compiler/extfunc.h.
38
39 Requires:
40 #include "utilities/ascConfig.h"
41 #include "compiler/instance_enum.h"
42 #include "general/list.h"
43 #include "compiler/compiler.h"
44 *//*
45 by Kirk Andre Abbott and Ben Allan
46 Created: July 4, 1994.
47 Version: $Revision: 1.5 $
48 Version control file: $RCSfile: extfunc.h,v $
49 Date last modified: $Date: 1997/07/18 12:29:30 $
50 Last modified by: $Author: mthomas $
51 */
52
53 #ifndef ASC_EXTFUNC_H
54 #define ASC_EXTFUNC_H
55
56 #include <utilities/ascConfig.h>
57 #include "relation_util.h"
58
59 /*------------------------------------------------------------------------------
60 type definitions and forward decls
61 */
62
63 /**
64 ExtEvalFunc type is a function pointer.
65
66 @see rootfind.c:51
67
68 @param mode 'to pass to the eval function' (?)
69 @param m relation index
70 @param n variable index
71 @param x 'x' vector (?)
72 @param u 'u' vector (?)
73 @param f vector of residuals
74 @param g vector of gradients
75 */
76 typedef int ExtEvalFunc(int *mode, int *m, int *n,
77 double *x, double *u, double *f, double *g);
78
79 /**
80 This is an enum to clarify and make type-safer the
81 the variation of external functions circa 1995.
82 Blackboxes might be callable from methods as well (@TODO), but
83 this is dependent on their code registration to setup.
84 */
85 enum ExternalFuncType {
86 efunc_ERR = 0, /**< err value (Traps old mode errors too) */
87 efunc_BlackBox = 10, /**< remainder of struct is blackbox */
88 efunc_GlassBox = 20, /**< remainder of struct is glassbox */
89 efunc_Method = 30 /**< remainder of struct is method */
90 };
91
92 struct GlassBoxExternalFunc {
93 ExtEvalFunc *initial;
94 ExtEvalFunc **value; /**< array of relation residual functions. */
95 ExtEvalFunc **deriv; /**< array of relation gradient functions. */
96 ExtEvalFunc **deriv2; /**< array of relation hessian functions. */
97 ExtEvalFunc *final; /**< cleanup function. */
98 };
99
100
101 /** values a blackbox (or ?) can report when returning. */
102 enum Calc_status {
103 calc_converged,
104 calc_diverged,
105 calc_fp_error,
106 calc_incorrect_args,
107 calc_error,
108 calc_all_ok
109 };
110
111 /**
112 Things that a blackbox can be asked to do.
113
114 @NOTE Rhetorical question: Why do we want this? See comments in Slv_Interp.
115 */
116 enum Request_type {
117 bb_none, /**< do nothing. should never be sent. */
118 bb_first_call, /**< will be given when the initial function pointer is called. */
119 bb_last_call, /**< will be given when the final function pointer is called. */
120 bb_check_args, /**< do any argument checking of the variables, data */
121 bb_recalculate, /**< the caller thinks the input may have changed: recalc if reqd */
122 bb_func_eval, /**< the caller needs the residual function pointer. */
123 bb_deriv_eval, /**< the caller needs the deriv function pointer. */
124 bb_hess_eval, /**< the caller needs the hessian function pointer. */
125 bb_single_step /**< the caller would like one step toward the solution;
126 usually this is meaningless and should be answered with calc_diverged. */
127 };
128
129 /**
130 Each blackbox equation may show up more than once in a simulation
131 if models repeat in the structure. For each occurence of the
132 blackbox, a unique BBoxInterp object is given when the set of
133 corresponding relations is created.
134 It is used for the blackbox to communicate to the rest of the system.
135 If the blackbox retains internal state between evaluation calls,
136 it should store this state in the user_data pointer.
137 */
138 struct BBoxInterp {
139 /** status is set by blackbox calls before returning. */
140 enum Calc_status status;
141
142 /** user_data is set by the blackbox if it has any persistent state
143 during calls to initial and final functions given in
144 CreateUserFunctionBlackBox.
145 */
146 void *user_data;
147
148 /** What the caller wants done on a given call.
149
150 As black boxes are represented with 5 function pointers,
151 one might think this is not needed. Providing the 'task' here allows
152 one to implement only one function and have it handle all types of
153 calls. It also facilitates cases where there is checking rather than
154 evaluation.
155
156 @NOTE Problem? Don't init functions and evaluation functions have
157 different signatures?
158 */
159 enum Request_type task;
160 /* if someone still needs a nodestamp, we could go back to
161 defining one, but it should really be inside user_data as
162 ascend doesn't need it. */
163
164 };
165
166 typedef int ExtBBoxInitFunc(struct BBoxInterp *interp,
167 struct Instance *data,
168 struct gl_list_t *arglist);
169 /**<
170 Note Well: References to ascend instances must not be
171 cached in the user_data of interp, as instances may move
172 in the dynamically typed ASCEND world.
173 @param interp is the structure that all subsequent calls to
174 evaluation functions will include.
175 @param data is the DATA instance from the ascend model.
176 @param arglist is the input and output list of instance lists,
177 where each element corresponds to a formal argument.
178 Elements 1:n_formal_inputs are the inputs and the next
179 n_formal_outputs elements are the outputs.
180 @return 0 if ok, nonzero if some error makes the blackbox impossible.
181
182 */
183
184 typedef void ExtBBoxFinalFunc(struct BBoxInterp *interp);
185 /**< @param interp same as called in init and evaluate.
186 This is the opportunity to deallocate user_data as the
187 instance is being destroyed.
188 */
189
190 /**
191 External black box equations are of the block form
192 y_out = f(x_in). This block expands to N_outputs equations
193 of the form y_out[i] = f_i(x_in), where the functional details
194 of f are assumed to be smooth enough but otherwise totally hidden
195 and x_in, y_out are non-overlapping sets of variables.
196 The compiler will warn if overlap is detected.
197 Normal D.O.F. solver analysis applies in most cases.
198
199 Note that solvers are not psychic; if this blackbox is embedded
200 in a larger model such that some of y_out are inconsistently
201 fixed variables, the odds of convergence are small.
202 Cleverer solvers may issue a warning.
203
204 @param interp the control information is exchanged in interp;
205 interp->task should be consulted.
206 @param ninputs the length of the inputs, xi_in.
207 @param noutputs, the length of the outputs, y_out.
208
209 @param jacobian, the partial derivative df/dx, where
210 each row is df[i]/dx[j] over each j for the y_out[i] of
211 matching index. The jacobian array is 1-D, row major, i.e.
212 df[i]/dx[j] -> jacobian[i*ninputs+j].
213
214 @TODO this one may need splitting/rework for hessian.
215 */
216 typedef int ExtBBoxFunc(struct BBoxInterp *interp,
217 int ninputs, int noutputs,
218 double *inputs, double *outputs, double *jacobian);
219
220 struct BlackBoxExternalFunc {
221 ExtBBoxInitFunc *initial; /**< called after instance construction */
222 ExtBBoxFunc *value; /**< relation residual function. */
223 ExtBBoxFunc *deriv; /**< relation gradient function (see jacobian)*/
224 ExtBBoxFunc *deriv2; /**< relation hessian function. */
225 ExtBBoxFinalFunc *final; /**< cleanup function called at instance destruction. */
226 double inputTolerance; /**< largest change in an input variable
227 that is allowable without recalculating. */
228 };
229
230
231 /**
232 Function pointer (type) to implement an external method on a particular
233 instance
234
235 @param context the instance on which the method is run.
236 context may also appear explicitly in the arg list as SELF.
237 @param args Each element of args is a list of instances; each
238 name in the ascend-language argument list is expanded to a list
239 (which may contain 0 or more Instances) and appended to args.
240 @return ???
241 */
242 typedef int ExtMethodRun(struct Instance *context, struct gl_list_t *args, void *user_data);
243
244 /**
245 Setup/teardown, if any needed, for a particular instance.
246
247 We don't actually support this method anywhere right now, as
248 we're not sure what it can logically be used for that the
249 init function in dlopening shouldn't be doing.
250 In principal, we could add and cache a client-data pointer
251 in each instance so that the external method may be stateful.
252 Presently, the external methods must be clever to do that
253 on their own or must use ascend instances for state instead.
254 @param context the instance on which the method may be run.
255 */
256 typedef int ExtMethodInit( struct Instance *context);
257
258 /**
259 Destroy function (note comments for ExtMethodInit).
260
261 This function deallocated user_data for a particular external method.
262 In the case of external python script methods, for example, this will perform
263 Py_DECREF on the external script, so that python can unload it.
264
265 Couldn't see a way to do this without adding back this function here. -- JP
266
267 @return 0 on success, else error code.
268 */
269
270 typedef int ExtMethodDestroyFn( void *user_data);
271
272
273 struct MethodExternalFunc {
274 ExtMethodRun *run; /**< the method invoked. */
275 void *user_data; /**< I'd anticipate that this would be a function pointer
276 implemented in an external scripting language. Should only be accessed
277 from inside the 'run' function! -- JP */
278 ExtMethodDestroyFn *destroyfn;
279 };
280
281 struct ExternalFunc {
282 enum ExternalFuncType etype;
283 CONST char *name; /**< a string we own. */
284 CONST char *help; /**< a string we own. */
285 unsigned long n_inputs; /**< expected # of formal inputs. */
286 unsigned long n_outputs; /**< expected # of formal outputs. */
287 union {
288 struct GlassBoxExternalFunc glass;
289 struct BlackBoxExternalFunc black;
290 struct MethodExternalFunc method;
291 } u;
292 };
293
294 /*------------------------------------------------------------------------------
295 REGISTRATION / LOOKUP FUNCTIONS
296 */
297
298
299 extern void InitExternalFuncLibrary(void);
300 /**<
301 The main external functions library initialization routine. This
302 function must be called before all others.
303 */
304
305 extern void DestroyExtFuncLibrary(void);
306 /**<
307 Destroys the external function library and deallocates all the
308 information associated with it.
309 */
310
311
312 extern int AddExternalFunc(struct ExternalFunc *efunc, int force);
313 /**<
314 Adds an external function node to the external function library.
315 We look up the external function before adding it to the
316 library. If force is zero and the function exists then nothing
317 is done and 0 is returned. If force is true, then the old entry is
318 removed and the new one is added; 1 is returned. If the name is not
319 found then the information is added to the library.
320
321 @return 1 if an element is added to ExternalFunctionLibrary Table,
322 or 0 if no addition is made.
323 */
324
325 ASC_DLLSPEC(struct ExternalFunc *) LookupExtFunc(CONST char *funcname);
326 /**<
327 Returns the external function having the given name, or NULL if
328 not found.
329 */
330
331
332 extern struct ExternalFunc *RemoveExternalFunc(char *name);
333 /**<
334 Removes the external function having the given name from the
335 External function library.
336 */
337
338 extern void DestroyExternalFunc(struct ExternalFunc *name);
339 /**<
340 Destroys an external function, but does *not* remove it from the
341 library. Use the RemoveExternalFunc library first to retrieve the
342 information, then call this function.
343 */
344
345
346 extern void PrintExtFuncLibrary(FILE *f);
347 /**<
348 Prints the contents of the external function library to the given
349 file. The file must be opened for writing.
350 */
351
352 ASC_DLLSPEC(char *) WriteExtFuncLibraryString(void);
353 /**<
354 Returns a string of formatted information about the external functions
355 defined. the string looks like "{{name1} {help1}} {{name2} {help2}} "
356 The string may be empty/NULL if there are no external functions loaded.
357 */
358
359 /**
360 This provides a way for other code to visit the external function list
361 */
362 ASC_DLLSPEC(void) TraverseExtFuncLibrary(void (*)(void *,void *),void *secondparam);
363
364
365 /** fetch the required formal input count for glass, black, or method. */
366 ASC_DLLSPEC(unsigned long) NumberInputArgs(CONST struct ExternalFunc *efunc);
367
368 /** fetch the required formal output count for glass, black, or method. */
369 ASC_DLLSPEC(unsigned long) NumberOutputArgs(CONST struct ExternalFunc *efunc);
370
371
372 ASC_DLLSPEC(CONST char*) ExternalFuncName(CONST struct ExternalFunc *efunc);
373 /**<
374 Returns the name of an external function.
375 */
376
377 /*------------------------------------------------------------------------------
378 EXTERNAL METHOD STUFF
379 */
380
381 ASC_DLLSPEC(int) CreateUserFunctionMethod(CONST char *name
382 ,ExtMethodRun *run
383 ,CONST long n_args
384 ,CONST char *help
385 ,void *user_data
386 ,ExtMethodDestroyFn *destroyfn
387 );
388 /**<
389 * Adds an external method call to the ASCEND system.
390 * The name of the function is looked up. If it already exists, the
391 * information will be updated. If the name was not found in the
392 * external function library, then an external function node will be
393 * created and added to the external function library. We make a
394 * *copy* of the help string if it is provided. We also make a copy
395 * of the name. Anyone desirous of ASCEND knowing about their
396 * external methods must use this protocol.
397 *
398 *
399 * Note on blackbox integration with nonlinear solvers:
400 * The basic idea is that the blackbox has inputs x and outputs y
401 * that are all variables to the ascend model. Some of these may
402 * be fixed variables, but this is of no consequence to the blackbox
403 * routine unless one of the fixed variables is fixed outside the
404 * bounds of feasible input to the box. In the newton solution
405 * process there are three sets of values involved, x (inputs),
406 * yhat (the outputs as computed by the box), and y (the proposed
407 * values of the outputs in the model which may not match yhat
408 * until the entire model is converged. The many equations of the
409 * blackbox are hidden and represented by the reduced set of
410 * equations. In mathematical form, an array of equations:
411 * y = yhat(x); (ascend form bbrel: bboxname(inputs, outputs, data);)
412 * where yhat(x) is computed as bboxname(x,yhat).
413 * The bbox may produce the reduced gradient or be finite differenced
414 * to get dyhat/dx partial derivatives.
415 * The residual then, obviously, is yhat - y and the gradient is
416 * (in matrix form) I-dyhat/dx for the reduced equations.
417 *
418 * @param name Name of the function being added (or updated).
419 * @param initial Pointer to initialisation function, or NULL if none.
420 * @param run Pointer to the method.
421 * @param final Pointer to cleanup function, or NULL if none.
422 * @param n_args number of arguments expected as input, or -1 if any number is allowed.
423 * @return Returns 0 if the function was successfully added,
424 * non-zero otherwise.
425 */
426
427 /** Fetch method run function. */
428 extern ExtMethodRun *GetExtMethodRun(struct ExternalFunc *efunc);
429 extern void *GetExtMethodUserData(struct ExternalFunc *efunc);
430
431 /*------------------------------------------------------------------------------
432 BLACK BOX STUFF
433 */
434
435 /** Fetch black initialization function. */
436 extern ExtBBoxInitFunc *GetInitFunc(struct ExternalFunc *efunc);
437 /** Fetch black residual function. */
438 extern ExtBBoxFunc *GetValueFunc(struct ExternalFunc *efunc);
439 /** Fetch black sensitivity gradient function. */
440 extern ExtBBoxFunc *GetDerivFunc(struct ExternalFunc *efunc);
441 /** Fetch black hessian function. */
442 extern ExtBBoxFunc *GetDeriv2Func(struct ExternalFunc *efunc);
443 /** Fetch black cleanup function. */
444 extern ExtBBoxFinalFunc *GetFinalFunc(struct ExternalFunc *efunc);
445 /** Fetch black inputTolerance. */
446 extern double GetValueFuncTolerance(struct ExternalFunc *efunc);
447
448
449 ASC_DLLSPEC(int) CreateUserFunctionBlackBox(CONST char *name,
450 ExtBBoxInitFunc *init,
451 ExtBBoxFunc *value,
452 ExtBBoxFunc *deriv,
453 ExtBBoxFunc *deriv2,
454 ExtBBoxFinalFunc *final,
455 CONST unsigned long n_inputs,
456 CONST unsigned long n_outputs,
457 CONST char *help,
458 double inputTolerance
459 );
460 /**<
461 Adds an external function to the ASCEND system.
462 The name of the function is looked up. If it already exists, the
463 information will be updated. If the name was not found in the
464 external function library, then an external function node will be
465 created and added to the external function library. We make a
466 *copy* of the help string if it is provided. We also make a copy
467 of the name. Anyone desirous of ASCEND knowing about their
468 functions must use this protocol.
469
470 Note on blackbox integration with nonlinear solvers:
471 The basic idea is that the blackbox has inputs x and outputs y
472 that are all variables to the ascend model. Some of these may
473 be fixed variables, but this is of no consequence to the blackbox
474 routine unless one of the fixed variables is fixed outside the
475 bounds of feasible input to the box. In the newton solution
476 process there are three sets of values involved, x (inputs),
477 yhat (the outputs as computed by the box), and y (the proposed
478 values of the outputs in the model which may not match yhat
479 until the entire model is converged. The many equations of the
480 blackbox are hidden and represented by the reduced set of
481 equations. In mathematical form, an array of equations:
482 y = yhat(x); (ascend form bbrel: bboxname(inputs, outputs, data);)
483 where yhat(x) is computed as bboxname(x,yhat).
484 The bbox may produce the reduced gradient or be finite differenced
485 to get dyhat/dx partial derivatives.
486 The residual then, obviously, is yhat - y and the gradient is
487 (in matrix form) I-dyhat/dx for the reduced equations.
488
489 @param name Name of the function being added (or updated).
490 @param init Pointer to initialisation function, or NULL if none.
491 @param final Pointer to shutdown function. May be same as init.
492 @param value evaluation function pointers, or NULL if none.
493 @param deriv first partial derivative functions, or NULL if none.
494 @param deriv2 second derivative functions, or NULL if none.
495 @param inputTolerance maximum change in any of the inputs that is
496 allowable without recomputing the outputs.
497 0.0 is conservative, or specify a larger number if the
498 outputs are only mildly sensitive to small changes in inputs.
499 @return Returns 0 if the function was successfully added,
500 non-zero otherwise.
501 */
502
503
504 ASC_DLLSPEC(int) DefaultExtBBoxFuncDerivFD(
505 struct BBoxInterp *interp,
506 int ninputs,
507 int noutputs,
508 double *inputs,
509 double *outputs,
510 double *jacobian
511 );
512 /**< Default finite-differencing code for blackboxes.
513 If the user does not supply a derivative function they wrote,
514 they must supply this derivative function instead.
515 */
516
517 /*-----------------------------------------------------------------------------
518 GLASS BOX STUFF
519 */
520
521 ASC_DLLSPEC(int) CreateUserFunctionGlassBox(CONST char *name,
522 ExtEvalFunc *init,
523 ExtEvalFunc **value,
524 ExtEvalFunc **deriv,
525 ExtEvalFunc **deriv2,
526 ExtEvalFunc *final,
527 CONST unsigned long n_inputs, CONST unsigned long n_outputs,
528 CONST char *help
529 );
530 /**<
531 Adds an external function to the ASCEND system.
532 The name of the function is looked up. If it already exists, the
533 information will be updated. If the name was not found in the
534 external function library, then an external function node will be
535 created and added to the external function library. We make a
536 *copy* of the help string if it is provided. We also make a copy
537 of the name. Anyone desirous of ASCEND knowing about their
538 functions must use this protocol.
539
540 @param name Name of the function being added (or updated).
541 @param init Pointer to initialisation function, or NULL if none.
542 @param value array of evaluation function pointers,
543 or NULL if none.
544 @param deriv array of first partial
545 derivative functions, or NULL if none.
546 @param deriv2 array of second derivative
547 functions, or NULL if none.
548 @return Returns 0 if the function was successfully added,
549 non-zero otherwise.
550 */
551
552 /** Fetch glass initialization function. */
553 extern ExtEvalFunc *GetGlassBoxInit(struct ExternalFunc *efunc);
554 /** Get glass box residual function array. */
555 extern ExtEvalFunc **GetValueJumpTable(struct ExternalFunc *efunc);
556 /** Get glass box gradient function array. */
557 extern ExtEvalFunc **GetDerivJumpTable(struct ExternalFunc *efunc);
558 /** Get glass box hessian function array. */
559 extern ExtEvalFunc **GetDeriv2JumpTable(struct ExternalFunc *efunc);
560 /** Fetch black initialization function. */
561 extern ExtEvalFunc *GetGlassBoxFinal(struct ExternalFunc *efunc);
562
563 #endif /* ASC_EXTFUNC_H */

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22