Skip to content
Snippets Groups Projects
Select Git revision
  • 3f2d2b3497184c38dda877b8f90eebc0ac7b9ea5
  • master default protected
  • 6.x protected
  • madysson
  • 5.x protected
  • asm
  • time-varying-information-set
  • 4.6 protected
  • dynare_minreal
  • dragonfly
  • various_fixes
  • 4.5 protected
  • clang+openmp
  • exo_steady_state
  • declare_vars_in_model_block
  • julia
  • error_msg_undeclared_model_vars
  • static_aux_vars
  • slice
  • aux_func
  • penalty
  • 6.4 protected
  • 6.3 protected
  • 6.2 protected
  • 6.1 protected
  • 6.0 protected
  • 6-beta2 protected
  • 6-beta1 protected
  • 5.5 protected
  • 5.4 protected
  • 5.3 protected
  • 5.2 protected
  • 5.1 protected
  • 5.0 protected
  • 5.0-rc1 protected
  • 4.7-beta3 protected
  • 4.7-beta2 protected
  • 4.7-beta1 protected
  • 4.6.4 protected
  • 4.6.3 protected
  • 4.6.2 protected
41 results

compute_mh_covariance_matrix.m

Blame
  • DynamicModelCaller.hh 6.00 KiB
    /*
     * Copyright © 2019-2023 Dynare Team
     *
     * This file is part of Dynare.
     *
     * Dynare is free software: you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     *
     * Dynare is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with Dynare.  If not, see <https://www.gnu.org/licenses/>.
     */
    
    #include <algorithm>
    #include <limits>
    #include <memory>
    #include <string>
    #include <type_traits>
    #include <vector>
    
    #include <dynmex.h>
    
    #if defined(_WIN32) || defined(__CYGWIN32__)
    # ifndef NOMINMAX
    #  define NOMINMAX // Do not define "min" and "max" macros
    # endif
    # include <windows.h>
    #else
    # include <dlfcn.h> // unix/linux DLL (.so) handling routines
    #endif
    
    class DynamicModelCaller
    {
    public:
      const bool linear;
      bool compute_jacobian; // Not constant, because will be changed from true to false for linear
                             // models after first evaluation
    
      // Used to store error messages (as exceptions cannot cross the OpenMP boundary)
      static std::string error_msg;
    
      DynamicModelCaller(bool linear_arg, bool compute_jacobian_arg) :
          linear {linear_arg}, compute_jacobian {compute_jacobian_arg}
      {
      }
      virtual ~DynamicModelCaller() = default;
      [[nodiscard]] virtual double* y() = 0;
      [[nodiscard]] virtual double* x() = 0;
      /* Copy a column of the Jacobian to dest.
         Only copies non-zero elements, according to g1_sparse_{rowval,colval,colptr}. */
      virtual void copy_jacobian_column(mwIndex col, double* dest) const = 0;
      virtual void eval(double* resid) = 0;
    };
    
    class DynamicModelDllCaller : public DynamicModelCaller
    {
    private:
    #if defined(_WIN32) || defined(__CYGWIN32__)
      static HINSTANCE resid_mex, g1_mex;
    #else
      static void *resid_mex, *g1_mex;
    #endif
      using dynamic_tt_fct = void (*)(const double* y, const double* x, const double* params,
                                      const double* steady_state, double* T);
      using dynamic_fct = void (*)(const double* y, const double* x, const double* params,
                                   const double* steady_state, const double* T, double* value);
      static dynamic_tt_fct residual_tt_fct, g1_tt_fct;
      static dynamic_fct residual_fct, g1_fct;
      const double *params, *steady_state;
      std::vector<double> tt, y_p, x_p, jacobian_p;
      const int32_T* g1_sparse_colptr;
    
    public:
      DynamicModelDllCaller(size_t ntt, mwIndex ny, mwIndex nx, const double* params_arg,
                            const double* steady_state_arg, const int32_T* g1_sparse_colptr_arg,
                            bool linear_arg, bool compute_jacobian_arg);
      [[nodiscard]] double*
      y() override
      {
        return y_p.data();
      }
      [[nodiscard]] double*
      x() override
      {
        return x_p.data();
      }
      void copy_jacobian_column(mwIndex col, double* dest) const override;
      void eval(double* resid) override;
      static void load_dll(const std::string& basename);
      static void unload_dll();
    };
    
    class DynamicModelMatlabCaller : public DynamicModelCaller
    {
    private:
      std::string basename;
      mxArray *y_mx, *x_mx, *jacobian_mx, *params_mx, *steady_state_mx, *g1_sparse_rowval_mx,
          *g1_sparse_colval_mx, *g1_sparse_colptr_mx;
      /* Given a complex matrix (of double floats), returns a sparse matrix of same size.
         Real elements of the original matrix are copied as-is to the new one.
         Complex elements are replaced by NaNs.
         Destroys the original matrix.
         There are two versions, one for dense matrices, another for sparse
         matrices. */
      template<bool sparse>
      static mxArray* cmplxToReal(mxArray* cmplx_mx);
    
    public:
      DynamicModelMatlabCaller(std::string basename_arg, mwIndex ny, mwIndex nx,
                               const mxArray* params_mx_arg, const mxArray* steady_state_mx_arg,
                               const mxArray* g1_sparse_rowval_mx_arg,
                               const mxArray* g1_sparse_colval_mx_arg,
                               const mxArray* g1_sparse_colptr_mx_arg, bool linear_arg,
                               bool compute_jacobian_arg);
      ~DynamicModelMatlabCaller() override;
      [[nodiscard]] double*
      y() override
      {
        return mxGetPr(y_mx);
      }
      [[nodiscard]] double*
      x() override
      {
        return mxGetPr(x_mx);
      }
      void copy_jacobian_column(mwIndex col, double* dest) const override;
      void eval(double* resid) override;
      class Exception
      {
      public:
        const std::string msg;
        Exception(std::string msg_arg) : msg {std::move(msg_arg)}
        {
        }
      };
    };
    
    template<bool sparse>
    mxArray*
    DynamicModelMatlabCaller::cmplxToReal(mxArray* cmplx_mx)
    {
      mxArray* real_mx {
          sparse ? mxCreateSparse(mxGetM(cmplx_mx), mxGetN(cmplx_mx), mxGetNzmax(cmplx_mx), mxREAL)
                 : mxCreateDoubleMatrix(mxGetM(cmplx_mx), mxGetN(cmplx_mx), mxREAL)};
    
      if constexpr (sparse)
        {
          std::copy_n(mxGetIr(cmplx_mx), mxGetNzmax(cmplx_mx), mxGetIr(real_mx));
          std::copy_n(mxGetJc(cmplx_mx), mxGetN(cmplx_mx) + 1, mxGetJc(real_mx));
        }
    
    #if MX_HAS_INTERLEAVED_COMPLEX
      mxComplexDouble* cmplx {mxGetComplexDoubles(cmplx_mx)};
    #else
      double* cmplx_real {mxGetPr(cmplx_mx)};
      double* cmplx_imag {mxGetPi(cmplx_mx)};
    #endif
      double* real {mxGetPr(real_mx)};
      for (std::conditional_t<sparse, mwSize, size_t> i {0};
           i <
           [&] {
             if constexpr (sparse)
               return mxGetNzmax(cmplx_mx);
             else
               return mxGetNumberOfElements(cmplx_mx);
           }(); // Use a lambda instead of the ternary operator to have the right type (there is no
                // constexpr ternary operator)
           i++)
    #if MX_HAS_INTERLEAVED_COMPLEX
        if (cmplx[i].imag == 0.0)
          real[i] = cmplx[i].real;
    #else
        if (cmplx_imag[i] == 0.0)
          real[i] = cmplx_real[i];
    #endif
        else
          real[i] = std::numeric_limits<double>::quiet_NaN();
    
      mxDestroyArray(cmplx_mx);
      return real_mx;
    }