diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc index 57317e479..48f665ee8 100644 --- a/preprocessor/DynamicModel.cc +++ b/preprocessor/DynamicModel.cc @@ -2089,8 +2089,7 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll) const ExprNodeOutputType output_type = (use_dll ? oCDynamicModel : oMatlabDynamicModel); deriv_node_temp_terms_t tef_terms; - writeModelLocalVariables(model_output, output_type, tef_terms); - + writeTemporaryTerms(temporary_terms, model_output, output_type, tef_terms); writeModelEquations(model_output, output_type); @@ -4419,3 +4418,356 @@ DynamicModel::dynamicOnlyEquationsNbr() const return eqs.size(); } +void +DynamicModel::writeFirstDerivativesCC(const string &basename, bool cuda) const +{ + string filename = basename + "_first_derivatives.cc"; + ofstream mDynamicModelFile, mDynamicMexFile; + + mDynamicModelFile.open(filename.c_str(), ios::out | ios::binary); + if (!mDynamicModelFile.is_open()) + { + cerr << "Error: Can't open file " << filename << " for writing" << endl; + exit(EXIT_FAILURE); + } + mDynamicModelFile << "/*" << endl + << " * " << filename << " : Computes first order derivatives of the model for Dynare" << endl + << " *" << endl + << " * Warning : this file is generated automatically by Dynare" << endl + << " * from model " << basename << "(.mod)" << endl + << " */" << endl + << "#include " << endl; + + mDynamicModelFile << "#include " << endl; + + mDynamicModelFile << "#define max(a, b) (((a) > (b)) ? (a) : (b))" << endl + << "#define min(a, b) (((a) > (b)) ? (b) : (a))" << endl; + + // Write function definition if oPowerDeriv is used + writePowerDerivCHeader(mDynamicModelFile); + + mDynamicModelFile << "void FirstDerivatives(const double *y, double *x, int nb_row_x, double *params, double *steady_state, int it_, double *residual, double *g1, double *v2, double *v3)" << endl + << "{" << endl; + + // this is always empty here, but needed by d1->writeOutput + deriv_node_temp_terms_t tef_terms; + + // Writing Jacobian + for (first_derivatives_t::const_iterator it = first_derivatives.begin(); + it != first_derivatives.end(); it++) + { + int eq = it->first.first; + int var = it->first.second; + expr_t d1 = it->second; + + jacobianHelper(mDynamicModelFile, eq, getDynJacobianCol(var), oCDynamicModel); + mDynamicModelFile << "="; + // oCstaticModel makes reference to the static variables + d1->writeOutput(mDynamicModelFile, oCStaticModel, temporary_terms, tef_terms); + mDynamicModelFile << ";" << endl; + } + + mDynamicModelFile << "}" << endl; + + writePowerDeriv(mDynamicModelFile, true); + mDynamicModelFile.close(); + +} + +// using compressed sparse row format (CSR) +void +DynamicModel::writeSecondDerivativesCC_csr(const string &basename, bool cuda) const +{ + + string filename = basename + "_second_derivatives.cc"; + ofstream mDynamicModelFile, mDynamicMexFile; + + mDynamicModelFile.open(filename.c_str(), ios::out | ios::binary); + if (!mDynamicModelFile.is_open()) + { + cerr << "Error: Can't open file " << filename << " for writing" << endl; + exit(EXIT_FAILURE); + } + mDynamicModelFile << "/*" << endl + << " * " << filename << " : Computes second order derivatives of the model for Dynare" << endl + << " *" << endl + << " * Warning : this file is generated automatically by Dynare" << endl + << " * from model " << basename << "(.mod)" << endl + << " */" << endl + << "#include " << endl; + + mDynamicModelFile << "#include " << endl; + + mDynamicModelFile << "#define max(a, b) (((a) > (b)) ? (a) : (b))" << endl + << "#define min(a, b) (((a) > (b)) ? (b) : (a))" << endl; + + // write function definition if oPowerDeriv is used + writePowerDerivCHeader(mDynamicModelFile); + + mDynamicModelFile << "void SecondDerivatives(const double *y, double *x, int nb_row_x, double *params, double *steady_state, int it_, double *residual, int *row_ptr, int *col_ptr, double *value)" << endl + << "{" << endl; + + // this is always empty here, but needed by d1->writeOutput + deriv_node_temp_terms_t tef_terms; + + // Indexing derivatives in column order + vector d_order(NNZDerivatives[1]); + OrderByLinearAddress obla(NNZDerivatives[1]); + int counter = 0; + int dynHessianColsNbr = dynJacobianColsNbr*dynJacobianColsNbr; + for (second_derivatives_t::const_iterator it = second_derivatives.begin(); + it != second_derivatives.end(); it++) + { + int eq = it->first.first; + int var1 = it->first.second.first; + int var2 = it->first.second.second; + + int id1 = getDynJacobianCol(var1); + int id2 = getDynJacobianCol(var2); + + int col_nb = id1 * dynJacobianColsNbr + id2; + int col_nb_sym = id2 * dynJacobianColsNbr + id1; + + obla.linear_address[counter] = col_nb + eq*dynHessianColsNbr; + d_order[counter] = counter; + ++counter; + if (id1 != id2) + { + obla.linear_address[counter] = col_nb_sym + eq*dynHessianColsNbr; + d_order[counter] = counter; + ++counter; + } + } + sort(d_order.begin(), d_order.end(), obla); + + // Writing Hessian + vector row_ptr(equations.size()); + fill(row_ptr.begin(),row_ptr.end(),0.0); + int k = 0; // Keep the order of a 2nd derivative + for (second_derivatives_t::const_iterator it = second_derivatives.begin(); + it != second_derivatives.end(); it++) + { + int eq = it->first.first; + int var1 = it->first.second.first; + int var2 = it->first.second.second; + expr_t d2 = it->second; + + int id1 = getDynJacobianCol(var1); + int id2 = getDynJacobianCol(var2); + + int col_nb = id1 * dynJacobianColsNbr + id2; + int col_nb_sym = id2 * dynJacobianColsNbr + id1; + + row_ptr[eq]++; + mDynamicModelFile << "col_ptr[" << d_order[k] << "] " + << "=" << col_nb << ";" << endl; + mDynamicModelFile << "value[" << d_order[k] << "] = "; + // oCstaticModel makes reference to the static variables + d2->writeOutput(mDynamicModelFile, oCStaticModel, temporary_terms, tef_terms); + mDynamicModelFile << ";" << endl; + + k++; + + // Treating symetric elements + if (id1 != id2) + { + row_ptr[eq]++; + mDynamicModelFile << "col_ptr[" << d_order[k] << "] " + << "=" << col_nb_sym << ";" << endl; + mDynamicModelFile << "value[" << d_order[k] << "] = "; + // oCstaticModel makes reference to the static variables + d2->writeOutput(mDynamicModelFile, oCStaticModel, temporary_terms, tef_terms); + mDynamicModelFile << ";" << endl; + + k++; + } + } + + // row_ptr must point to the relative address of the first element of the row + int cumsum = 0; + mDynamicModelFile << "row_ptr = [ 0"; + for (vector::iterator it=row_ptr.begin(); it != row_ptr.end(); ++it) + { + cumsum += *it; + mDynamicModelFile << ", " << cumsum; + } + mDynamicModelFile << "];" << endl; + + mDynamicModelFile << "}" << endl; + + writePowerDeriv(mDynamicModelFile, true); + mDynamicModelFile.close(); + +} + +void +DynamicModel::writeThirdDerivativesCC_csr(const string &basename, bool cuda) const +{ + string filename = basename + "_third_derivatives.cc"; + ofstream mDynamicModelFile, mDynamicMexFile; + + mDynamicModelFile.open(filename.c_str(), ios::out | ios::binary); + if (!mDynamicModelFile.is_open()) + { + cerr << "Error: Can't open file " << filename << " for writing" << endl; + exit(EXIT_FAILURE); + } + mDynamicModelFile << "/*" << endl + << " * " << filename << " : Computes third order derivatives of the model for Dynare" << endl + << " *" << endl + << " * Warning : this file is generated automatically by Dynare" << endl + << " * from model " << basename << "(.mod)" << endl + << " */" << endl + << "#include " << endl; + + mDynamicModelFile << "#include " << endl; + + mDynamicModelFile << "#define max(a, b) (((a) > (b)) ? (a) : (b))" << endl + << "#define min(a, b) (((a) > (b)) ? (b) : (a))" << endl; + + // Write function definition if oPowerDeriv is used + writePowerDerivCHeader(mDynamicModelFile); + + mDynamicModelFile << "void ThirdDerivatives(const double *y, double *x, int nb_row_x, double *params, double *steady_state, int it_, double *residual, double *g1, double *v2, double *v3)" << endl + << "{" << endl; + + // this is always empty here, but needed by d1->writeOutput + deriv_node_temp_terms_t tef_terms; + + // Indexing derivatives in column order + vector d_order(NNZDerivatives[1]); + OrderByLinearAddress obla(NNZDerivatives[1]); + int counter = 0; + int dynHessianColsNbr = dynJacobianColsNbr*dynJacobianColsNbr; + for (third_derivatives_t::const_iterator it = third_derivatives.begin(); + it != third_derivatives.end(); it++) + { + int eq = it->first.first; + int var1 = it->first.second.first; + int var2 = it->first.second.second.first; + int var3 = it->first.second.second.second; + expr_t d3 = it->second; + + int id1 = getDynJacobianCol(var1); + int id2 = getDynJacobianCol(var2); + int id3 = getDynJacobianCol(var3); + + // Reference column number for the g3 matrix + int ref_col = id1 * hessianColsNbr + id2 * dynJacobianColsNbr + id3; + + sparseHelper(3, mDynamicModelFile, k, 0, oCDynamicModel); + mDynamicModelFile << "=" << eq + 1 << ";" << endl; + + sparseHelper(3, mDynamicModelFile, k, 1, oCDynamicModel); + mDynamicModelFile << "=" << ref_col + 1 << ";" << endl; + + sparseHelper(3, mDynamicModelFile, k, 2, oCDynamicModel); + mDynamicModelFile << "="; + // oCstaticModel makes reference to the static variables + d3->writeOutput(mDynamicModelFile, oCStaticModel, temporary_terms, tef_terms); + mDynamicModelFile << ";" << endl; + + // Compute the column numbers for the 5 other permutations of (id1,id2,id3) and store them in a set (to avoid duplicates if two indexes are equal) + set cols; + cols.insert(id1 * hessianColsNbr + id3 * dynJacobianColsNbr + id2); + cols.insert(id2 * hessianColsNbr + id1 * dynJacobianColsNbr + id3); + cols.insert(id2 * hessianColsNbr + id3 * dynJacobianColsNbr + id1); + cols.insert(id3 * hessianColsNbr + id1 * dynJacobianColsNbr + id2); + cols.insert(id3 * hessianColsNbr + id2 * dynJacobianColsNbr + id1); + + int k2 = 1; // Keeps the offset of the permutation relative to k + for (set::iterator it2 = cols.begin(); it2 != cols.end(); it2++) + if (*it2 != ref_col) + { + sparseHelper(3, mDynamicModelFile, k+k2, 0, oCDynamicModel); + mDynamicModelFile << "=" << eq + 1 << ";" << endl; + + sparseHelper(3, mDynamicModelFile, k+k2, 1, oCDynamicModel); + mDynamicModelFile << "=" << *it2 + 1 << ";" << endl; + + sparseHelper(3, mDynamicModelFile, k+k2, 2, oCDynamicModel); + mDynamicModelFile << "="; + sparseHelper(3, mDynamicModelFile, k, 2, oCDynamicModel); + mDynamicModelFile << ";" << endl; + + k2++; + } + k += k2; + } + + // Writing third derivatives + int hessianColsNbr = dynJacobianColsNbr * dynJacobianColsNbr; + int k = 0; // Keep the line of a 3rd derivative in v3 + for (third_derivatives_t::const_iterator it = third_derivatives.begin(); + it != third_derivatives.end(); it++) + { + int eq = it->first.first; + int var1 = it->first.second.first; + int var2 = it->first.second.second.first; + int var3 = it->first.second.second.second; + expr_t d3 = it->second; + + int id1 = getDynJacobianCol(var1); + int id2 = getDynJacobianCol(var2); + int id3 = getDynJacobianCol(var3); + + // Reference column number for the g3 matrix + int ref_col = id1 * hessianColsNbr + id2 * dynJacobianColsNbr + id3; + + sparseHelper(3, mDynamicModelFile, k, 0, oCDynamicModel); + mDynamicModelFile << "=" << eq + 1 << ";" << endl; + + sparseHelper(3, mDynamicModelFile, k, 1, oCDynamicModel); + mDynamicModelFile << "=" << ref_col + 1 << ";" << endl; + + sparseHelper(3, mDynamicModelFile, k, 2, oCDynamicModel); + mDynamicModelFile << "="; + // oCstaticModel makes reference to the static variables + d3->writeOutput(mDynamicModelFile, oCStaticModel, temporary_terms, tef_terms); + mDynamicModelFile << ";" << endl; + + // Compute the column numbers for the 5 other permutations of (id1,id2,id3) and store them in a set (to avoid duplicates if two indexes are equal) + set cols; + cols.insert(id1 * hessianColsNbr + id3 * dynJacobianColsNbr + id2); + cols.insert(id2 * hessianColsNbr + id1 * dynJacobianColsNbr + id3); + cols.insert(id2 * hessianColsNbr + id3 * dynJacobianColsNbr + id1); + cols.insert(id3 * hessianColsNbr + id1 * dynJacobianColsNbr + id2); + cols.insert(id3 * hessianColsNbr + id2 * dynJacobianColsNbr + id1); + + int k2 = 1; // Keeps the offset of the permutation relative to k + for (set::iterator it2 = cols.begin(); it2 != cols.end(); it2++) + if (*it2 != ref_col) + { + sparseHelper(3, mDynamicModelFile, k+k2, 0, oCDynamicModel); + mDynamicModelFile << "=" << eq + 1 << ";" << endl; + + sparseHelper(3, mDynamicModelFile, k+k2, 1, oCDynamicModel); + mDynamicModelFile << "=" << *it2 + 1 << ";" << endl; + + sparseHelper(3, mDynamicModelFile, k+k2, 2, oCDynamicModel); + mDynamicModelFile << "="; + sparseHelper(3, mDynamicModelFile, k, 2, oCDynamicModel); + mDynamicModelFile << ";" << endl; + + k2++; + } + k += k2; + } + + mDynamicModelFile << "}" << endl; + + writePowerDeriv(mDynamicModelFile, true); + mDynamicModelFile.close(); + +} + +OrderByLinearAddress::OrderByLinearAddress(int size) +{ + linear_address.resize(size); +} + +bool OrderByLinearAddress::operator()(const int i1, const int i2) const +{ + return linear_address[i1] < linear_address[i2]; +} + diff --git a/preprocessor/DynamicModel.hh b/preprocessor/DynamicModel.hh index e23816a08..720e23ea7 100644 --- a/preprocessor/DynamicModel.hh +++ b/preprocessor/DynamicModel.hh @@ -223,6 +223,12 @@ public: void writeDynamicFile(const string &basename, bool block, bool bytecode, bool use_dll, int order) const; //! Writes file containing parameters derivatives void writeParamsDerivativesFile(const string &basename) const; + //! Writes CC file containing first order derivatives of model evaluated at steady state + void writeFirstDerivativesCC(const string &basename, bool cuda) const; + //! Writes CC file containing second order derivatives of model evaluated at steady state (compressed sparse column) + void writeSecondDerivativesCC_csr(const string &basename, bool cuda) const; + //! Writes CC file containing third order derivatives of model evaluated at steady state (compressed sparse column) + void writeThirdDerivativesCC_csr(const string &basename, bool cuda) const; //! Converts to static model (only the equations) /*! It assumes that the static model given in argument has just been allocated */ void toStatic(StaticModel &static_model) const; @@ -467,4 +473,14 @@ public: bool isModelLocalVariableUsed() const; }; +//! Class to re-order derivatives for various sparse storage formats +class OrderByLinearAddress +{ +public: + //! vector of linear addresses in derivatives matrices + vector linear_address; + OrderByLinearAddress(int size); + //! Order by linear address in a matrix + bool operator()(const int i1, const int i2) const; +}; #endif diff --git a/preprocessor/DynareMain.cc b/preprocessor/DynareMain.cc index 383ffa086..633f5f97b 100644 --- a/preprocessor/DynareMain.cc +++ b/preprocessor/DynareMain.cc @@ -199,13 +199,15 @@ main(int argc, char **argv) cerr << "Incorrect syntax for ouput option" << endl; usage(); } + // we don't want temp terms in CC functions + no_tmp_terms = true; if (strlen(argv[arg]) == 14 && !strncmp(argv[arg] + 7, "dynamic", 7)) output_mode = dynamic; - else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "first", 5)) + else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "first", 5)) output_mode = first; - else if (strlen(argv[arg]) == 13 && !strncmp(argv[arg] + 7, "second", 6)) + else if (strlen(argv[arg]) == 13 && !strncmp(argv[arg] + 7, "second", 6)) output_mode = second; - else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "third", 5)) + else if (strlen(argv[arg]) == 12 && !strncmp(argv[arg] + 7, "third", 5)) output_mode = third; else { diff --git a/preprocessor/DynareMain2.cc b/preprocessor/DynareMain2.cc index cb9beac57..44416b32c 100644 --- a/preprocessor/DynareMain2.cc +++ b/preprocessor/DynareMain2.cc @@ -54,7 +54,7 @@ main2(stringstream &in, string &basename, bool debug, bool clear_all, bool no_tm mod_file->evalAllExpressions(warn_uninit); // Do computations - mod_file->computingPass(no_tmp_terms); + mod_file->computingPass(no_tmp_terms, output_mode); // Write outputs if (output_mode != none) diff --git a/preprocessor/ExprNode.cc b/preprocessor/ExprNode.cc index 2fff674b7..6639416fe 100644 --- a/preprocessor/ExprNode.cc +++ b/preprocessor/ExprNode.cc @@ -673,6 +673,9 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, case oSteadyStateFile: output << "ys_(" << tsid + 1 << ")"; break; + case oCSteadyStateFile: + output << "ys_[" << tsid << "]"; + break; default: cerr << "VariableNode::writeOutput: should not reach this point" << endl; exit(EXIT_FAILURE); @@ -715,6 +718,9 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, case oSteadyStateFile: output << "exo_(" << i << ")"; break; + case oCSteadyStateFile: + output << "exo_[" << i - 1 << "]"; + break; default: cerr << "VariableNode::writeOutput: should not reach this point" << endl; exit(EXIT_FAILURE); @@ -757,6 +763,9 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, case oSteadyStateFile: output << "exo_(" << i << ")"; break; + case oCSteadyStateFile: + output << "exo_[" << i - 1 << "]"; + break; default: cerr << "VariableNode::writeOutput: should not reach this point" << endl; exit(EXIT_FAILURE); @@ -4376,7 +4385,7 @@ ExternalFunctionNode::writeOutput(ostream &output, ExprNodeOutputType output_typ const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms) const { - if (output_type == oMatlabOutsideModel || output_type == oSteadyStateFile) + if (output_type == oMatlabOutsideModel || output_type == oSteadyStateFile || output_type == oCSteadyStateFile) { output << datatree.symbol_table.getName(symb_id) << "("; writeExternalFunctionArguments(output, output_type, temporary_terms, tef_terms); diff --git a/preprocessor/ExprNode.hh b/preprocessor/ExprNode.hh index aebdead2b..fd53a62d1 100644 --- a/preprocessor/ExprNode.hh +++ b/preprocessor/ExprNode.hh @@ -73,7 +73,8 @@ enum ExprNodeOutputType oMatlabDynamicSteadyStateOperator, //!< Matlab code, dynamic model, inside a steady state operator oMatlabDynamicSparseSteadyStateOperator, //!< Matlab code, dynamic block decomposed model, inside a steady state operator oCDynamicSteadyStateOperator, //!< C code, dynamic model, inside a steady state operator - oSteadyStateFile //!< Matlab code, in the generated steady state file + oSteadyStateFile, //!< Matlab code, in the generated steady state file + oCSteadyStateFile //!< C code, in the generated steady state file }; #define IS_MATLAB(output_type) ((output_type) == oMatlabStaticModel \ diff --git a/preprocessor/ExternalFiles.hh b/preprocessor/ExternalFiles.hh index ee0f6cf96..7e34ab9d0 100644 --- a/preprocessor/ExternalFiles.hh +++ b/preprocessor/ExternalFiles.hh @@ -30,7 +30,9 @@ using namespace std; class ExternalFiles { public: + void eraseFiles(const string &basename); void writeHeaders(const string &basename, bool cuda); + void writeModelCC(const string &basename, bool cuda); }; diff --git a/preprocessor/ModFile.cc b/preprocessor/ModFile.cc index 954e02b6c..5725a6dcd 100644 --- a/preprocessor/ModFile.cc +++ b/preprocessor/ModFile.cc @@ -447,7 +447,7 @@ ModFile::transformPass(bool nostrict) } void -ModFile::computingPass(bool no_tmp_terms) +ModFile::computingPass(bool no_tmp_terms, OutputType output) { // Mod file may have no equation (for example in a standalone BVAR estimation) if (dynamic_model.equation_number() > 0) @@ -493,8 +493,14 @@ ModFile::computingPass(bool no_tmp_terms) cerr << "ERROR: Incorrect order option..." << endl; exit(EXIT_FAILURE); } - bool hessian = mod_file_struct.order_option >= 2 || mod_file_struct.identification_present || mod_file_struct.estimation_analytic_derivation; - bool thirdDerivatives = mod_file_struct.order_option == 3 || mod_file_struct.estimation_analytic_derivation; + bool hessian = mod_file_struct.order_option >= 2 + || mod_file_struct.identification_present + || mod_file_struct.estimation_analytic_derivation + || output == second + || output == third; + bool thirdDerivatives = mod_file_struct.order_option == 3 + || mod_file_struct.estimation_analytic_derivation + || output == third; bool paramsDerivatives = mod_file_struct.identification_present || mod_file_struct.estimation_analytic_derivation; dynamic_model.computingPass(true, hessian, thirdDerivatives, paramsDerivatives, global_eval_context, no_tmp_terms, block, use_dll, byte_code); } @@ -799,29 +805,9 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all, bool no_log, b } void -ModFile::writeCOutputFiles(const string &basename) const +ModFile::writeModelCC(const string &basename, bool cuda) const { - // Erase possible remnants of previous runs - string dynfile = basename + "_dynamic.m"; - unlink(dynfile.c_str()); - - dynfile = basename + "_dynamic.c"; - unlink(dynfile.c_str()); - - dynfile = basename + "_dynamic_mex.c"; - unlink(dynfile.c_str()); - - string statfile = basename + "_static.m"; - unlink(statfile.c_str()); - - statfile = basename + "_static.c"; - unlink(statfile.c_str()); - - statfile = basename + "_static_mex.c"; - unlink(statfile.c_str()); - - string filename = "preprocessorOutput.cc"; - unlink(filename.c_str()); + string filename = basename + ".cc"; ofstream mDriverCFile; mDriverCFile.open(filename.c_str(), ios::out | ios::binary); @@ -847,8 +833,6 @@ ModFile::writeCOutputFiles(const string &basename) const // Write basic info symbol_table.writeCOutput(mDriverCFile); - dynamic_model.writeCOutput(mDriverCFile, basename, false, false, true, mod_file_struct.order_option, mod_file_struct.estimation_present); - mDriverCFile << "/*" << endl << " * Writing statements" << endl << " */" << endl @@ -875,11 +859,6 @@ ModFile::writeCOutputFiles(const string &basename) const mDriverCFile << "}" << endl; mDriverCFile.close(); - dynamic_model.writeDynamicFile(basename, false, false, true, mod_file_struct.order_option); - if (!no_static) - static_model.writeStaticFile(basename, false, false, true); - - // Write informational m file ofstream mOutputFile; @@ -914,22 +893,28 @@ ModFile::writeCOutputFiles(const string &basename) const void ModFile::writeExternalFiles(const string &basename, OutputType output, bool cuda) const { - ExternalFiles::writeHeaders(basename, cuda); - ExternalFiles::writeModelCC(cuda); + writeModelCC(basename, cuda); steady_state_model.writeSteadyStateFileCC(basename, mod_file_struct.ramsey_policy_present, cuda); - static_model.writeStaticFile(basename, block, byte_code, use_dll); - static_model.writeParamsDerivativesFile(basename); - static_model.writeAuxVarInitvalCC(mOutputFile, oMatlabOutsideModel); - dynamic_model.writeResiduals(basename, cuda); - dynamic_model.writeParamsDerivativesFile(basename, cuda); - dynamic_model.writeFirstDerivatives(basename, cuda); + dynamic_model.writeDynamicFile(basename, block, byte_code, use_dll, mod_file_struct.order_option); + + if (!no_static) + static_model.writeStaticFile(basename, false, false, true); + + + // static_model.writeStaticCFile(basename, block, byte_code, use_dll); + // static_model.writeParamsDerivativesFileCC(basename, cuda); + // static_model.writeAuxVarInitvalCC(mOutputFile, oMatlabOutsideModel, cuda); + + // dynamic_model.writeResidualsCC(basename, cuda); + // dynamic_model.writeParamsDerivativesFileCC(basename, cuda); + dynamic_model.writeFirstDerivativesCC(basename, cuda); if (output == second) - dynamic_model.writeSecondDerivatives(basename, cuda); + dynamic_model.writeSecondDerivativesCC_csr(basename, cuda); else if (output == third) { - dynamic_model.writeSecondDerivatives(basename, cuda); - dynamic_model.writeThirdDerivatives(basename, cuda); + dynamic_model.writeSecondDerivativesCC_csr(basename, cuda); + dynamic_model.writeThirdDerivativesCC_csr(basename, cuda); } } diff --git a/preprocessor/ModFile.hh b/preprocessor/ModFile.hh index 5e4f01de4..9301283cd 100644 --- a/preprocessor/ModFile.hh +++ b/preprocessor/ModFile.hh @@ -123,7 +123,7 @@ public: void transformPass(bool nostrict); //! Execute computations /*! \param no_tmp_terms if true, no temporary terms will be computed in the static and dynamic files */ - void computingPass(bool no_tmp_terms); + void computingPass(bool no_tmp_terms, OutputType output); //! Writes Matlab/Octave output files /*! \param basename The base name used for writing output files. Should be the name of the mod file without its extension @@ -141,6 +141,7 @@ public: ) const; //! Writes C output files only => No further Matlab processing void writeCOutputFiles(const string &basename) const; + void writeModelCC(const string &basename, bool cuda) const; void writeExternalFiles(const string &basename, OutputType output, bool cuda) const; }; diff --git a/preprocessor/ModelTree.hh b/preprocessor/ModelTree.hh index ffdb02acd..4d161daf8 100644 --- a/preprocessor/ModelTree.hh +++ b/preprocessor/ModelTree.hh @@ -161,7 +161,6 @@ protected: void computeThirdDerivatives(const set &vars); //! Computes derivatives of the Jacobian and Hessian w.r. to parameters void computeParamsDerivatives(); - //! Write derivative of an equation w.r. to a variable void writeDerivative(ostream &output, int eq, int symb_id, int lag, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const; //! Computes temporary terms (for all equations and derivatives) diff --git a/preprocessor/SteadyStateModel.cc b/preprocessor/SteadyStateModel.cc index a8770c785..d84b4f770 100644 --- a/preprocessor/SteadyStateModel.cc +++ b/preprocessor/SteadyStateModel.cc @@ -145,3 +145,58 @@ SteadyStateModel::writeSteadyStateFile(const string &basename, bool ramsey_polic << "end" << endl; } +void +SteadyStateModel::writeSteadyStateFileCC(const string &basename, bool ramsey_policy, bool cuda) const +{ + string filename = basename + "_steadystate.cc"; + + ofstream output; + output.open(filename.c_str(), ios::out | ios::binary); + if (!output.is_open()) + { + cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + exit(EXIT_FAILURE); + } + + if (cuda) + output << "__global__ "; + + output << "void steadystate(" + << "const double *exo_, const double *params_, double *ys_, int *info)" << endl + << "// Steady state file generated by Dynare preprocessor" << endl + << "{" << endl + << " info = 0;" << endl; + + if (recursive_order.size() == 0) + { + output << " return;" << endl + << "}" << endl; + return; + } + + for (size_t i = 0; i < recursive_order.size(); i++) + { + const vector &symb_ids = recursive_order[i]; + output << " "; + if (symb_ids.size() > 1) + output << "["; + for (size_t j = 0; j < symb_ids.size(); j++) + { + variable_node_map_t::const_iterator it = variable_node_map.find(make_pair(symb_ids[j], 0)); + assert(it != variable_node_map.end()); + dynamic_cast(it->second)->writeOutput(output, oSteadyStateFile); + if (j < symb_ids.size()-1) + output << ","; + } + if (symb_ids.size() > 1) + output << "]"; + + output << "="; + def_table.find(symb_ids)->second->writeOutput(output, oSteadyStateFile); + output << ";" << endl; + } + output << " // Auxiliary equations" << endl; + static_model.writeAuxVarInitval(output, oSteadyStateFile); + output << "}" << endl; +} + diff --git a/preprocessor/SteadyStateModel.hh b/preprocessor/SteadyStateModel.hh index cbb206afa..d2184ffcf 100644 --- a/preprocessor/SteadyStateModel.hh +++ b/preprocessor/SteadyStateModel.hh @@ -49,6 +49,7 @@ public: \param[in] ramsey_policy Is there a ramsey_policy statement in the MOD file? If yes, then use the "ys" in argument of the steady state file as initial values */ void writeSteadyStateFile(const string &basename, bool ramsey_policy) const; + void writeSteadyStateFileCC(const string &basename, bool ramsey_policy, bool cuda) const; }; #endif