diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index 7efae9c9f3c6decfca1cd5e91a46cfbabda33761..8232d22a5a69253f51c05ab77a19a2cf00c50f02 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -665,87 +665,11 @@ DynamicModel::writeDynamicPerBlockHelper(int blk, ostream &output, temporary_ter int nze_exo_det, int nze_other_endo) const { BlockSimulationType simulation_type { blocks[blk].simulation_type }; - int block_size { blocks[blk].size }; int block_mfs_size { blocks[blk].mfs_size }; int block_recursive_size { blocks[blk].getRecursiveSize() }; - deriv_node_temp_terms_t tef_terms; - - auto write_eq_tt = [&](int eq) - { - for (auto it : blocks_temporary_terms[blk][eq]) - { - if (dynamic_cast<AbstractExternalFunctionNode *>(it)) - it->writeExternalFunctionOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs, tef_terms); - - output << " "; - it->writeOutput(output, output_type, blocks_temporary_terms[blk][eq], blocks_temporary_terms_idxs, tef_terms); - output << '='; - it->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs, tef_terms); - temporary_terms.insert(it); - output << ';' << endl; - } - }; - - // The equations - for (int eq {0}; eq < block_size; eq++) - { - write_eq_tt(eq); - - EquationType equ_type { getBlockEquationType(blk, eq) }; - BinaryOpNode *e { getBlockEquationExpr(blk, eq) }; - expr_t lhs { e->arg1 }, rhs { e->arg2 }; - switch (simulation_type) - { - case BlockSimulationType::evaluateBackward: - case BlockSimulationType::evaluateForward: - evaluation: - if (equ_type == EquationType::evaluateRenormalized) - { - e = getBlockEquationRenormalizedExpr(blk, eq); - lhs = e->arg1; - rhs = e->arg2; - } - else if (equ_type != EquationType::evaluate) - { - cerr << "Type mismatch for equation " << getBlockEquationID(blk, eq)+1 << endl; - exit(EXIT_FAILURE); - } - output << " "; - lhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); - output << '='; - rhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); - output << ';' << endl; - break; - case BlockSimulationType::solveBackwardSimple: - case BlockSimulationType::solveForwardSimple: - case BlockSimulationType::solveBackwardComplete: - case BlockSimulationType::solveForwardComplete: - case BlockSimulationType::solveTwoBoundariesComplete: - case BlockSimulationType::solveTwoBoundariesSimple: - if (eq < block_recursive_size) - goto evaluation; - output << " residual" << LEFT_ARRAY_SUBSCRIPT(output_type) - << eq-block_recursive_size+ARRAY_SUBSCRIPT_OFFSET(output_type) - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=("; - goto end; - default: - end: - lhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); - output << ")-("; - rhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); - output << ");" << endl; - } - } - - // The Jacobian if we have to solve the block - - /* Write temporary terms for derivatives. - Also note that in the case of “evaluate” blocks, derivatives are not - computed in deterministic mode; still their temporary terms must be - computed even in that mode, because they may be needed in subsequent - blocks. */ - write_eq_tt(blocks[blk].size); + // Write residuals and temporary terms (incl. for derivatives) + writePerBlockHelper<output_type>(blk, output, temporary_terms); if constexpr(isCOutput(output_type)) output << " if (stochastic_mode) {" << endl; diff --git a/src/ModelTree.hh b/src/ModelTree.hh index bcb4a6d89e26b809856040ed42fdfafe677bfd05..a03e96597f35b7d0dbdb7ad8b789d5591d423a6f 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -271,6 +271,10 @@ protected: template<ExprNodeOutputType output_type> pair<vector<ostringstream>, vector<ostringstream>> writeModelFileHelper() const; + // Writes per-block residuals and temporary terms (incl. for derivatives) + template<ExprNodeOutputType output_type> + void writePerBlockHelper(int blk, ostream &output, temporary_terms_t &temporary_terms) const; + /* Helper for writing derivatives w.r.t. parameters. Returns { tt, rp, gp, rpp, gpp, hp, g3p }. g3p is empty if requesting a static output type. */ @@ -812,6 +816,89 @@ ModelTree::writeModelFileHelper() const return { move(d_output), move(tt_output) }; } +template<ExprNodeOutputType output_type> +void +ModelTree::writePerBlockHelper(int blk, ostream &output, temporary_terms_t &temporary_terms) const +{ + int block_recursive_size { blocks[blk].getRecursiveSize() }; + + // The equations + deriv_node_temp_terms_t tef_terms; + + auto write_eq_tt = [&](int eq) + { + for (auto it : blocks_temporary_terms[blk][eq]) + { + if (dynamic_cast<AbstractExternalFunctionNode *>(it)) + it->writeExternalFunctionOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs, tef_terms); + + output << " "; + it->writeOutput(output, output_type, blocks_temporary_terms[blk][eq], blocks_temporary_terms_idxs, tef_terms); + output << '='; + it->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs, tef_terms); + temporary_terms.insert(it); + output << ';' << endl; + } + }; + + for (int eq {0}; eq < blocks[blk].size; eq++) + { + write_eq_tt(eq); + + EquationType equ_type { getBlockEquationType(blk, eq) }; + BinaryOpNode *e { getBlockEquationExpr(blk, eq) }; + expr_t lhs { e->arg1 }, rhs { e->arg2 }; + switch (blocks[blk].simulation_type) + { + case BlockSimulationType::evaluateBackward: + case BlockSimulationType::evaluateForward: + evaluation: + if (equ_type == EquationType::evaluateRenormalized) + { + e = getBlockEquationRenormalizedExpr(blk, eq); + lhs = e->arg1; + rhs = e->arg2; + } + else if (equ_type != EquationType::evaluate) + { + cerr << "Type mismatch for equation " << getBlockEquationID(blk, eq)+1 << endl; + exit(EXIT_FAILURE); + } + output << " "; + lhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); + output << '='; + rhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); + output << ';' << endl; + break; + case BlockSimulationType::solveBackwardSimple: + case BlockSimulationType::solveForwardSimple: + case BlockSimulationType::solveBackwardComplete: + case BlockSimulationType::solveForwardComplete: + case BlockSimulationType::solveTwoBoundariesComplete: + case BlockSimulationType::solveTwoBoundariesSimple: + if (eq < block_recursive_size) + goto evaluation; + output << " residual" << LEFT_ARRAY_SUBSCRIPT(output_type) + << eq-block_recursive_size+ARRAY_SUBSCRIPT_OFFSET(output_type) + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=("; + lhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); + output << ")-("; + rhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); + output << ");" << endl; + break; + default: + cerr << "Incorrect type for block " << blk+1 << endl; + exit(EXIT_FAILURE); + } + } + + /* Write temporary terms for derivatives. + This is done even for “evaluate” blocks, whose derivatives are not + always computed at runtime; still those temporary terms may be needed by + subsequent blocks. */ + write_eq_tt(blocks[blk].size); +} + template<ExprNodeOutputType output_type> tuple<ostringstream, ostringstream, ostringstream, ostringstream, ostringstream, ostringstream, ostringstream> diff --git a/src/StaticModel.hh b/src/StaticModel.hh index a67637d7a5f0745d2080ecbe08b2ef22347ab25f..092ebdc046af0fb1ef5feebe99504963d6f088e6 100644 --- a/src/StaticModel.hh +++ b/src/StaticModel.hh @@ -176,82 +176,8 @@ StaticModel::writeStaticPerBlockHelper(int blk, ostream &output, temporary_terms BlockSimulationType simulation_type { blocks[blk].simulation_type }; int block_recursive_size { blocks[blk].getRecursiveSize() }; - // The equations - deriv_node_temp_terms_t tef_terms; - - auto write_eq_tt = [&](int eq) - { - for (auto it : blocks_temporary_terms[blk][eq]) - { - if (dynamic_cast<AbstractExternalFunctionNode *>(it)) - it->writeExternalFunctionOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs, tef_terms); - - output << " "; - it->writeOutput(output, output_type, blocks_temporary_terms[blk][eq], blocks_temporary_terms_idxs, tef_terms); - output << '='; - it->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs, tef_terms); - temporary_terms.insert(it); - output << ';' << endl; - } - }; - - for (int eq {0}; eq < blocks[blk].size; eq++) - { - write_eq_tt(eq); - - EquationType equ_type { getBlockEquationType(blk, eq) }; - BinaryOpNode *e { getBlockEquationExpr(blk, eq) }; - expr_t lhs { e->arg1 }, rhs { e->arg2 }; - switch (simulation_type) - { - case BlockSimulationType::evaluateBackward: - case BlockSimulationType::evaluateForward: - evaluation: - if (equ_type == EquationType::evaluateRenormalized) - { - e = getBlockEquationRenormalizedExpr(blk, eq); - lhs = e->arg1; - rhs = e->arg2; - } - else if (equ_type != EquationType::evaluate) - { - cerr << "Type mismatch for equation " << getBlockEquationID(blk, eq)+1 << endl; - exit(EXIT_FAILURE); - } - output << " "; - lhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); - output << '='; - rhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); - output << ';' << endl; - break; - case BlockSimulationType::solveBackwardSimple: - case BlockSimulationType::solveForwardSimple: - case BlockSimulationType::solveBackwardComplete: - case BlockSimulationType::solveForwardComplete: - if (eq < block_recursive_size) - goto evaluation; - output << " residual" << LEFT_ARRAY_SUBSCRIPT(output_type) - << eq-block_recursive_size+ARRAY_SUBSCRIPT_OFFSET(output_type) - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=("; - lhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); - output << ")-("; - rhs->writeOutput(output, output_type, temporary_terms, blocks_temporary_terms_idxs); - output << ");" << endl; - break; - default: - cerr << "Incorrect type for block " << blk+1 << endl; - exit(EXIT_FAILURE); - } - } - - /* Write temporary terms for derivatives. - This is done even for “evaluate” blocks, whose derivatives are not - computed at runtime; still those temporary terms may be needed by - subsequent blocks (not calling write_eq_tt() would not be a bug though, - because those terms would not be added to temporary_terms_union and would - therefore not be used; still, it’s probably better performance-wise to - use those temporary terms). */ - write_eq_tt(blocks[blk].size); + // Write residuals and temporary terms (incl. for derivatives) + writePerBlockHelper<output_type>(blk, output, temporary_terms); // The Jacobian if we have to solve the block if (simulation_type != BlockSimulationType::evaluateBackward