External Solvers: Difference between revisions
Restored page from Google Cache, uploaded by John Pye |
No edit summary |
||
| Line 1: | Line 1: | ||
All ASCEND [[NLA]] and [[NLP]] [[Solvers]] are loaded dynamically at runtime. This helps us to keep a tidy architecture in which solver code is kept by itself, and the 'core' part of ASCEND contains none of the numerical algorithms other than automatic differentiation, direct solution and a few other small things. | All ASCEND [[NLA]] and [[NLP]] [[Solvers]] are loaded dynamically at runtime. This helps us to keep a tidy architecture in which solver code is kept by itself, and the 'core' part of ASCEND contains none of the numerical algorithms other than automatic differentiation, direct solution and a few other small things. | ||
By default, [[QRSlv]], [[CONOPT]] (if available), [[LRSlv]], and [[CMSlv]] (if available) are loaded at launch. If you create your own '''external''' solver, you can load it my adding an <tt>IMPORT</tt> statement into your model file. We also plan to add import functionality via the scripting interface but this is not implemented yet. We currently don't support linear solvers via this mechanism: our API for those still needs a little work. | By default, [[QRSlv]], [[CONOPT]] (if available), [[LRSlv]], and [[CMSlv]] (if available) are loaded at launch. If you create your own '''external''' solver, you can load it my adding an <tt>IMPORT</tt> statement into your model file. We also plan to add import functionality via the scripting interface but this is not implemented yet. We currently don't support linear solvers via this mechanism: our API for those still needs a little work. | ||
The API is similar to that used for [[External_Integrators|'''External''' Integrators]] and still requires some more changes to the way that problem/system/solver APIs are connected together. The Python test-suite contains a large number of tests that provide a fair coverage of these functions, so we are fairly confident that the API changes can be made without too much inconvenience. | The API is similar to that used for [[External_Integrators|'''External''' Integrators]] and still requires some more changes to the way that problem/system/solver APIs are connected together. The Python test-suite contains a large number of tests that provide a fair coverage of these functions, so we are fairly confident that the API changes can be made without too much inconvenience. | ||
| Line 11: | Line 9: | ||
Some solvers are loaded by default, including [[QRSlv]] and the others listed above. If you have a solver that is not loaded by default, you can add a command at the start of your model file: | Some solvers are loaded by default, including [[QRSlv]] and the others listed above. If you have a solver that is not loaded by default, you can add a command at the start of your model file: | ||
<source lang="a4c">IMPORT "path/to/yoursolver";</source> | |||
<source lang="a4c">IMPORT | |||
This should cause the solver to be added to the list of available solvers. We still need to test this, however. | This should cause the solver to be added to the list of available solvers. We still need to test this, however. | ||
== How to write your own '''external''' solver for ASCEND == | == How to write your own '''external''' solver for ASCEND == | ||
| Line 22: | Line 18: | ||
To create your own '''external''' solver for ASCEND, you need to compile a DLL or shared object that can be loaded with the <tt>LoadArchiveLibrary("pathname/to/yourpackage")</tt> function from <tt>compiler/packages.h</tt>. This means that your DLL must contain a exported function called <tt>yourpackage_register</tt>. That function will be called when your DLL is first loaded, and it must 'tell ASCEND about' your solver. This means that you prepare a <tt>SlvFunctionsT</tt> structure containing the hook functions provided by your solver, and then call the <tt>solver_register(slvfunctions)</tt> function. You can return a non-zero value from <tt>yourpackage_register</tt> if there is anything that stops the solver from registering correctly, for example if other sub-solvers are not found, or a secondary DLL can't be loaded, etc. | To create your own '''external''' solver for ASCEND, you need to compile a DLL or shared object that can be loaded with the <tt>LoadArchiveLibrary("pathname/to/yourpackage")</tt> function from <tt>compiler/packages.h</tt>. This means that your DLL must contain a exported function called <tt>yourpackage_register</tt>. That function will be called when your DLL is first loaded, and it must 'tell ASCEND about' your solver. This means that you prepare a <tt>SlvFunctionsT</tt> structure containing the hook functions provided by your solver, and then call the <tt>solver_register(slvfunctions)</tt> function. You can return a non-zero value from <tt>yourpackage_register</tt> if there is anything that stops the solver from registering correctly, for example if other sub-solvers are not found, or a secondary DLL can't be loaded, etc. | ||
The contents of the SlvFunctionsT structure are described in the header file <tt>{{src|ascend/solver/solver.h}}</tt> and in a minimal solver, this will header may be the only one you need to include. However, most solvers make callbacks to other functions in 'libascend' so you will probably include <tt>{{src|ascend/system/slv_client.h}}</tt> and possibly others too. | The contents of the SlvFunctionsT structure are described in the header file <tt>{{src|ascend/solver/solver.h}}</tt> and in a minimal solver, this will header may be the only one you need to include. However, most solvers make callbacks to other functions in 'libascend' so you will probably include <tt>{{src|ascend/system/slv_client.h}}</tt> and possibly others too. | ||
| Line 30: | Line 25: | ||
Here is the snippet of code that does the registration of the [[QRSlv]] solver. Note that the optional hook function <tt>dump_internals</tt> is not provided by this solver. Not all hook functions are required for all solvers. | Here is the snippet of code that does the registration of the [[QRSlv]] solver. Note that the optional hook function <tt>dump_internals</tt> is not provided by this solver. Not all hook functions are required for all solvers. | ||
<source lang="c">static const SlvFunctionsT qrslv_internals = { | |||
<source lang=" | |||
SOLVER_QRSLV_EXT | SOLVER_QRSLV_EXT | ||
, | ,"QRSlv" | ||
,qrslv_create | ,qrslv_create | ||
,qrslv_destroy | ,qrslv_destroy | ||
| Line 48: | Line 42: | ||
,qrslv_get_jacobian | ,qrslv_get_jacobian | ||
,NULL /* dump_internals not defined for QRSlv */ | ,NULL /* dump_internals not defined for QRSlv */ | ||
}; | }; | ||
ASC_EXPORT int qrslv_register(void){ | ASC_EXPORT int qrslv_register(void){ | ||
return solver_register(& | return solver_register(&qrslv_internals); | ||
}</source> | }</source> | ||
| Line 60: | Line 52: | ||
See also [[External_Integrators|'''External''' Integrators]]. | See also [[External_Integrators|'''External''' Integrators]]. | ||
[[Category:Development]] | |||
Latest revision as of 13:35, 2 August 2010
All ASCEND NLA and NLP Solvers are loaded dynamically at runtime. This helps us to keep a tidy architecture in which solver code is kept by itself, and the 'core' part of ASCEND contains none of the numerical algorithms other than automatic differentiation, direct solution and a few other small things.
By default, QRSlv, CONOPT (if available), LRSlv, and CMSlv (if available) are loaded at launch. If you create your own external solver, you can load it my adding an IMPORT statement into your model file. We also plan to add import functionality via the scripting interface but this is not implemented yet. We currently don't support linear solvers via this mechanism: our API for those still needs a little work.
The API is similar to that used for External Integrators and still requires some more changes to the way that problem/system/solver APIs are connected together. The Python test-suite contains a large number of tests that provide a fair coverage of these functions, so we are fairly confident that the API changes can be made without too much inconvenience.
Using an external solver
Some solvers are loaded by default, including QRSlv and the others listed above. If you have a solver that is not loaded by default, you can add a command at the start of your model file:
IMPORT "path/to/yoursolver";
This should cause the solver to be added to the list of available solvers. We still need to test this, however.
How to write your own external solver for ASCEND
There are several examples currently in the solvers/ directories.
To create your own external solver for ASCEND, you need to compile a DLL or shared object that can be loaded with the LoadArchiveLibrary("pathname/to/yourpackage") function from compiler/packages.h. This means that your DLL must contain a exported function called yourpackage_register. That function will be called when your DLL is first loaded, and it must 'tell ASCEND about' your solver. This means that you prepare a SlvFunctionsT structure containing the hook functions provided by your solver, and then call the solver_register(slvfunctions) function. You can return a non-zero value from yourpackage_register if there is anything that stops the solver from registering correctly, for example if other sub-solvers are not found, or a secondary DLL can't be loaded, etc.
The contents of the SlvFunctionsT structure are described in the header file ascend/solver/solver.h and in a minimal solver, this will header may be the only one you need to include. However, most solvers make callbacks to other functions in 'libascend' so you will probably include ascend/system/slv_client.h and possibly others too.
Currently the solver functionality is pretty much tied to the mtx sparse-matrix data storage format. We do intend to de-couple this from libascend so that solvers can use arbitrary data storage. This is already possible in the Integrator API, but not yet with the Solver API. Part of fixing this requires boiling down the Linear API, which is yet to be tackled.
Here is the snippet of code that does the registration of the QRSlv solver. Note that the optional hook function dump_internals is not provided by this solver. Not all hook functions are required for all solvers.
static const SlvFunctionsT qrslv_internals = { SOLVER_QRSLV_EXT ,"QRSlv" ,qrslv_create ,qrslv_destroy ,qrslv_eligible_solver ,qrslv_get_default_parameters ,qrslv_get_parameters ,qrslv_set_parameters ,qrslv_get_status ,qrslv_solve ,qrslv_presolve ,qrslv_iterate ,qrslv_resolve ,qrslv_get_linsolqr_sys ,qrslv_get_jacobian ,NULL /* dump_internals not defined for QRSlv */ }; ASC_EXPORT int qrslv_register(void){ return solver_register(&qrslv_internals); }
Further documentation of these methods is available in ascend/solver/solver.h.
See also External Integrators.