User Guide
neuron_solve.cpp
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 #include <catch2/catch_test_macros.hpp>
9 
10 #include "ast/program.hpp"
11 #include "parser/nmodl_driver.hpp"
17 
18 
19 using namespace nmodl;
20 using namespace visitor;
21 using namespace test;
22 using namespace test_utils;
23 
25 
26 
27 //=============================================================================
28 // CnexpSolve visitor tests
29 //=============================================================================
30 
31 std::string run_cnexp_solve_visitor(const std::string& text) {
33  const auto& ast = driver.parse_string(text);
34 
35  SymtabVisitor().visit_program(*ast);
36  NeuronSolveVisitor().visit_program(*ast);
37  std::stringstream stream;
38  NmodlPrintVisitor(stream).visit_program(*ast);
39 
40  // check that, after visitor rearrangement, parents are still up-to-date
41  CheckParentVisitor().check_ast(*ast);
42 
43  return stream.str();
44 }
45 
46 
47 SCENARIO("NeuronSolveVisitor visitor solves different ODE types") {
48  GIVEN("Derivative block with cnexp method in breakpoint block") {
49  std::string nmodl_text = R"(
50  BREAKPOINT {
51  SOLVE states METHOD cnexp
52  }
53 
54  DERIVATIVE states {
55  m' = (mInf-m)/mTau[0]
56  h' = (hInf-h)/hTau
57  m = m + h
58  }
59  )";
60 
61  std::string output_nmodl = R"(
62  BREAKPOINT {
63  SOLVE states METHOD cnexp
64  }
65 
66  DERIVATIVE states {
67  m = m+(1.0-exp(dt*((((-1.0)))/mTau[0])))*(-(((mInf))/mTau[0])/((((-1.0)))/mTau[0])-m)
68  h = h+(1.0-exp(dt*((((-1.0)))/hTau)))*(-(((hInf))/hTau)/((((-1.0)))/hTau)-h)
69  m = m+h
70  }
71  )";
72 
73  THEN("ODEs get replaced with solution") {
74  std::string input = reindent_text(nmodl_text);
75  auto expected_result = reindent_text(output_nmodl);
76  auto result = run_cnexp_solve_visitor(input);
77  REQUIRE(result == expected_result);
78  }
79  }
80 
81  GIVEN("Derivative block without any solve method specification") {
82  std::string nmodl_text = R"(
83  DERIVATIVE states {
84  m' = (mInf-m)/mTau
85  h' = (hInf-h)/hTau
86  }
87  )";
88 
89  std::string output_nmodl = R"(
90  DERIVATIVE states {
91  m' = (mInf-m)/mTau
92  h' = (hInf-h)/hTau
93  }
94  )";
95 
96  THEN("ODEs don't get solved") {
97  std::string input = reindent_text(nmodl_text);
98  auto expected_result = reindent_text(output_nmodl);
99  auto result = run_cnexp_solve_visitor(input);
100  REQUIRE(result == expected_result);
101  }
102  }
103 
104  GIVEN("Derivative block with non-cnexp method in breakpoint block") {
105  std::string nmodl_text = R"(
106  BREAKPOINT {
107  SOLVE states METHOD derivimplicit
108  }
109 
110  DERIVATIVE states {
111  m' = (mInf-m)/mTau
112  h' = (hInf-h)/hTau
113  }
114  )";
115 
116  std::string output_nmodl = R"(
117  BREAKPOINT {
118  SOLVE states METHOD derivimplicit
119  }
120 
121  DERIVATIVE states {
122  Dm = (mInf-m)/mTau
123  Dh = (hInf-h)/hTau
124  }
125  )";
126 
127  THEN("ODEs don't get solved but state variables get replaced with Dstate ") {
128  std::string input = reindent_text(nmodl_text);
129  auto expected_result = reindent_text(output_nmodl);
130  auto result = run_cnexp_solve_visitor(input);
131  REQUIRE(result == expected_result);
132  }
133  }
134 
135  GIVEN("Derivative block with ODEs that needs non-cnexp method to solve") {
136  std::string nmodl_text = R"(
137  BREAKPOINT {
138  SOLVE states METHOD cnexp
139  }
140 
141  DERIVATIVE states {
142  A_AMPA' = tau_r_AMPA/A_AMPA
143  }
144  )";
145 
146  std::string output_nmodl = R"(
147  BREAKPOINT {
148  SOLVE states METHOD cnexp
149  }
150 
151  DERIVATIVE states {
152  A_AMPA' = tau_r_AMPA/A_AMPA
153  }
154  )";
155 
156  THEN("ODEs don't get replaced as cnexp is not possible") {
157  std::string input = reindent_text(nmodl_text);
158  auto expected_result = reindent_text(output_nmodl);
159  auto result = run_cnexp_solve_visitor(input);
160  REQUIRE(result == expected_result);
161  }
162  }
163 }
test_utils.hpp
nmodl::parser::NmodlDriver
Class that binds all pieces together for parsing nmodl file.
Definition: nmodl_driver.hpp:67
SCENARIO
SCENARIO("NeuronSolveVisitor visitor solves different ODE types")
Definition: neuron_solve.cpp:47
nmodl::test_utils::reindent_text
std::string reindent_text(const std::string &text, int indent_level)
Reindent nmodl text for text-to-text comparison.
Definition: test_utils.cpp:53
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
run_cnexp_solve_visitor
std::string run_cnexp_solve_visitor(const std::string &text)
Definition: neuron_solve.cpp:31
program.hpp
Auto generated AST classes declaration.
driver
nmodl::parser::UnitDriver driver
Definition: parser.cpp:28
nmodl::parser::UnitDriver::parse_string
bool parse_string(const std::string &input)
parser Units provided as string (used for testing)
Definition: unit_driver.cpp:40
neuron_solve_visitor.hpp
Visitor that solves ODEs using old solvers of NEURON
checkparent_visitor.hpp
Visitor for checking parents of ast nodes
nmodl_driver.hpp
symtab_visitor.hpp
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
nmodl_visitor.hpp
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.