/* * Copyright © 2007-2020 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 . */ #include #include "Interpreter.hh" #include "ErrorHandling.hh" #include #include #ifdef DEBUG_EX using namespace std; # include string Get_Argument(const char *argv) { string f(argv); return f; } #else void (*prev_fn)(int); string Get_Argument(const mxArray *prhs) { const mxArray *mxa = prhs; mwSize buflen = mwSize(mxGetM(mxa) * mxGetN(mxa) + 1); char *first_argument; first_argument = static_cast(mxCalloc(buflen, sizeof(char))); size_t status = mxGetString(mxa, first_argument, buflen); if (status != 0) mexWarnMsgTxt("Not enough space. The first argument is truncated."); string f(first_argument); mxFree(first_argument); return f; } #endif //#include #include #ifdef CUDA int GPU_Test_and_Info(cublasHandle_t *cublas_handle, cusparseHandle_t *cusparse_handle, cusparseMatDescr_t *descr) { cudaDeviceProp deviceProp; int device_count, device, version, version_max = 0; cublasStatus_t cublas_status; cudaError_t cuda_error; *descr = 0; /* ask cuda how many devices it can find */ cudaGetDeviceCount(&device_count); if (device_count < 1) { /* if it couldn't find any fail out */ ostringstream tmp; tmp << " Unable to find a CUDA device. Unable to implement CUDA solvers\n"; throw FatalExceptionHandling(tmp.str()); } else { mexPrintf("-----------------------------------------\n"); for (int i = 0; i < device_count; i++) { cudaSetDevice(i); // Statistics about the GPU device cuda_error = cudaGetDeviceProperties(&deviceProp, i); if (cuda_error != cudaSuccess) { ostringstream tmp; tmp << " bytecode cudaGetDeviceProperties failed\n"; throw FatalExceptionHandling(tmp.str()); } mexPrintf("> GPU device %d: \"%s\" has:\n - %d Multi-Processors,\n - %d threads per multiprocessor,\n", i, deviceProp.name, deviceProp.multiProcessorCount, deviceProp.maxThreadsPerMultiProcessor); mexEvalString("drawnow;"); version = (deviceProp.major * 0x10 + deviceProp.minor); if (version >= version_max) { device = i; version_max = version; } mexPrintf(" - %4.2fMhz clock rate,\n - %2.0fMb of memory,\n - %d.%d compute capabilities.\n", double (deviceProp.clockRate) / (1024 * 1024), double (deviceProp.totalGlobalMem) / (1024 * 1024), deviceProp.major, deviceProp.minor); mexEvalString("drawnow;"); } } mexPrintf("> Device %d selected\n", device); mexEvalString("drawnow;"); cuda_error = cudaSetDevice(device); if (cuda_error != cudaSuccess) { ostringstream tmp; tmp << " bytecode cudaSetDevice failed\n"; throw FatalExceptionHandling(tmp.str()); } if (version_max < 0x11) { ostringstream tmp; tmp << " bytecode requires a minimum CUDA compute 1.1 capability\n"; cudaDeviceReset(); throw FatalExceptionHandling(tmp.str()); } // Initialize CuBlas library cublas_status = cublasCreate(cublas_handle); if (cublas_status != CUBLAS_STATUS_SUCCESS) { ostringstream tmp; switch (cublas_status) { case CUBLAS_STATUS_NOT_INITIALIZED: tmp << " the CUBLAS initialization failed.\n"; break; case CUBLAS_STATUS_ALLOC_FAILED: tmp << " the resources could not be allocated.\n"; break; default: tmp << " unknown error during the initialization of cusparse library.\n"; } throw FatalExceptionHandling(tmp.str()); } // Initialize the CuSparse library cusparseStatus_t cusparse_status; cusparse_status = cusparseCreate(cusparse_handle); if (cusparse_status != CUSPARSE_STATUS_SUCCESS) { ostringstream tmp; switch (cusparse_status) { case CUSPARSE_STATUS_NOT_INITIALIZED: tmp << " the CUDA Runtime initialization failed.\n"; break; case CUSPARSE_STATUS_ALLOC_FAILED: tmp << " the resources could not be allocated.\n"; break; case CUSPARSE_STATUS_ARCH_MISMATCH: tmp << " the device compute capability (CC) is less than 1.1. The CC of at least 1.1 is required.\n"; break; default: tmp << " unknown error during the initialization of cusparse library.\n"; } throw FatalExceptionHandling(tmp.str()); } // Create and setup matrix descriptor cusparse_status = cusparseCreateMatDescr(descr); if (cusparse_status != CUSPARSE_STATUS_SUCCESS) { ostringstream tmp; tmp << " Matrix descriptor initialization failed\n"; throw FatalExceptionHandling(tmp.str()); } cusparseSetMatType(*descr, CUSPARSE_MATRIX_TYPE_GENERAL); cusparseSetMatIndexBase(*descr, CUSPARSE_INDEX_BASE_ZERO); mexPrintf("> Driver version:\n"); int cuda_version; cuda_error = cudaDriverGetVersion(&cuda_version); if (cuda_error != cudaSuccess) { ostringstream tmp; tmp << " cudaGetVersion has failed\n"; throw FatalExceptionHandling(tmp.str()); } mexPrintf(" - CUDA version %5.3f\n", double (cuda_version) / 1000); int cublas_version; cublas_status = cublasGetVersion(*cublas_handle, &cublas_version); if (cublas_status != CUBLAS_STATUS_SUCCESS) { ostringstream tmp; tmp << " cublasGetVersion has failed\n"; throw FatalExceptionHandling(tmp.str()); } mexPrintf(" - CUBLAS version %5.3f\n", double (cublas_version) / 1000); int cusparse_version; cusparse_status = cusparseGetVersion(*cusparse_handle, &cusparse_version); if (cusparse_status != CUSPARSE_STATUS_SUCCESS) { ostringstream tmp; tmp << " cusparseGetVersion has failed\n"; throw FatalExceptionHandling(tmp.str()); } mexPrintf(" - CUSPARSE version %5.3f\n", double (cusparse_version) / 1000); mexPrintf("-----------------------------------------\n"); return device; } void GPU_close(cublasHandle_t cublas_handle, cusparseHandle_t cusparse_handle, cusparseMatDescr_t descr) { cublasChk(cublasDestroy(cublas_handle), "in bytecode cublasDestroy failed\n"); cusparseChk(cusparseDestroyMatDescr(descr), "in bytecode cusparseDestroyMatDescr failed\n"); cusparseChk(cusparseDestroy(cusparse_handle), "in bytecode cusparseDestroy failed\n"); } #endif string deblank(string x) { for (int i = 0; i < static_cast(x.length()); i++) if (x[i] == ' ') x.erase(i--, 1); return x; } void Get_Arguments_and_global_variables(int nrhs, #ifndef DEBUG_EX const mxArray *prhs[], #else const char *prhs[], #endif int &count_array_argument, double *yd[], size_t &row_y, size_t &col_y, double *xd[], size_t &row_x, size_t &col_x, double *params[], double *steady_yd[], size_t &steady_row_y, size_t &steady_col_y, unsigned int &periods, #ifndef DEBUG_EX mxArray *block_structur[], #endif bool &steady_state, bool &evaluate, int &block, mxArray *M_[], mxArray *oo_[], mxArray *options_[], bool &global_temporary_terms, bool &print, bool &print_error, mxArray *GlobalTemporaryTerms[], string *plan_struct_name, string *pfplan_struct_name, bool *extended_path, mxArray *ep_struct[]) { size_t pos; *extended_path = false; #ifdef DEBUG_EX for (int i = 2; i < nrhs; i++) #else for (int i = 0; i < nrhs; i++) #endif { #ifndef DEBUG_EX if (!mxIsChar(prhs[i])) { switch (count_array_argument) { case 0: *yd = mxGetPr(prhs[i]); row_y = mxGetM(prhs[i]); col_y = mxGetN(prhs[i]); break; case 1: *xd = mxGetPr(prhs[i]); row_x = mxGetM(prhs[i]); col_x = mxGetN(prhs[i]); break; case 2: *params = mxGetPr(prhs[i]); break; case 3: *steady_yd = mxGetPr(prhs[i]); steady_row_y = mxGetM(prhs[i]); steady_col_y = mxGetN(prhs[i]); break; case 4: periods = int (mxGetScalar(prhs[i])); break; case 5: *block_structur = mxDuplicateArray(prhs[i]); break; case 6: global_temporary_terms = true; *GlobalTemporaryTerms = mxDuplicateArray(prhs[i]); break; default: mexPrintf("Unknown argument count_array_argument=%d\n", count_array_argument); break; } count_array_argument++; } else #endif if (Get_Argument(prhs[i]) == "static") steady_state = true; else if (Get_Argument(prhs[i]) == "dynamic") steady_state = false; else if (Get_Argument(prhs[i]) == "evaluate") evaluate = true; else if (Get_Argument(prhs[i]) == "global_temporary_terms") global_temporary_terms = true; else if (Get_Argument(prhs[i]) == "print") print = true; else if (Get_Argument(prhs[i]) == "no_print_error") print_error = false; else { pos = 0; if (Get_Argument(prhs[i]).substr(0, 5) == "block") { size_t pos1 = Get_Argument(prhs[i]).find("=", pos + 5); if (pos1 != string::npos) pos = pos1 + 1; else pos += 5; block = atoi(Get_Argument(prhs[i]).substr(pos, string::npos).c_str())-1; } else if (Get_Argument(prhs[i]).substr(0, 13) == "extended_path") { *extended_path = true; if ((i+1) >= nrhs) *ep_struct = NULL; else { *ep_struct = mxDuplicateArray(prhs[i + 1]); i++; } } else if (Get_Argument(prhs[i]).substr(0, 6) == "pfplan") { size_t pos1 = Get_Argument(prhs[i]).find("=", pos + 6); if (pos1 != string::npos) pos = pos1 + 1; else pos += 6; *pfplan_struct_name = deblank(Get_Argument(prhs[i]).substr(pos, string::npos)); } else if (Get_Argument(prhs[i]).substr(0, 4) == "plan") { size_t pos1 = Get_Argument(prhs[i]).find("=", pos + 4); if (pos1 != string::npos) pos = pos1 + 1; else pos += 4; *plan_struct_name = deblank(Get_Argument(prhs[i]).substr(pos, string::npos)); } else { ostringstream tmp; tmp << " in main, unknown argument : " << Get_Argument(prhs[i]) << "\n"; throw FatalExceptionHandling(tmp.str()); } } } if (count_array_argument > 0 && count_array_argument < 5) { if (count_array_argument == 3 && steady_state) periods = 1; else { ostringstream tmp; tmp << " in main, missing arguments. All the following arguments have to be indicated y, x, params, it_, ys\n"; throw FatalExceptionHandling(tmp.str()); } } *M_ = mexGetVariable("global", "M_"); if (*M_ == NULL) { ostringstream tmp; tmp << " in main, global variable not found: M_\n"; throw FatalExceptionHandling(tmp.str()); } /* Gets variables and parameters from global workspace of Matlab */ *oo_ = mexGetVariable("global", "oo_"); if (*oo_ == NULL) { ostringstream tmp; tmp << " in main, global variable not found: oo_\n"; throw FatalExceptionHandling(tmp.str()); } *options_ = mexGetVariable("global", "options_"); if (*options_ == NULL) { ostringstream tmp; tmp << " in main, global variable not found: options_\n"; throw FatalExceptionHandling(tmp.str()); } } #ifdef DEBUG_EX int main(int nrhs, const char *prhs[]) #else /* The gateway routine */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) #endif { mxArray *M_, *oo_, *options_; mxArray *GlobalTemporaryTerms; #ifndef DEBUG_EX mxArray *block_structur = NULL; #else int nlhs = 0; char *plhs[1]; load_global((char *) prhs[1]); #endif mxArray *pfplan_struct = NULL; ErrorMsg error_msg; size_t i, row_y = 0, col_y = 0, row_x = 0, col_x = 0, nb_row_xd = 0; size_t steady_row_y, steady_col_y; int y_kmin = 0, y_kmax = 0, y_decal = 0; unsigned int periods = 1; double *direction; bool steady_state = false; bool evaluate = false; int block = -1; double *params = NULL; double *yd = NULL, *xd = NULL; int count_array_argument = 0; bool global_temporary_terms = false; bool print = false, print_error = true, print_it = false; double *steady_yd = NULL, *steady_xd = NULL; string plan, pfplan; bool extended_path; mxArray *extended_path_struct; table_conditional_local_type conditional_local; vector splan, spfplan, sextended_path, sconditional_extended_path; vector_table_conditional_local_type vector_conditional_local; table_conditional_global_type table_conditional_global; int max_periods = 0; #ifdef CUDA int CUDA_device = -1; cublasHandle_t cublas_handle; cusparseHandle_t cusparse_handle; cusparseMatDescr_t descr; #endif try { Get_Arguments_and_global_variables(nrhs, prhs, count_array_argument, &yd, row_y, col_y, &xd, row_x, col_x, ¶ms, &steady_yd, steady_row_y, steady_col_y, periods, #ifndef DEBUG_EX &block_structur, #endif steady_state, evaluate, block, &M_, &oo_, &options_, global_temporary_terms, print, print_error, &GlobalTemporaryTerms, &plan, &pfplan, &extended_path, &extended_path_struct); } catch (GeneralExceptionHandling &feh) { mexErrMsgTxt(feh.GetErrorMsg().c_str()); } if (!count_array_argument) { int field = mxGetFieldNumber(M_, "params"); if (field < 0) mexErrMsgTxt("params is not a field of M_"); params = mxGetPr(mxGetFieldByNumber(M_, 0, field)); } ErrorMsg emsg; vector dates; if (extended_path) { if (extended_path_struct == NULL) { string tmp = "The 'extended_path' option must be followed by the extended_path descriptor"; mexErrMsgTxt(tmp.c_str()); } mxArray *date_str = mxGetField(extended_path_struct, 0, "date_str"); if (date_str == NULL) { string tmp = "date_str"; tmp.insert(0, "The extended_path description structure does not contain the member: "); mexErrMsgTxt(tmp.c_str()); } int nb_periods = mxGetM(date_str) * mxGetN(date_str); mxArray *constrained_vars_ = mxGetField(extended_path_struct, 0, "constrained_vars_"); if (constrained_vars_ == NULL) { string tmp = "constrained_vars_"; tmp.insert(0, "The extended_path description structure does not contain the member: "); mexErrMsgTxt(tmp.c_str()); } mxArray *constrained_paths_ = mxGetField(extended_path_struct, 0, "constrained_paths_"); if (constrained_paths_ == NULL) { string tmp = "constrained_paths_"; tmp.insert(0, "The extended_path description structure does not contain the member: "); mexErrMsgTxt(tmp.c_str()); } mxArray *constrained_int_date_ = mxGetField(extended_path_struct, 0, "constrained_int_date_"); if (constrained_int_date_ == NULL) { string tmp = "constrained_int_date_"; tmp.insert(0, "The extended_path description structure does not contain the member: "); mexErrMsgTxt(tmp.c_str()); } mxArray *constrained_perfect_foresight_ = mxGetField(extended_path_struct, 0, "constrained_perfect_foresight_"); if (constrained_perfect_foresight_ == NULL) { string tmp = "constrained_perfect_foresight_"; tmp.insert(0, "The extended_path description structure does not contain the member: "); mexErrMsgTxt(tmp.c_str()); } mxArray *shock_var_ = mxGetField(extended_path_struct, 0, "shock_vars_"); if (shock_var_ == NULL) { string tmp = "shock_vars_"; tmp.insert(0, "The extended_path description structure does not contain the member: "); mexErrMsgTxt(tmp.c_str()); } mxArray *shock_paths_ = mxGetField(extended_path_struct, 0, "shock_paths_"); if (shock_paths_ == NULL) { string tmp = "shock_paths_"; tmp.insert(0, "The extended_path description structure does not contain the member: "); mexErrMsgTxt(tmp.c_str()); } mxArray *shock_int_date_ = mxGetField(extended_path_struct, 0, "shock_int_date_"); if (shock_int_date_ == NULL) { string tmp = "shock_int_date_"; tmp.insert(0, "The extended_path description structure does not contain the member: "); mexErrMsgTxt(tmp.c_str()); } mxArray *shock_str_date_ = mxGetField(extended_path_struct, 0, "shock_str_date_"); if (shock_str_date_ == NULL) { string tmp = "shock_str_date_"; tmp.insert(0, "The extended_path description structure does not contain the member: "); mexErrMsgTxt(tmp.c_str()); } int nb_constrained = mxGetM(constrained_vars_) * mxGetN(constrained_vars_); int nb_controlled = 0; mxArray *options_cond_fcst_ = mxGetField(extended_path_struct, 0, "options_cond_fcst_"); mxArray *controlled_varexo = NULL; if (options_cond_fcst_ != NULL) { controlled_varexo = mxGetField(options_cond_fcst_, 0, "controlled_varexo"); nb_controlled = mxGetM(controlled_varexo) * mxGetN(controlled_varexo); if (nb_controlled != nb_constrained) { mexErrMsgTxt("The number of exogenized variables and the number of exogenous controlled variables should be equal."); } } double *controlled_varexo_value = NULL; if (controlled_varexo != NULL) controlled_varexo_value = mxGetPr(controlled_varexo); double *constrained_var_value = mxGetPr(constrained_vars_); sconditional_extended_path.resize(nb_constrained); max_periods = 0; if (nb_constrained) { conditional_local.is_cond = false; conditional_local.var_exo = 0; conditional_local.var_endo = 0; conditional_local.constrained_value = 0; for (int i = 0; i < nb_periods; i++) { vector_conditional_local.clear(); for (unsigned int j = 0; j < row_y; j++) { conditional_local.var_endo = j; vector_conditional_local.push_back(conditional_local); } table_conditional_global[i] = vector_conditional_local; } } vector_table_conditional_local_type vv3 = table_conditional_global[0]; for (int i = 0; i < nb_constrained; i++) { sconditional_extended_path[i].exo_num = ceil(constrained_var_value[i]); sconditional_extended_path[i].var_num = ceil(controlled_varexo_value[i]); mxArray *Array_constrained_paths_ = mxGetCell(constrained_paths_, i); double *specific_constrained_paths_ = mxGetPr(Array_constrained_paths_); double *specific_constrained_int_date_ = mxGetPr(mxGetCell(constrained_int_date_, i)); int nb_local_periods = mxGetM(Array_constrained_paths_) * mxGetN(Array_constrained_paths_); int *constrained_int_date = static_cast(mxMalloc(nb_local_periods * sizeof(int))); error_msg.test_mxMalloc(constrained_int_date, __LINE__, __FILE__, __func__, nb_local_periods * sizeof(int)); if (nb_periods < nb_local_periods) { ostringstream oss; oss << nb_periods; string tmp = oss.str(); tmp.insert(0, "The total number of simulation periods ("); tmp.append(") is lesser than the number of periods in the shock definitions ("); oss << nb_local_periods; string tmp1 = oss.str(); tmp.append(tmp1); tmp.append(")"); mexErrMsgTxt(tmp.c_str()); } (sconditional_extended_path[i]).per_value.resize(nb_local_periods); (sconditional_extended_path[i]).value.resize(nb_periods); for (int j = 0; j < nb_periods; j++) sconditional_extended_path[i].value[j] = 0; for (int j = 0; j < nb_local_periods; j++) { constrained_int_date[j] = int (specific_constrained_int_date_[j]) - 1; conditional_local.is_cond = true; conditional_local.var_exo = sconditional_extended_path[i].var_num - 1; conditional_local.var_endo = sconditional_extended_path[i].exo_num - 1; conditional_local.constrained_value = specific_constrained_paths_[j]; table_conditional_global[constrained_int_date[j]][sconditional_extended_path[i].exo_num - 1] = conditional_local; sconditional_extended_path[i].per_value[j] = make_pair(constrained_int_date[j], specific_constrained_paths_[j]); sconditional_extended_path[i].value[constrained_int_date[j]] = specific_constrained_paths_[j]; if (max_periods < constrained_int_date[j] + 1) max_periods = constrained_int_date[j] + 1; } mxFree(constrained_int_date); } vector_table_conditional_local_type vv = table_conditional_global[0]; double *shock_var_value = mxGetPr(shock_var_); int nb_shocks = mxGetM(shock_var_) * mxGetN(shock_var_); sextended_path.resize(nb_shocks); for (int i = 0; i < nb_shocks; i++) { sextended_path[i].exo_num = ceil(shock_var_value[i]); mxArray *Array_shock_paths_ = mxGetCell(shock_paths_, i); double *specific_shock_paths_ = mxGetPr(Array_shock_paths_); double *specific_shock_int_date_ = mxGetPr(mxGetCell(shock_int_date_, i)); int nb_local_periods = mxGetM(Array_shock_paths_) * mxGetN(Array_shock_paths_); if (nb_periods < nb_local_periods) { ostringstream oss; oss << nb_periods; string tmp = oss.str(); tmp.insert(0, "The total number of simulation periods ("); tmp.append(") is lesser than the number of periods in the shock definitions ("); oss << nb_local_periods; string tmp1 = oss.str(); tmp.append(tmp1); tmp.append(")"); mexErrMsgTxt(tmp.c_str()); } (sextended_path[i]).per_value.resize(nb_local_periods); (sextended_path[i]).value.resize(nb_periods); for (int j = 0; j < nb_periods; j++) sextended_path[i].value[j] = 0; for (int j = 0; j < nb_local_periods; j++) { sextended_path[i].per_value[j] = make_pair(int (specific_shock_int_date_[j]), specific_shock_paths_[j]); sextended_path[i].value[int (specific_shock_int_date_[j]-1)] = specific_shock_paths_[j]; if (max_periods < int (specific_shock_int_date_[j])) max_periods = int (specific_shock_int_date_[j]); } } for (int i = 0; i < nb_periods; i++) { int buflen = mxGetNumberOfElements(mxGetCell(date_str, i)) + 1; char *buf = static_cast(mxCalloc(buflen, sizeof(char))); int info = mxGetString(mxGetCell(date_str, i), buf, buflen); if (info) { string tmp = "Can not allocated memory to store the date_str in the extended path descriptor"; mexErrMsgTxt(tmp.c_str()); } dates.push_back(string(buf)); //string(Dates[i]); mxFree(buf); } } if (plan.length() > 0) { mxArray *plan_struct = mexGetVariable("base", plan.c_str()); if (plan_struct == NULL) { string tmp = plan; tmp.insert(0, "Can't find the plan: "); mexErrMsgTxt(tmp.c_str()); } size_t n_plan = mxGetN(plan_struct); splan.resize(n_plan); for (int i = 0; i < static_cast(n_plan); i++) { splan[i].var = ""; splan[i].exo = ""; mxArray *tmp = mxGetField(plan_struct, i, "exo"); if (tmp) { char name[100]; mxGetString(tmp, name, 100); splan[i].var = name; SymbolType variable_type = SymbolType::endogenous; int exo_num = emsg.get_ID(name, &variable_type); if (variable_type == SymbolType::exogenous || variable_type == SymbolType::exogenousDet) splan[i].var_num = exo_num; else { string tmp = name; tmp.insert(0, "the variable '"); tmp.append("' defined as var in plan is not an exogenous or a deterministic exogenous\n"); mexErrMsgTxt(tmp.c_str()); } } tmp = mxGetField(plan_struct, i, "var"); if (tmp) { char name[100]; mxGetString(tmp, name, 100); splan[i].exo = name; SymbolType variable_type; int exo_num = emsg.get_ID(name, &variable_type); if (variable_type == SymbolType::endogenous) splan[i].exo_num = exo_num; else { string tmp = name; tmp.insert(0, "the variable '"); tmp.append("' defined as exo in plan is not an endogenous variable\n"); mexErrMsgTxt(tmp.c_str()); } } tmp = mxGetField(plan_struct, i, "per_value"); if (tmp) { size_t num_shocks = mxGetM(tmp); (splan[i]).per_value.resize(num_shocks); double *per_value = mxGetPr(tmp); for (int j = 0; j < static_cast(num_shocks); j++) (splan[i]).per_value[j] = make_pair(ceil(per_value[j]), per_value[j + num_shocks]); } } int i = 0; for (vector::iterator it = splan.begin(); it != splan.end(); it++) { mexPrintf("----------------------------------------------------------------------------------------------------\n"); mexPrintf("surprise #%d\n", i+1); if (it->exo.length()) mexPrintf(" plan fliping var=%s (%d) exo=%s (%d) for the following periods and with the following values:\n", it->var.c_str(), it->var_num, it->exo.c_str(), it->exo_num); else mexPrintf(" plan shocks on var=%s for the following periods and with the following values:\n", it->var.c_str()); for (vector>::iterator it1 = it->per_value.begin(); it1 != it->per_value.end(); it1++) { mexPrintf(" %3d %10.5f\n", it1->first, it1->second); } i++; } } if (pfplan.length() > 0) { pfplan_struct = mexGetVariable("base", pfplan.c_str()); if (!pfplan_struct) { string tmp = pfplan; tmp.insert(0, "Can't find the pfplan: "); mexErrMsgTxt(tmp.c_str()); } size_t n_plan = mxGetN(pfplan_struct); spfplan.resize(n_plan); for (int i = 0; i < static_cast(n_plan); i++) { spfplan[i].var = ""; spfplan[i].exo = ""; mxArray *tmp = mxGetField(pfplan_struct, i, "var"); if (tmp) { char name[100]; mxGetString(tmp, name, 100); spfplan[i].var = name; SymbolType variable_type = SymbolType::endogenous; int exo_num = emsg.get_ID(name, &variable_type); if (variable_type == SymbolType::exogenous || variable_type == SymbolType::exogenousDet) splan[i].var_num = exo_num; else { string tmp = name; tmp.insert(0, "the variable '"); tmp.append("' defined as var in pfplan is not an exogenous or a deterministic exogenous\n"); mexErrMsgTxt(tmp.c_str()); } } tmp = mxGetField(pfplan_struct, i, "exo"); if (tmp) { char name[100]; mxGetString(tmp, name, 100); spfplan[i].exo = name; SymbolType variable_type; int exo_num = emsg.get_ID(name, &variable_type); if (variable_type == SymbolType::endogenous) spfplan[i].exo_num = exo_num; else { string tmp = name; tmp.insert(0, "the variable '"); tmp.append("' defined as exo in pfplan is not an endogenous variable\n"); mexErrMsgTxt(tmp.c_str()); } } tmp = mxGetField(pfplan_struct, i, "per_value"); if (tmp) { size_t num_shocks = mxGetM(tmp); double *per_value = mxGetPr(tmp); (spfplan[i]).per_value.resize(num_shocks); for (int j = 0; j < static_cast(num_shocks); j++) spfplan[i].per_value[j] = make_pair(ceil(per_value[j]), per_value[j+ num_shocks]); } } int i = 0; for (vector::iterator it = spfplan.begin(); it != spfplan.end(); it++) { mexPrintf("----------------------------------------------------------------------------------------------------\n"); mexPrintf("perfect foresight #%d\n", i+1); if (it->exo.length()) mexPrintf(" plan flipping var=%s (%d) exo=%s (%d) for the following periods and with the following values:\n", it->var.c_str(), it->var_num, it->exo.c_str(), it->exo_num); else mexPrintf(" plan shocks on var=%s (%d) for the following periods and with the following values:\n", it->var.c_str(), it->var_num); for (vector>::iterator it1 = it->per_value.begin(); it1 != it->per_value.end(); it1++) { mexPrintf(" %3d %10.5f\n", it1->first, it1->second); } i++; } } int field_steady_state = mxGetFieldNumber(oo_, "steady_state"); if (field_steady_state < 0) mexErrMsgTxt("steady_state is not a field of oo_"); int field_exo_steady_state = mxGetFieldNumber(oo_, "exo_steady_state"); if (field_exo_steady_state < 0) mexErrMsgTxt("exo_steady_state is not a field of oo_"); if (!steady_state) { int field_endo_simul = mxGetFieldNumber(oo_, "endo_simul"); if (field_endo_simul < 0) mexErrMsgTxt("endo_simul is not a field of oo_"); int field_exo_simul = mxGetFieldNumber(oo_, "exo_simul"); if (field_exo_simul < 0) mexErrMsgTxt("exo_simul is not a field of oo_"); if (!count_array_argument) { mxArray *endo_sim_arr = mxGetFieldByNumber(oo_, 0, field_endo_simul); yd = mxGetPr(endo_sim_arr); row_y = mxGetM(endo_sim_arr); col_y = mxGetN(endo_sim_arr); mxArray *exo_sim_arr = mxGetFieldByNumber(oo_, 0, field_exo_simul); xd = mxGetPr(exo_sim_arr); row_x = mxGetM(exo_sim_arr); col_x = mxGetN(exo_sim_arr); nb_row_xd = row_x; } int field = mxGetFieldNumber(M_, "maximum_lag"); if (field >= 0) y_kmin = int (floor(*(mxGetPr(mxGetFieldByNumber(M_, 0, field))))); else mexErrMsgTxt("maximum_lag is not a field of M_"); field = mxGetFieldNumber(M_, "maximum_lead"); if (field >= 0) y_kmax = int (floor(*(mxGetPr(mxGetFieldByNumber(M_, 0, field))))); else mexErrMsgTxt("maximum_lead is not a field of M_"); field = mxGetFieldNumber(M_, "maximum_endo_lag"); if (field >= 0) y_decal = max(0, y_kmin-int (floor(*(mxGetPr(mxGetFieldByNumber(M_, 0, field)))))); else mexErrMsgTxt("maximum_endo_lag is not a field of M_"); if (!count_array_argument) { int field = mxGetFieldNumber(options_, "periods"); if (field >= 0) periods = int (floor(*(mxGetPr(mxGetFieldByNumber(options_, 0, field))))); else mexErrMsgTxt("options_ is not a field of options_"); } if (!steady_yd) { mxArray *steady_state_arr = mxGetFieldByNumber(oo_, 0, field_steady_state); steady_yd = mxGetPr(steady_state_arr); steady_row_y = mxGetM(steady_state_arr); steady_col_y = mxGetN(steady_state_arr); } steady_xd = mxGetPr(mxGetFieldByNumber(oo_, 0, field_exo_steady_state)); } else { if (!count_array_argument) { mxArray *steady_state_arr = mxGetFieldByNumber(oo_, 0, field_steady_state); yd = mxGetPr(steady_state_arr); row_y = mxGetM(steady_state_arr); col_y = mxGetN(steady_state_arr); mxArray *exo_steady_state_arr = mxGetFieldByNumber(oo_, 0, field_exo_steady_state); xd = mxGetPr(exo_steady_state_arr); row_x = mxGetM(exo_steady_state_arr); col_x = mxGetN(exo_steady_state_arr); nb_row_xd = row_x; } } int field = mxGetFieldNumber(options_, "verbosity"); int verbose = 0; if (field >= 0) verbose = int (*mxGetPr((mxGetFieldByNumber(options_, 0, field)))); else mexErrMsgTxt("verbosity is not a field of options_"); if (verbose) print_it = true; if (!steady_state) field = mxGetFieldNumber(options_, "simul"); else field = mxGetFieldNumber(options_, "steady"); mxArray *temporaryfield; if (field >= 0) temporaryfield = mxGetFieldByNumber(options_, 0, field); else { if (!steady_state) mexErrMsgTxt("simul is not a field of options_"); else mexErrMsgTxt("steady is not a field of options_"); } field = mxGetFieldNumber(temporaryfield, "maxit"); if (field < 0) { if (!steady_state) mexErrMsgTxt("maxit is not a field of options_.simul"); else mexErrMsgTxt("maxit is not a field of options_.steady"); } int maxit_ = int (floor(*(mxGetPr(mxGetFieldByNumber(temporaryfield, 0, field))))); field = mxGetFieldNumber(options_, "slowc"); if (field < 0) mexErrMsgTxt("slows is not a field of options_"); double slowc = double (*(mxGetPr(mxGetFieldByNumber(options_, 0, field)))); field = mxGetFieldNumber(options_, "markowitz"); if (field < 0) mexErrMsgTxt("markowitz is not a field of options_"); double markowitz_c = double (*(mxGetPr(mxGetFieldByNumber(options_, 0, field)))); field = mxGetFieldNumber(options_, "minimal_solving_periods"); if (field < 0) mexErrMsgTxt("minimal_solving_periods is not a field of options_"); int minimal_solving_periods = int (*(mxGetPr(mxGetFieldByNumber(options_, 0, field)))); field = mxGetFieldNumber(options_, "stack_solve_algo"); if (field < 0) mexErrMsgTxt("stack_solve_algo is not a field of options_"); int stack_solve_algo = int (*(mxGetPr(mxGetFieldByNumber(options_, 0, field)))); int solve_algo; double solve_tolf; if (steady_state) { int field = mxGetFieldNumber(options_, "solve_algo"); if (field >= 0) solve_algo = int (*(mxGetPr(mxGetFieldByNumber(options_, 0, field)))); else mexErrMsgTxt("solve_algo is not a field of options_"); field = mxGetFieldNumber(options_, "solve_tolf"); if (field >= 0) solve_tolf = *(mxGetPr(mxGetFieldByNumber(options_, 0, field))); else mexErrMsgTxt("solve_tolf is not a field of options_"); } else { solve_algo = stack_solve_algo; int field = mxGetFieldNumber(options_, "dynatol"); mxArray *dynatol; if (field >= 0) dynatol = mxGetFieldByNumber(options_, 0, field); else mexErrMsgTxt("dynatol is not a field of options_"); field = mxGetFieldNumber(dynatol, "f"); if (field >= 0) solve_tolf = *mxGetPr((mxGetFieldByNumber(dynatol, 0, field))); else mexErrMsgTxt("f is not a field of options_.dynatol"); } field = mxGetFieldNumber(M_, "fname"); mxArray *mxa; if (field >= 0) mxa = mxGetFieldByNumber(M_, 0, field); else mexErrMsgTxt("fname is not a field of M_"); size_t buflen = mxGetM(mxa) * mxGetN(mxa) + 1; char *fname; fname = static_cast(mxCalloc(buflen+1, sizeof(char))); size_t status = mxGetString(mxa, fname, int (buflen)); fname[buflen] = ' '; if (status != 0) mexWarnMsgTxt("Not enough space. Filename is truncated."); string file_name = fname; #ifdef CUDA try { if (stack_solve_algo == 7 && !steady_state) CUDA_device = GPU_Test_and_Info(&cublas_handle, &cusparse_handle, &descr); } catch (GeneralExceptionHandling &feh) { mexErrMsgTxt(feh.GetErrorMsg().c_str()); } #else if (stack_solve_algo == 7 && !steady_state) mexErrMsgTxt("bytecode has not been compiled with CUDA option. Bytecode Can't use options_.stack_solve_algo=7\n"); #endif size_t size_of_direction = col_y*row_y*sizeof(double); double *y = static_cast(mxMalloc(size_of_direction)); error_msg.test_mxMalloc(y, __LINE__, __FILE__, __func__, size_of_direction); double *ya = static_cast(mxMalloc(size_of_direction)); error_msg.test_mxMalloc(ya, __LINE__, __FILE__, __func__, size_of_direction); direction = static_cast(mxMalloc(size_of_direction)); error_msg.test_mxMalloc(direction, __LINE__, __FILE__, __func__, size_of_direction); memset(direction, 0, size_of_direction); /*mexPrintf("col_x : %d, row_x : %d\n",col_x, row_x);*/ double *x = static_cast(mxMalloc(col_x*row_x*sizeof(double))); error_msg.test_mxMalloc(x, __LINE__, __FILE__, __func__, col_x*row_x*sizeof(double)); for (i = 0; i < row_x*col_x; i++) { x[i] = double (xd[i]); } for (i = 0; i < row_y*col_y; i++) { y[i] = double (yd[i]); ya[i] = double (yd[i]); } size_t y_size = row_y; size_t nb_row_x = row_x; clock_t t0 = clock(); Interpreter interprete(params, y, ya, x, steady_yd, steady_xd, direction, y_size, nb_row_x, nb_row_xd, periods, y_kmin, y_kmax, maxit_, solve_tolf, size_of_direction, slowc, y_decal, markowitz_c, file_name, minimal_solving_periods, stack_solve_algo, solve_algo, global_temporary_terms, print, print_error, GlobalTemporaryTerms, steady_state, print_it, col_x, col_y #ifdef CUDA , CUDA_device, cublas_handle, cusparse_handle, descr #endif ); string f(fname); mxFree(fname); int nb_blocks = 0; double *pind; if (extended_path) { try { interprete.extended_path(f, f, evaluate, block, nb_blocks, max_periods, sextended_path, sconditional_extended_path, dates, table_conditional_global); } catch (GeneralExceptionHandling &feh) { mexErrMsgTxt(feh.GetErrorMsg().c_str()); } } else { try { interprete.compute_blocks(f, f, evaluate, block, nb_blocks); } catch (GeneralExceptionHandling &feh) { mexErrMsgTxt(feh.GetErrorMsg().c_str()); } } #ifdef CUDA if (stack_solve_algo == 7 && !steady_state) GPU_close(cublas_handle, cusparse_handle, descr); #endif clock_t t1 = clock(); if (!steady_state && !evaluate && print) mexPrintf("Simulation Time=%f milliseconds\n", 1000.0*(double (t1)-double (t0))/double (CLOCKS_PER_SEC)); #ifndef DEBUG_EX bool dont_store_a_structure = false; if (nlhs > 0) { if (block >= 0) { if (evaluate) { vector residual = interprete.get_residual(); plhs[0] = mxCreateDoubleMatrix(int (residual.size()/double (col_y)), int (col_y), mxREAL); pind = mxGetPr(plhs[0]); for (i = 0; i < residual.size(); i++) pind[i] = residual[i]; } else { int out_periods; if (extended_path) out_periods = max_periods + y_kmin; else out_periods = row_y; plhs[0] = mxCreateDoubleMatrix(out_periods, int (col_y), mxREAL); pind = mxGetPr(plhs[0]); for (i = 0; i < out_periods*col_y; i++) pind[i] = y[i]; } } else { int out_periods; if (extended_path) out_periods = max_periods + y_kmin; else out_periods = col_y; plhs[0] = mxCreateDoubleMatrix(int (row_y), out_periods, mxREAL); pind = mxGetPr(plhs[0]); if (evaluate) { vector residual = interprete.get_residual(); for (i = 0; i < residual.size(); i++) pind[i] = residual[i]; } else for (i = 0; i < row_y*out_periods; i++) pind[i] = y[i]; } if (nlhs > 1) { if (evaluate) { int jacob_field_number = 0, jacob_exo_field_number = 0, jacob_exo_det_field_number = 0, jacob_other_endo_field_number = 0; if (!block_structur) { const char *field_names[] = {"g1", "g1_x", "g1_xd", "g1_o"}; jacob_field_number = 0; jacob_exo_field_number = 1; jacob_exo_det_field_number = 2; jacob_other_endo_field_number = 3; mwSize dims[1] = {static_cast(nb_blocks) }; plhs[1] = mxCreateStructArray(1, dims, 4, field_names); } else if (!mxIsStruct(block_structur)) { plhs[1] = interprete.get_jacob(0); //mexCallMATLAB(0,NULL, 1, &plhs[1], "disp"); dont_store_a_structure = true; } else { plhs[1] = block_structur; jacob_field_number = mxAddField(plhs[1], "g1"); if (jacob_field_number == -1) mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field jacob to the structArray\n"); jacob_exo_field_number = mxAddField(plhs[1], "g1_x"); if (jacob_exo_field_number == -1) mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field jacob_exo to the structArray\n"); jacob_exo_det_field_number = mxAddField(plhs[1], "g1_xd"); if (jacob_exo_det_field_number == -1) mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field jacob_exo_det to the structArray\n"); jacob_other_endo_field_number = mxAddField(plhs[1], "g1_o"); if (jacob_other_endo_field_number == -1) mexErrMsgTxt("Fatal error in bytecode: in main, cannot add extra field jacob_other_endo to the structArray\n"); } if (!dont_store_a_structure) { for (int i = 0; i < nb_blocks; i++) { mxSetFieldByNumber(plhs[1], i, jacob_field_number, interprete.get_jacob(i)); if (!steady_state) { mxSetFieldByNumber(plhs[1], i, jacob_exo_field_number, interprete.get_jacob_exo(i)); mxSetFieldByNumber(plhs[1], i, jacob_exo_det_field_number, interprete.get_jacob_exo_det(i)); mxSetFieldByNumber(plhs[1], i, jacob_other_endo_field_number, interprete.get_jacob_other_endo(i)); } } } } else { plhs[1] = mxCreateDoubleMatrix(int (row_x), int (col_x), mxREAL); pind = mxGetPr(plhs[1]); for (i = 0; i < row_x*col_x; i++) { pind[i] = x[i]; } } if (nlhs > 2) { plhs[2] = mxCreateDoubleMatrix(int (row_y), int (col_y), mxREAL); pind = mxGetPr(plhs[2]); for (i = 0; i < row_y*col_y; i++) pind[i] = y[i]; if (nlhs > 3) { mxArray *GlobalTemporaryTerms = interprete.get_Temporary_Terms(); size_t nb_temp_terms = mxGetM(GlobalTemporaryTerms); plhs[3] = mxCreateDoubleMatrix(int (nb_temp_terms), 1, mxREAL); pind = mxGetPr(plhs[3]); double *tt = mxGetPr(GlobalTemporaryTerms); for (i = 0; i < nb_temp_terms; i++) pind[i] = tt[i]; } } } } #else Free_global(); #endif if (x) mxFree(x); if (y) mxFree(y); if (ya) mxFree(ya); if (direction) mxFree(direction); #ifdef _MSC_VER_ /*fFreeResult =*/ FreeLibrary(hinstLib); #endif return; }