Skip to content
Snippets Groups Projects
Select Git revision
2 results Searching

dynare_simul.cpp

Blame
  • dynare_simul.cpp 4.58 KiB
    // Copyright (C) 2005-2011, Ondra Kamenik
    
    // This is the mexFunction providing interface to
    // DecisionRule<>::simulate(). It takes the following input
    // parameters:
    //      order    the order of approximation, needs order+1 derivatives
    //      nstat
    //      npred
    //      nboth
    //      nforw
    //      nexog
    //      ystart   starting value (full vector of endogenous)
    //      shocks   matrix of shocks (nexog x number of period)
    //      vcov     covariance matrix of shocks (nexog x nexog)
    //      seed     integer seed
    //      ysteady  full vector of decision rule's steady
    //      ...      order+1 matrices of derivatives
    
    // output:
    //      res      simulated results
    
    #include "dynmex.h"
    #include "mex.h"
    
    #include "decision_rule.h"
    #include "fs_tensor.h"
    #include "SylvException.h"
    
    extern "C" {
    	void mexFunction(int nlhs, mxArray* plhs[],
    					 int nhrs, const mxArray* prhs[])
    	{
    		if (nhrs < 12 || nlhs != 2)
                      DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have at least 12 input parameters and exactly 2 output arguments.\n");
    
    		int order = (int)mxGetScalar(prhs[0]);
    		if (nhrs != 12 + order)
                      DYN_MEX_FUNC_ERR_MSG_TXT("dynare_simul_ must have exactly 11+order input parameters.\n");
    
    		int nstat = (int)mxGetScalar(prhs[1]);
    		int npred = (int)mxGetScalar(prhs[2]);
    		int nboth = (int)mxGetScalar(prhs[3]);
    		int nforw = (int)mxGetScalar(prhs[4]);
    		int nexog = (int)mxGetScalar(prhs[5]);
    
    		const mxArray* const ystart = prhs[6];
    		const mxArray* const shocks = prhs[7];
    		const mxArray* const vcov = prhs[8];
    		int seed = (int)mxGetScalar(prhs[9]);
    		const mxArray* const ysteady = prhs[10];
    		const mwSize* const ystart_dim = mxGetDimensions(ystart);
    		const mwSize* const shocks_dim = mxGetDimensions(shocks);
    		const mwSize* const vcov_dim = mxGetDimensions(vcov);
    		const mwSize* const ysteady_dim = mxGetDimensions(ysteady);
    
    		int ny = nstat + npred + nboth + nforw;
    		if (ny != (int) ystart_dim[0])
    			DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of rows.\n");
    		if (1 != ystart_dim[1])
    			DYN_MEX_FUNC_ERR_MSG_TXT("ystart has wrong number of cols.\n");
    		int nper = shocks_dim[1];
    		if (nexog != (int) shocks_dim[0])
    			DYN_MEX_FUNC_ERR_MSG_TXT("shocks has a wrong number of rows.\n");
    		if (nexog != (int) vcov_dim[0])
    			DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of rows.\n");
    		if (nexog != (int) vcov_dim[1])
    			DYN_MEX_FUNC_ERR_MSG_TXT("vcov has a wrong number of cols.\n");
    		if (ny != (int) ysteady_dim[0])
    			DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of rows.\n");
    		if (1 != ysteady_dim[1])
    			DYN_MEX_FUNC_ERR_MSG_TXT("ysteady has wrong number of cols.\n");
    
    		mxArray* res = mxCreateDoubleMatrix(ny, nper, mxREAL);
    
    		try {
    			// initialize tensor library
    			tls.init(order, npred+nboth+nexog);
    
    			// form the polynomial
    			UTensorPolynomial pol(ny, npred+nboth+nexog);
    			for (int dim = 0; dim <= order; dim++) {
    				const mxArray* gk = prhs[11+dim];
    				const mwSize* const gk_dim = mxGetDimensions(gk);
    				FFSTensor ft(ny, npred+nboth+nexog, dim);
    				if (ft.ncols() != (int) gk_dim[1]) {
    					char buf[1000];
    					sprintf(buf, "Wrong number of columns for folded tensor: got %d but I want %d\n",
    						(int) gk_dim[1], ft.ncols());
    					DYN_MEX_FUNC_ERR_MSG_TXT(buf);
    				}
    				if (ft.nrows() != (int) gk_dim[0]) {
    					char buf[1000];
    					sprintf(buf, "Wrong number of rows for folded tensor: got %d but I want %d\n",
    						(int) gk_dim[0], ft.nrows());
    					DYN_MEX_FUNC_ERR_MSG_TXT(buf);
    				}
    				ft.zeros();
    				ConstTwoDMatrix gk_mat(ft.nrows(), ft.ncols(), mxGetPr(gk));
    				ft.add(1.0, gk_mat);
    				UFSTensor* ut = new UFSTensor(ft);
    				pol.insert(ut);
    			}
    			// form the decision rule
    			UnfoldDecisionRule
    				dr(pol, PartitionY(nstat, npred, nboth, nforw),
    				   nexog, ConstVector(mxGetPr(ysteady), ny));
    			// form the shock realization
    			TwoDMatrix shocks_mat(nexog, nper, (const double*)mxGetPr(shocks));
    			TwoDMatrix vcov_mat(nexog, nexog, (const double*)mxGetPr(vcov));
    			GenShockRealization sr(vcov_mat, shocks_mat, seed);
    			// simulate and copy the results
    			Vector ystart_vec((const double*)mxGetPr(ystart), ny);
    			TwoDMatrix* res_mat =
    				dr.simulate(DecisionRule::horner, nper,
    							ystart_vec, sr);
    			TwoDMatrix res_tmp_mat(ny, nper, mxGetPr(res));
    			res_tmp_mat = (const TwoDMatrix&)(*res_mat);
    			delete res_mat;
    			plhs[1] = res;
    		} catch (const KordException& e) {
    			DYN_MEX_FUNC_ERR_MSG_TXT("Caugth Kord exception.");
    		} catch (const TLException& e) {
    			DYN_MEX_FUNC_ERR_MSG_TXT("Caugth TL exception.");
    		} catch (SylvException& e) {
    			DYN_MEX_FUNC_ERR_MSG_TXT("Caught Sylv exception.");
    		}
                    plhs[0] = mxCreateDoubleScalar(0);
    	}
    };