8 #include <catch2/catch_test_macros.hpp>
24 using namespace nmodl;
25 using namespace visitor;
32 SymtabVisitor().visit_program(*ast);
34 MatexpVisitor().visit_program(*ast);
46 SCENARIO(
"Solve a KINETIC block using the matexp method",
"[visitor][matexp]") {
47 GIVEN(
"KINETIC block, to be solved in initial and breakpoint blocks") {
48 std::string input_nmodl = R
"(
50 SOLVE test_kin STEADYSTATE matexp
54 SOLVE test_kin METHOD matexp
69 CONSERVE x + y = 3.14159
71 std::string expect_output = R"(
74 nmodl_eigen_j[0] = nmodl_eigen_j[0]-(a)*nmodl_dt
75 nmodl_eigen_j[1] = nmodl_eigen_j[1]+(a)*nmodl_dt
76 nmodl_eigen_j[3] = nmodl_eigen_j[3]-(b)*nmodl_dt
77 nmodl_eigen_j[2] = nmodl_eigen_j[2]+(b)*nmodl_dt
78 } CONSERVE(CONSERVE x+y = 3.14159)
82 SOLVE test_kin METHOD matexp
96 nmodl_eigen_j[0] = nmodl_eigen_j[0]-(a)*nmodl_dt
97 nmodl_eigen_j[1] = nmodl_eigen_j[1]+(a)*nmodl_dt
98 nmodl_eigen_j[3] = nmodl_eigen_j[3]-(b)*nmodl_dt
99 nmodl_eigen_j[2] = nmodl_eigen_j[2]+(b)*nmodl_dt
100 } CONSERVE(CONSERVE x+y = 3.14159)
102 THEN("Replace the kinetic block with its solution in a procedure") {
109 SCENARIO(
"Solve multiple CONSERVE using the matexp method",
"[visitor][matexp]") {
110 GIVEN(
"KINETIC block with multiple CONSERVE statements") {
111 std::string input_nmodl = R
"(
113 SOLVE test_kin STEADYSTATE matexp
117 SOLVE test_kin METHOD matexp
127 CONSERVE x + y = 3.14159
130 std::string expect_output = R"(
133 } CONSERVE(CONSERVE x+y = 3.14159, CONSERVE z = 42)
137 SOLVE test_kin METHOD matexp
147 } CONSERVE(CONSERVE x+y = 3.14159, CONSERVE z = 42)
149 THEN("Accept multiple CONSERVE statements as valid") {
156 SCENARIO(
"Test exponential decay using the matexp method",
"[visitor][matexp]") {
157 GIVEN(
"KINETIC block, to be solved in initial and breakpoint blocks") {
158 std::string input_nmodl = R
"(
160 SOLVE test_kin STEADYSTATE matexp
164 SOLVE test_kin METHOD matexp
178 std::string expect_output = R"(
181 nmodl_eigen_j[0] = nmodl_eigen_j[0]-(a)*nmodl_dt
186 SOLVE test_kin METHOD matexp
198 nmodl_eigen_j[0] = nmodl_eigen_j[0]-(a)*nmodl_dt
201 THEN("Replace the kinetic block with its solution in a procedure") {
208 SCENARIO(
"Mix matexp and sparse solver methods",
"[visitor][matexp]") {
209 GIVEN(
"KINETIC block, to be solved by multiple methods") {
210 std::string input_nmodl = R
"(
212 SOLVE test_kin STEADYSTATE sparse
216 SOLVE test_kin METHOD matexp
227 std::string expect_output = R"(
229 SOLVE test_kin STEADYSTATE sparse
233 SOLVE test_kin METHOD matexp
246 nmodl_eigen_j[0] = nmodl_eigen_j[0]-(a)*nmodl_dt
247 nmodl_eigen_j[1] = nmodl_eigen_j[1]+(a)*nmodl_dt
248 nmodl_eigen_j[3] = nmodl_eigen_j[3]-(b)*nmodl_dt
249 nmodl_eigen_j[2] = nmodl_eigen_j[2]+(b)*nmodl_dt
253 "The original KINETIC block is kept unchanged,"
254 "its solution is inserted into a new PROCEDURE block") {
261 SCENARIO(
"Solve multiple blocks with matexp",
"[visitor][matexp]") {
262 GIVEN(
"Mutliple KINETIC block to be solved") {
263 std::string input_nmodl = R
"(
265 SOLVE test_kin_1 STEADYSTATE matexp
266 SOLVE test_kin_2 STEADYSTATE matexp
270 SOLVE test_kin_1 METHOD matexp
271 SOLVE test_kin_2 METHOD matexp
288 std::string expect_output = R"(
291 nmodl_eigen_j[0] = nmodl_eigen_j[0]-(1.1)*nmodl_dt
292 nmodl_eigen_j[1] = nmodl_eigen_j[1]+(1.1)*nmodl_dt
293 nmodl_eigen_j[5] = nmodl_eigen_j[5]-(2.2)*nmodl_dt
294 nmodl_eigen_j[4] = nmodl_eigen_j[4]+(2.2)*nmodl_dt
297 nmodl_eigen_j[10] = nmodl_eigen_j[10]-(3.3)*nmodl_dt
298 nmodl_eigen_j[11] = nmodl_eigen_j[11]+(3.3)*nmodl_dt
299 nmodl_eigen_j[15] = nmodl_eigen_j[15]-(4.4)*nmodl_dt
300 nmodl_eigen_j[14] = nmodl_eigen_j[14]+(4.4)*nmodl_dt
305 SOLVE test_kin_1 METHOD matexp
306 SOLVE test_kin_2 METHOD matexp
317 nmodl_eigen_j[0] = nmodl_eigen_j[0]-(1.1)*nmodl_dt
318 nmodl_eigen_j[1] = nmodl_eigen_j[1]+(1.1)*nmodl_dt
319 nmodl_eigen_j[5] = nmodl_eigen_j[5]-(2.2)*nmodl_dt
320 nmodl_eigen_j[4] = nmodl_eigen_j[4]+(2.2)*nmodl_dt
324 nmodl_eigen_j[10] = nmodl_eigen_j[10]-(3.3)*nmodl_dt
325 nmodl_eigen_j[11] = nmodl_eigen_j[11]+(3.3)*nmodl_dt
326 nmodl_eigen_j[15] = nmodl_eigen_j[15]-(4.4)*nmodl_dt
327 nmodl_eigen_j[14] = nmodl_eigen_j[14]+(4.4)*nmodl_dt
330 THEN("All KINETIC block are solved") {
337 SCENARIO(
"Give non-linear equations to the matexp solver",
"[visitor][matexp]") {
338 GIVEN(
"KINETIC block with x + y <-> z reaction statement") {
339 std::string input_nmodl = R
"(
341 SOLVE test_kin METHOD matexp
349 ~ x + y <-> z (123, 456)
351 THEN("Raise an exception") {
355 GIVEN(
"KINETIC block with 2 x <-> y reaction statement") {
356 std::string input_nmodl = R
"(
358 SOLVE test_kin METHOD matexp
365 ~ 2 x <-> y (123, 456)
367 THEN("Raise an exception") {
371 GIVEN(
"KINETIC block with 1 x <-> y reaction statement") {
372 std::string input_nmodl = R
"(
374 SOLVE test_kin METHOD matexp
381 ~ 1 x <-> y (123, 456)
383 THEN("Equation is valid, do not raise exception") {
387 GIVEN(
"KINETIC block with << reaction statement") {
388 std::string input_nmodl = R
"(
390 SOLVE test_kin METHOD matexp
398 THEN("Raise an exception") {
402 GIVEN(
"KINETIC block with -> reaction statement") {
403 std::string input_nmodl = R
"(
405 SOLVE test_kin METHOD matexp
413 THEN("Equation is valid, do not raise exception") {
417 GIVEN(
"KINETIC block with invalid state variable") {
418 std::string input_nmodl = R
"(
420 SOLVE test_kin METHOD matexp
428 THEN("Raise an exception") {
432 GIVEN(
"non-linear CONSERVE statement") {
433 std::string input_nmodl = R
"(
435 SOLVE test_kin METHOD matexp
443 THEN("Raise an exception") {
447 GIVEN(
"CONSERVE statement with derivatives") {
448 std::string input_nmodl = R
"(
450 SOLVE test_kin METHOD matexp
458 THEN("Raise an exception") {
Auto generated AST classes declaration.
Class that binds all pieces together for parsing nmodl file.
AstNodeType
Enum type for every AST node type.
bool parse_string(const std::string &input)
parser Units provided as string (used for testing)
std::string run_matexp_visitor(const std::string &text, bool verbatim)
SCENARIO("Solve a KINETIC block using the matexp method", "[visitor][matexp]")
Visitor used for generating the necessary AST nodes for matexp solver.
std::string reindent_text(const std::string &text, int indent_level)
Reindent nmodl text for text-to-text comparison.
encapsulates code generation backend implementations
std::string to_nmodl(const ast::Ast &node, const std::set< ast::AstNodeType > &exclude_types)
Given AST node, return the NMODL string representation.
THIS FILE IS GENERATED AT BUILD TIME AND SHALL NOT BE EDITED.
nmodl::parser::UnitDriver driver
Utility functions for visitors implementation.