|
User Guide
|
Go to the documentation of this file.
36 logger->debug(
"KineticBlockVisitor :: adding non-state fflux[{}] \"{}\"",
41 logger->debug(
"KineticBlockVisitor :: adding non-state bflux[{}] \"{}\"",
49 int i_statevar = it->second;
53 logger->debug(
"KineticBlockVisitor :: nu_L[{}][{}] += {}",
60 logger->debug(
"KineticBlockVisitor :: nu_R[{}][{}] += {}",
81 if (compartment_factor.empty()) {
93 "KineticBlockVisitor :: Error : CONSERVE statement should only contain state vars "
94 "on LHS, but found {}",
101 std::shared_ptr<ast::Expression>
create_expr(
const std::string& str_expr) {
103 auto expr = std::dynamic_pointer_cast<ast::ExpressionStatement>(statement)->get_expression();
104 return std::dynamic_pointer_cast<ast::BinaryExpression>(expr)->get_rhs();
115 logger->debug(
"KineticBlockVisitor :: CONSERVE statement: {}",
to_nmodl(node));
140 auto expr = std::dynamic_pointer_cast<ast::Conserve>(statement);
151 throw std::runtime_error(
"Setting compartment volume twice.");
155 logger->debug(
"KineticBlockVisitor :: COMPARTMENT factor {} for state var {} (index {})",
166 int var_index = it->second;
168 std::string expression =
to_nmodl(expr);
173 "KineticBlockVisitor :: COMPARTMENT specified volume for non-state variable {}",
183 auto pattern = fmt::format(
"^{}\\[([0-9]*)\\]$", array_var_name);
184 std::regex re(pattern);
187 for (
size_t var_index = 0; var_index <
state_var.size(); ++var_index) {
188 auto matches = std::regex_match(
state_var[var_index], m, re);
191 int index_value = std::stoi(m[1]);
193 auto expr = std::shared_ptr<ast::Expression>(volume_expr->clone());
196 std::string expression =
to_nmodl(*expr);
257 logger->debug(
"KineticBlockVisitor :: '<<' reaction statement: {}",
to_nmodl(node));
267 bool single_state_var =
true;
268 if (lhs->is_react_var_name()) {
269 auto value = std::dynamic_pointer_cast<ast::ReactVarName>(lhs)->get_value();
270 if (value && (value->eval() != 1)) {
271 single_state_var =
false;
274 if (!lhs->is_react_var_name() || !single_state_var) {
275 throw std::runtime_error(fmt::format(
276 "KineticBlockVisitor :: LHS of \"<<\" reaction statement must be a single state "
277 "var, but instead found {}: ignoring this statement",
281 std::string varname =
to_nmodl(lhs);
285 int var_index = it->second;
292 logger->debug(
"KineticBlockVisitor :: '<<' reaction statement: {}' += {}",
339 std::string multiply_var = std::string(
"*").append(
state_var[j]);
380 auto var_name = std::dynamic_pointer_cast<ast::Name>(node.
get_expression());
381 if (var_name->get_node_name() ==
"f_flux") {
383 logger->debug(
"KineticBlockVisitor :: replacing f_flux with {}",
to_nmodl(expr));
385 }
else if (var_name->get_node_name() ==
"b_flux") {
387 logger->debug(
"KineticBlockVisitor :: replacing b_flux with {}",
to_nmodl(expr));
429 for (
int j = 0; j < Nj; ++j) {
432 for (
int i = 0; i < Ni; ++i) {
436 if (!ode_rhs.empty()) {
439 if (
bflux[i].empty()) {
440 ode_rhs += fmt::format(
"({}*({}))", delta_nu,
fflux[i]);
441 }
else if (
fflux[i].empty()) {
442 ode_rhs += fmt::format(
"({}*(-{}))", delta_nu,
bflux[i]);
444 ode_rhs += fmt::format(
"({}*({}-{}))", delta_nu,
fflux[i],
bflux[i]);
453 if (!ode_rhs.empty()) {
455 std::string var_str = state_var_split[0];
456 std::string index_str;
457 if (state_var_split.size() > 1) {
458 index_str =
"[" + state_var_split[1];
460 odes.push_back(fmt::format(
"{}'{} = {}", var_str, index_str, ode_rhs));
464 for (
const auto& ode:
odes) {
465 logger->debug(
"KineticBlockVisitor :: ode : {}", ode);
472 for (
const auto& ode:
odes) {
473 logger->debug(
"KineticBlockVisitor :: -> adding statement: {}", ode);
487 std::string unmangled_name = fmt::format(
"{}{}_", stem,
n_equations);
488 std::string mangled_name = unmangled_name;
490 size_t mangle_attempt = 0;
492 mangled_name = fmt::format(
"{}{:04d}", unmangled_name, mangle_attempt++);
494 if (mangle_attempt >= 10000) {
495 throw std::runtime_error(
"Failed to find unique local name.");
499 auto name = std::make_shared<ast::Name>(std::make_shared<ast::String>(mangled_name));
554 const std::shared_ptr<ast::Name>& name,
555 const std::shared_ptr<ast::Expression>& expression) {
556 auto local = std::make_shared<ast::BinaryExpression>(name,
559 return std::make_shared<ast::ExpressionStatement>(local);
562 template <
class Node>
564 return std::shared_ptr<Node>(node.
clone());
579 for (
const auto& local: locals) {
591 for (
auto iter = statements.begin(); iter != statements.end(); ++iter) {
592 if ((*iter)->is_reaction_statement()) {
593 auto reaction_equation = std::dynamic_pointer_cast<ast::ReactionStatement>(*iter);
594 auto op = reaction_equation->get_op();
598 auto local_expr1 = reaction_equation->get_expression1();
599 auto local_expr2 = reaction_equation->get_expression2();
601 std::shared_ptr<ast::Name> expr1_name =
nullptr;
602 std::shared_ptr<ast::Name> expr2_name =
nullptr;
614 reaction_equation->get_expression1());
615 localized_statements.push_back(assignment);
616 local_expr1 =
clone(*expr1_name);
621 reaction_equation->get_expression2());
622 localized_statements.push_back(assignment);
623 local_expr2 =
clone(*expr2_name);
626 auto local_reaction =
627 std::make_shared<ast::ReactionStatement>(reaction_equation->get_reaction1(),
628 reaction_equation->get_op(),
629 reaction_equation->get_reaction2(),
632 localized_statements.push_back(local_reaction);
635 for (
const auto& stmt: localized_statements) {
653 for (
const auto& ii: kineticBlockNodes) {
654 ii->accept(const_folder);
668 for (
const auto& ii: kineticBlockNodes) {
669 ii->accept(unroller);
674 for (
const auto& ii: kineticBlockNodes) {
675 ii->accept(const_folder);
695 auto statevars = symtab->get_variables_with_properties(NmodlType::state_var);
696 for (
const auto& v: statevars) {
697 std::string var_name = v->get_name();
703 for (
int i = 0; i < v->get_length(); ++i) {
705 logger->debug(
"KineticBlockVisitor :: state_var_index[{}] = {}",
712 logger->debug(
"KineticBlockVisitor :: state_var_index[{}] = {}",
723 for (
const auto& ii: kineticBlockNodes) {
730 for (
auto it = blocks.begin(); it != blocks.end(); ++it) {
731 if (it->get() == kinetic_block) {
733 std::make_shared<ast::DerivativeBlock>(kinetic_block->get_name(),
734 kinetic_block->get_statement_block());
736 dblock->set_token(tok);
void visit_wrapped_expression(ast::WrappedExpression &node) override
visit node of type ast::WrappedExpression
std::shared_ptr< ast::ExpressionStatement > localize_expression(const std::shared_ptr< ast::Name > &name, const std::shared_ptr< ast::Expression > &expression)
Base class for all AST node.
std::string to_nmodl(const ast::Ast &node, const std::set< ast::AstNodeType > &exclude_types)
Given AST node, return the NMODL string representation.
std::shared_ptr< Expression > get_expression() const noexcept
Getter for member variable WrappedExpression::expression.
void compute_compartment_factor(ast::Compartment &node, const ast::Name &name)
std::shared_ptr< Expression > get_expression1() const noexcept
Getter for member variable ReactionStatement::expression1.
std::vector< std::string > get_local_variable_names()
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...
Implement class to represent a symbol in Symbol Table.
ReactionOp get_value() const noexcept
Getter for member variable ReactionOperator::value.
std::shared_ptr< ast::Name > generate_local_name(const std::string &stem)
@ KINETIC_BLOCK
type of ast::KineticBlock
void visit_statement_block(ast::StatementBlock &node) override
visit node of type ast::StatementBlock
void process_conserve_reac_var(const std::string &varname, int count=1)
update CONSERVE statement with reaction var term
std::shared_ptr< ast::Name > generate_source_name()
void visit_children(visitor::Visitor &v) override
visit children i.e.
Represent CONSERVE statement in NMODL.
std::shared_ptr< Expression > get_expr() const noexcept
Getter for member variable Conserve::expr.
std::shared_ptr< Expression > get_expression2() const noexcept
Getter for member variable ReactionStatement::expression2.
std::vector< std::string > non_state_var_fflux
multiplicate constant terms for fluxes from non-state vars as reactants e.g.
std::vector< std::shared_ptr< Statement > > StatementVector
int conserve_statement_count
counts the number of CONSERVE statements in Kinetic blocks
std::shared_ptr< StatementBlock > get_statement_block() const noexcept override
Getter for member variable KineticBlock::statement_block.
std::shared_ptr< Name > get_index_name() const noexcept
Getter for member variable Compartment::index_name.
encapsulates code generation backend implementations
static constexpr auto kb_stem
std::vector< std::string > compartment_factors
multiplicative factors for ODEs from COMPARTMENT statements
const NameVector & get_species() const noexcept
Getter for member variable Compartment::species.
StatementVector::const_iterator insert_statement(StatementVector::const_iterator position, const std::shared_ptr< Statement > &n)
Insert member to statements.
Unroll for loop in the AST.
void visit_program(ast::Program &node) override
visit node of type ast::Program
Perform constant folding of integer/float/double expressions.
int state_var_count
number of state variables
void visit_compartment(ast::Compartment &node) override
visit node of type ast::Compartment
std::shared_ptr< VarName > get_name() const noexcept
Getter for member variable ReactVarName::name.
Helper visitor to replace index of array variable with integer.
Implement string manipulation functions.
void accept(visitor::Visitor &v) override
accept (or visit) the current AST node using provided visitor
std::vector< std::string > fflux
generated set of fluxes and ODEs
std::string conserve_equation_statevar
conserve statement: current state variable being processed
void set_expr(std::shared_ptr< Expression > &&expr)
Setter for member variable Conserve::expr (rvalue reference)
void visit_reaction_operator(ast::ReactionOperator &node) override
visit node of type ast::ReactionOperator
void visit_children(visitor::Visitor &v) override
visit children i.e.
std::shared_ptr< Expression > get_reaction1() const noexcept
Getter for member variable ReactionStatement::reaction1.
struct nmodl::visitor::KineticBlockVisitor::RateEqs rate_eqs
void visit_kinetic_block(ast::KineticBlock &node)
visit node of type ast::KineticBlock
const StatementVector & get_statements() const noexcept
Getter for member variable StatementBlock::statements.
Unroll for loop in the AST.
void visit_conserve(ast::Conserve &node) override
visit node of type ast::Conserve
Visitor for kinetic block statements
Perform constant folding of integer/float/double expressions.
Utility functions for visitors implementation.
bool in_reaction_statement_lhs
true if we are visiting the left hand side of reaction statement
LocalRateNames(symtab::SymbolTable const *symtab)
int i_statement
current statement index
std::shared_ptr< Node > clone(const Node &node)
StatementVector::const_iterator erase_statement(StatementVector::const_iterator first)
Erase member to statements.
void visit_children(visitor::Visitor &v) override
visit children i.e.
bool in_conserve_statement
true if we are visiting a CONSERVE statement
void set_compartment_factor(int var_index, const std::string &factor)
void visit_expression(ast::Expression &node) override
visit node of type ast::Expression
std::unordered_set< ast::Statement * > statements_to_remove
statements to remove from block
std::string to_string(const T &obj)
Concrete visitor for all AST classes.
void set_expression(std::shared_ptr< Expression > &&expression)
Setter for member variable WrappedExpression::expression (rvalue reference)
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_statement(ast::ReactionStatement &node) override
visit node of type ast::ReactionStatement
const ReactionOperator & get_op() const noexcept
Getter for member variable ReactionStatement::op.
symtab::SymbolTable const * symtab
std::vector< std::string > state_var
state variables vector
std::string conserve_equation_str
conserve statement equation as string
void compute_indexed_compartment_factor(ast::Compartment &node, const ast::Name &name)
Represent symbol table for a NMODL block.
std::vector< std::string > bflux
std::shared_ptr< Statement > create_statement(const std::string &code_statement)
Convert given code statement (in string format) to corresponding ast node.
std::vector< std::shared_ptr< const ast::Ast > > collect_nodes(const ast::Ast &node, const std::vector< ast::AstNodeType > &types)
traverse node recursively and collect nodes of given types
Represent COMPARTMENT statement in NMODL.
std::shared_ptr< ast::Expression > create_expr(const std::string &str_expr)
static constexpr auto source_stem
void visit_react_var_name(ast::ReactVarName &node) override
visit node of type ast::ReactVarName
LocalRateNames & operator=(const LocalRateNames &)=default
void visit_children(visitor::Visitor &v) override
visit children i.e.
std::vector< std::string > local_names
static std::vector< std::string > split_string(const std::string &text, char delimiter)
Split a text in a list of words, using a given delimiter character.
Node * clone() const override
Return a copy of the current node.
Represents block encapsulating list of statements.
void set_react(std::shared_ptr< Expression > &&react)
Setter for member variable Conserve::react (rvalue reference)
NmodlType
NMODL variable properties.
const NodeVector & get_blocks() const noexcept
Getter for member variable Program::blocks.
std::string modfile_bflux
std::vector< std::string > k_b
Operator used in ast::BinaryExpression.
std::vector< std::string > additive_terms
additive constant terms for ODEs from reaction statements like ~ x << (a)
void visit_kinetic_block(ast::KineticBlock &node) override
visit node of type ast::KineticBlock
std::pair< std::shared_ptr< ast::Name >, std::shared_ptr< ast::Name > > generate_rate_names()
std::unordered_map< std::string, int > state_var_index
unordered_map from state variable to corresponding index
std::string get_node_name() const override
Return name of the node.
Implement logger based on spdlog library.
std::vector< ast::KineticBlock * > kinetic_blocks
vector of kinetic block nodes
LocalVar * add_local_variable(StatementBlock &node, Identifier *varname)
ast::StatementBlock * current_statement_block
current statement block being visited
symtab::SymbolTable * get_symbol_table() const override
Return associated symbol table for the current ast node.
void unroll_kinetic_blocks(ast::Program &node)
Unroll loops in KINETIC blocks.
static constexpr auto kf_stem
std::vector< std::string > k_f
std::vector< std::string > odes
void process_reac_var(const std::string &varname, int count=1)
update stoichiometric matrices with reaction var term
Represents top level AST node for whole NMODL input.
void visit_statement_block(ast::StatementBlock &node)
visit node of type ast::StatementBlock
void visit_children(visitor::Visitor &v) override
visit children i.e.
bool in_reaction_statement
true if we are visiting a reaction statement
LocalRateNames local_names
void set_blocks(NodeVector &&blocks)
Setter for member variable Program::blocks (rvalue reference)
std::vector< std::vector< int > > nu_R
std::shared_ptr< ast::Name > generate_forward_rate_name()
std::shared_ptr< Integer > get_value() const noexcept
Getter for member variable ReactVarName::value.
Represent token returned by scanner.
std::vector< std::vector< int > > nu_L
Auto generated AST classes declaration.
Wrap any other expression type.
std::vector< std::string > non_state_var_bflux
std::string conserve_equation_factor
conserve statement: current state var multiplicative factor being processed
std::shared_ptr< Symbol > lookup_in_scope(const std::string &name) const
check if symbol with given name exist in the current table (including all parents)
std::shared_ptr< Expression > get_volume() const noexcept
Getter for member variable Compartment::volume.