k-order DLL: in use_dll mode, get model derivatives from preprocessor at an arbitrary order

Ref #217
time-shift
Sébastien Villemot 2019-04-15 16:46:39 +02:00
parent a101457cf0
commit 68aa1ace8f
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
3 changed files with 47 additions and 61 deletions

View File

@ -22,8 +22,9 @@
#include "dynare_exception.hh"
#include <iostream>
#include <cassert>
DynamicModelDLL::DynamicModelDLL(const std::string &modName, int ntt_arg)
DynamicModelDLL::DynamicModelDLL(const std::string &modName, int ntt_arg, int order)
: DynamicModelAC(ntt_arg)
{
std::string fName;
@ -34,45 +35,43 @@ DynamicModelDLL::DynamicModelDLL(const std::string &modName, int ntt_arg)
#if defined(__CYGWIN32__) || defined(_WIN32)
dynamicHinstance = LoadLibrary(fName.c_str());
if (!dynamicHinstance)
throw DynareException(__FILE__, __LINE__, "Error when loading " + fName + ": can't dynamically load the file");
dynamic_resid_tt = reinterpret_cast<dynamic_tt_fct>(GetProcAddress(dynamicHinstance, "dynamic_resid_tt"));
dynamic_resid = reinterpret_cast<dynamic_resid_fct>(GetProcAddress(dynamicHinstance, "dynamic_resid"));
dynamic_g1_tt = reinterpret_cast<dynamic_tt_fct>(GetProcAddress(dynamicHinstance, "dynamic_g1_tt"));
dynamic_g1 = reinterpret_cast<dynamic_g1_fct>(GetProcAddress(dynamicHinstance, "dynamic_g1"));
dynamic_g2_tt = reinterpret_cast<dynamic_tt_fct>(GetProcAddress(dynamicHinstance, "dynamic_g2_tt"));
dynamic_g2 = reinterpret_cast<dynamic_g2_fct>(GetProcAddress(dynamicHinstance, "dynamic_g2"));
dynamic_g3_tt = reinterpret_cast<dynamic_tt_fct>(GetProcAddress(dynamicHinstance, "dynamic_g3_tt"));
dynamic_g3 = reinterpret_cast<dynamic_g3_fct>(GetProcAddress(dynamicHinstance, "dynamic_g3"));
if (!dynamic_resid_tt || !dynamic_resid
|| !dynamic_g1_tt || !dynamic_g1
|| !dynamic_g2_tt || !dynamic_g2
|| !dynamic_g3_tt || !dynamic_g3)
{
FreeLibrary(dynamicHinstance); // Free the library
throw DynareException(__FILE__, __LINE__, "Error when loading " + fName + ": can't locate the relevant dynamic symbols within the MEX file");
}
#else // Linux or Mac
#else // GNU/Linux or Mac
dynamicHinstance = dlopen(fName.c_str(), RTLD_NOW);
if (!dynamicHinstance)
throw DynareException(__FILE__, __LINE__, "Error when loading " + fName + ": " + dlerror());
dynamic_resid_tt = reinterpret_cast<dynamic_tt_fct>(dlsym(dynamicHinstance, "dynamic_resid_tt"));
dynamic_resid = reinterpret_cast<dynamic_resid_fct>(dlsym(dynamicHinstance, "dynamic_resid"));
dynamic_g1_tt = reinterpret_cast<dynamic_tt_fct>(dlsym(dynamicHinstance, "dynamic_g1_tt"));
dynamic_g1 = reinterpret_cast<dynamic_g1_fct>(dlsym(dynamicHinstance, "dynamic_g1"));
dynamic_g2_tt = reinterpret_cast<dynamic_tt_fct>(dlsym(dynamicHinstance, "dynamic_g2_tt"));
dynamic_g2 = reinterpret_cast<dynamic_g2_fct>(dlsym(dynamicHinstance, "dynamic_g2"));
dynamic_g3_tt = reinterpret_cast<dynamic_tt_fct>(dlsym(dynamicHinstance, "dynamic_g3_tt"));
dynamic_g3 = reinterpret_cast<dynamic_g3_fct>(dlsym(dynamicHinstance, "dynamic_g3"));
if (!dynamic_resid_tt || !dynamic_resid
|| !dynamic_g1_tt || !dynamic_g1
|| !dynamic_g2_tt || !dynamic_g2
|| !dynamic_g3_tt || !dynamic_g3)
{
dlclose(dynamicHinstance); // Free the library
throw DynareException(__FILE__, __LINE__, "Error when loading " + fName + ": " + dlerror());
}
#endif
if (!dynamicHinstance)
throw DynareException(__FILE__, __LINE__, "Error when loading " + fName
#if !defined(__CYGWIN32__) && !defined(_WIN32)
+ ": " + dlerror()
#endif
);
for (int i = 0; i <= order; i++)
{
std::string funcname = "dynamic_" + (i == 0 ? "resid" : "g" + std::to_string(i));
void *deriv, *tt;
#if defined(__CYGWIN32__) || defined(_WIN32)
deriv = GetProcAddress(dynamicHinstance, funcname.c_str());
tt = GetProcAddress(dynamicHinstance, (funcname + "_tt").c_str());
#else
deriv = dlsym(dynamicHinstance, funcname.c_str());
tt = dlsym(dynamicHinstance, (funcname + "_tt").c_str());
#endif
if (!deriv || !tt)
{
#if defined(__CYGWIN32__) || defined(_WIN32)
FreeLibrary(dynamicHinstance);
#else
dlclose(dynamicHinstance);
#endif
throw DynareException(__FILE__, __LINE__, "Error when loading symbols from " + fName
#if !defined(__CYGWIN32__) && !defined(_WIN32)
+ ": " + dlerror()
#endif
);
}
dynamic_deriv.push_back(reinterpret_cast<dynamic_deriv_fct>(deriv));
dynamic_tt.push_back(reinterpret_cast<dynamic_tt_fct>(tt));
}
tt = std::make_unique<double[]>(ntt);
}
@ -95,18 +94,11 @@ void
DynamicModelDLL::eval(const Vector &y, const Vector &x, const Vector &modParams, const Vector &ySteady,
Vector &residual, std::vector<TwoDMatrix> &md) noexcept(false)
{
dynamic_resid_tt(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get());
dynamic_resid(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), residual.base());
dynamic_g1_tt(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get());
dynamic_g1(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), md[0].base());
if (md.size() >= 2)
assert(md.size() == dynamic_deriv.size()-1);
for (size_t i = 0; i < dynamic_deriv.size(); i++)
{
dynamic_g2_tt(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get());
dynamic_g2(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), md[1].base());
}
if (md.size() >= 3)
{
dynamic_g3_tt(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get());
dynamic_g3(y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), md[2].base());
dynamic_tt[i](y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get());
dynamic_deriv[i](y.base(), x.base(), 1, modParams.base(), ySteady.base(), 0, tt.get(), i == 0 ? residual.base() : md[i-1].base());
}
}

View File

@ -35,10 +35,7 @@
#include "dynamic_abstract_class.hh"
using dynamic_tt_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, double *T);
using dynamic_resid_fct = void (*) (const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *residual);
using dynamic_g1_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *g1);
using dynamic_g2_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *v2);
using dynamic_g3_fct = void (*)(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *v3);
using dynamic_deriv_fct = void (*) (const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *deriv);
/**
* creates pointer to Dynamic function inside <model>_dynamic.dll
@ -47,11 +44,8 @@ using dynamic_g3_fct = void (*)(const double *y, const double *x, int nb_row_x,
class DynamicModelDLL : public DynamicModelAC
{
private:
dynamic_tt_fct dynamic_resid_tt, dynamic_g1_tt, dynamic_g2_tt, dynamic_g3_tt;
dynamic_resid_fct dynamic_resid;
dynamic_g1_fct dynamic_g1;
dynamic_g2_fct dynamic_g2;
dynamic_g3_fct dynamic_g3;
std::vector<dynamic_tt_fct> dynamic_tt;
std::vector<dynamic_deriv_fct> dynamic_deriv;
#if defined(_WIN32) || defined(__CYGWIN32__)
HINSTANCE dynamicHinstance; // DLL instance pointer in Windows
#else
@ -61,7 +55,7 @@ private:
public:
// construct and load Dynamic model DLL
explicit DynamicModelDLL(const std::string &fname, int ntt_arg);
explicit DynamicModelDLL(const std::string &fname, int ntt_arg, int order);
virtual ~DynamicModelDLL();
void eval(const Vector &y, const Vector &x, const Vector &params, const Vector &ySteady,

View File

@ -176,7 +176,7 @@ extern "C" {
std::unique_ptr<DynamicModelAC> dynamicModelFile;
if (use_dll)
dynamicModelFile = std::make_unique<DynamicModelDLL>(fName, ntt);
dynamicModelFile = std::make_unique<DynamicModelDLL>(fName, ntt, kOrder);
else
dynamicModelFile = std::make_unique<DynamicModelMFile>(fName, ntt);