NEURON
kinetic_block_visitor.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 Blue Brain Project, EPFL.
3  * See the top-level LICENSE file for details.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #pragma once
9 
10 /**
11  * \file
12  * \brief \copybrief nmodl::visitor::KineticBlockVisitor
13  */
14 
15 #include <memory>
16 #include <string>
17 #include <unordered_map>
18 #include <unordered_set>
19 #include <vector>
20 
21 #include "visitors/ast_visitor.hpp"
22 
23 namespace nmodl {
24 namespace visitor {
25 
26 /**
27  * \addtogroup visitor_classes
28  * \{
29  */
30 
31 /**
32  * \class KineticBlockVisitor
33  * \brief %Visitor for kinetic block statements
34  *
35  * Replaces each KINETIC block with a DERIVATIVE block
36  * containing a system of ODEs that is equivalent to
37  * the original set of reaction statements
38  *
39  * Note: assumes that the order of statements between the first and last
40  * reaction statement (those starting with "~") does not matter.
41  *
42  * If there is a CONSERVE statement it is rewritten in an equivalent
43  * form which is then be used by the SympySolver visitor to replace
44  * the ODE for the last state variable on the LHS of the CONSERVE statement
45  *
46  */
48  private:
49  /// update stoichiometric matrices with reaction var term
50  void process_reac_var(const std::string& varname, int count = 1);
51 
52  /// update CONSERVE statement with reaction var term
53  void process_conserve_reac_var(const std::string& varname, int count = 1);
54 
55  void set_compartment_factor(int var_index, const std::string& factor);
58 
59  /// Unroll loops in KINETIC blocks.
60  ///
61  /// The subsequent processing in KineticBlockVisitor fails if there's any
62  /// reaction equation inside a `FROM .. TO ..` block. The solution is to
63  /// unroll any loops first to satisfy the assumption.
65 
66  /// stochiometric matrices nu_L, nu_R
67  /// forwards/backwards fluxes k_f, k_b
68  /// (see kinetic_schemes.ipynb notebook for details)
69  struct RateEqs {
70  std::vector<std::vector<int>> nu_L;
71  std::vector<std::vector<int>> nu_R;
72  std::vector<std::string> k_f;
73  std::vector<std::string> k_b;
75 
76  /// multiplicative factors for ODEs from COMPARTMENT statements
77  std::vector<std::string> compartment_factors;
78 
79  /// additive constant terms for ODEs from reaction statements like ~ x << (a)
80  std::vector<std::string> additive_terms;
81 
82  /// multiplicate constant terms for fluxes from non-state vars as reactants
83  /// e.g. reaction statements like ~ x <-> c (a,a)
84  /// where c is not a state var, which is equivalent to the ODE
85  /// x' = a * (c - x)
86  std::vector<std::string> non_state_var_fflux;
87  std::vector<std::string> non_state_var_bflux;
88 
89  /// generated set of fluxes and ODEs
90  std::vector<std::string> fflux;
91  std::vector<std::string> bflux;
92  std::vector<std::string> odes;
93 
94  /// current expressions for the `fflux`, `bflux` variables that can be used in the mod file
95  /// and that are determined by the preceeding kinetic reaction statement, i.e. their
96  /// value changes depending on their location inside the kinetic block
97  std::string modfile_fflux;
98  std::string modfile_bflux;
99 
100  /// number of state variables
102 
103  /// state variables vector
104  std::vector<std::string> state_var;
105 
106  /// unordered_map from state variable to corresponding index
107  std::unordered_map<std::string, int> state_var_index;
108 
109  /// unordered_map from array state variable to its size (for summing over each element of any
110  /// array state vars in a CONSERVE statement)
111  std::unordered_map<std::string, int> array_state_var_size;
112 
113  /// true if we are visiting a reaction statement
114  bool in_reaction_statement = false;
115 
116  /// true if we are visiting the left hand side of reaction statement
118 
119  /// true if we are visiting a CONSERVE statement
120  bool in_conserve_statement = false;
121 
122  /// counts the number of CONSERVE statements in Kinetic blocks
124 
125  /// conserve statement equation as string
127 
128  /// conserve statement: current state variable being processed
130 
131  /// conserve statement: current state var multiplicative factor being processed
133 
134  /// current statement index
135  int i_statement = 0;
136 
137  /// vector of kinetic block nodes
138  std::vector<ast::KineticBlock*> kinetic_blocks;
139 
140  /// statements to remove from block
141  std::unordered_set<ast::Statement*> statements_to_remove;
142 
143  /// current statement block being visited
145 
146  public:
147  KineticBlockVisitor() = default;
148  inline int get_conserve_statement_count() const {
150  }
151 
156  void visit_conserve(ast::Conserve& node) override;
157  void visit_compartment(ast::Compartment& node) override;
160  void visit_program(ast::Program& node) override;
161 };
162 
163 /** \} */ // end of visitor_classes
164 
165 } // namespace visitor
166 } // namespace nmodl
Concrete visitor for all AST classes.
Represent COMPARTMENT statement in NMODL.
Definition: compartment.hpp:39
Represent CONSERVE statement in NMODL.
Definition: conserve.hpp:38
Represents a name.
Definition: name.hpp:44
Represents top level AST node for whole NMODL input.
Definition: program.hpp:39
Represents block encapsulating list of statements.
Wrap any other expression type.
Concrete visitor for all AST classes.
Definition: ast_visitor.hpp:37
Visitor for kinetic block statements
int state_var_count
number of state variables
void visit_kinetic_block(ast::KineticBlock &node) override
visit node of type ast::KineticBlock
std::string modfile_fflux
current expressions for the fflux, bflux variables that can be used in the mod file and that are dete...
void visit_reaction_operator(ast::ReactionOperator &node) override
visit node of type ast::ReactionOperator
struct nmodl::visitor::KineticBlockVisitor::RateEqs rate_eqs
void compute_compartment_factor(ast::Compartment &node, const ast::Name &name)
void visit_reaction_statement(ast::ReactionStatement &node) override
visit node of type ast::ReactionStatement
void visit_react_var_name(ast::ReactVarName &node) override
visit node of type ast::ReactVarName
bool in_conserve_statement
true if we are visiting a CONSERVE statement
std::string conserve_equation_str
conserve statement equation as string
std::vector< std::string > non_state_var_bflux
std::vector< ast::KineticBlock * > kinetic_blocks
vector of kinetic block nodes
std::vector< std::string > fflux
generated set of fluxes and ODEs
int conserve_statement_count
counts the number of CONSERVE statements in Kinetic blocks
void unroll_kinetic_blocks(ast::Program &node)
Unroll loops in KINETIC blocks.
void visit_statement_block(ast::StatementBlock &node) override
visit node of type ast::StatementBlock
std::unordered_map< std::string, int > array_state_var_size
unordered_map from array state variable to its size (for summing over each element of any array state...
std::vector< std::string > compartment_factors
multiplicative factors for ODEs from COMPARTMENT statements
std::vector< std::string > additive_terms
additive constant terms for ODEs from reaction statements like ~ x << (a)
std::unordered_set< ast::Statement * > statements_to_remove
statements to remove from block
void visit_conserve(ast::Conserve &node) override
visit node of type ast::Conserve
void visit_wrapped_expression(ast::WrappedExpression &node) override
visit node of type ast::WrappedExpression
void visit_compartment(ast::Compartment &node) override
visit node of type ast::Compartment
void process_conserve_reac_var(const std::string &varname, int count=1)
update CONSERVE statement with reaction var term
void visit_program(ast::Program &node) override
visit node of type ast::Program
void compute_indexed_compartment_factor(ast::Compartment &node, const ast::Name &name)
std::string conserve_equation_factor
conserve statement: current state var multiplicative factor being processed
std::string conserve_equation_statevar
conserve statement: current state variable being processed
void set_compartment_factor(int var_index, const std::string &factor)
ast::StatementBlock * current_statement_block
current statement block being visited
std::unordered_map< std::string, int > state_var_index
unordered_map from state variable to corresponding index
void process_reac_var(const std::string &varname, int count=1)
update stoichiometric matrices with reaction var term
std::vector< std::string > non_state_var_fflux
multiplicate constant terms for fluxes from non-state vars as reactants e.g.
bool in_reaction_statement_lhs
true if we are visiting the left hand side of reaction statement
std::vector< std::string > state_var
state variables vector
bool in_reaction_statement
true if we are visiting a reaction statement
const char * name
Definition: init.cpp:16
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
static Node * node(Object *)
Definition: netcvode.cpp:291
stochiometric matrices nu_L, nu_R forwards/backwards fluxes k_f, k_b (see kinetic_schemes....