8 #include <catch2/catch_test_macros.hpp> 
   21 using namespace nmodl;
 
   22 using namespace visitor;
 
   24 using namespace test_utils;
 
   40     SymtabVisitor(
false).visit_program(*ast);
 
   43     ConstantFolderVisitor().visit_program(*ast);
 
   44     InlineVisitor().visit_program(*ast);
 
   45     LocalVarRenameVisitor().visit_program(*ast);
 
   46     SymtabVisitor(
true).visit_program(*ast);
 
   49     SympyConductanceVisitor().visit_program(*ast);
 
   52     CheckParentVisitor().check_ast(*ast);
 
   65     SymtabVisitor().visit_program(*ast);
 
   74     SymtabVisitor v_symtab;
 
   75     v_symtab.visit_program(node);
 
   78     SympyConductanceVisitor v_sympy1;
 
   79     v_sympy1.visit_program(node);
 
   80     v_symtab.visit_program(node);
 
   81     v_sympy1.visit_program(node);
 
   82     v_symtab.visit_program(node);
 
   85     SympyConductanceVisitor v_sympy2;
 
   86     v_sympy2.visit_program(node);
 
   87     v_symtab.visit_program(node);
 
   88     v_sympy1.visit_program(node);
 
   89     v_symtab.visit_program(node);
 
   90     v_sympy2.visit_program(node);
 
   91     v_symtab.visit_program(node);
 
   94 SCENARIO(
"Addition of CONDUCTANCE using SympyConductance visitor", 
"[visitor][solver][sympy]") {
 
   97     GIVEN(
"breakpoint block containing VERBATIM statement") {
 
   98         std::string nmodl_text = R
"( 
  101                 USEION ca READ eca WRITE ica 
  102                 RANGE gCabar, gCa, ica 
  105                 CONDUCTANCE gCa USEION ca 
  106                 SOLVE states METHOD cnexp 
  114         std::string breakpoint_text = R"( 
  116                 CONDUCTANCE gCa USEION ca 
  117                 SOLVE states METHOD cnexp 
  130     GIVEN(
"breakpoint block containing IF/ELSE block") {
 
  131         std::string nmodl_text = R
"( 
  134                 USEION ca READ eca WRITE ica 
  135                 RANGE gCabar, gCa, ica 
  138                 CONDUCTANCE gCa USEION ca 
  139                 SOLVE states METHOD cnexp 
  149         std::string breakpoint_text = R"( 
  151                 CONDUCTANCE gCa USEION ca 
  152                 SOLVE states METHOD cnexp 
  167     GIVEN(
"ion current, existing CONDUCTANCE hint & var") {
 
  168         std::string nmodl_text = R
"( 
  171                 USEION ca READ eca WRITE ica 
  172                 RANGE gCabar, gCa, ica 
  182                 gCabar = 0.00001 (S/cm2) 
  206                 CONDUCTANCE gCa USEION ca 
  207                 SOLVE states METHOD cnexp 
  222         std::string breakpoint_text = R"( 
  224                 CONDUCTANCE gCa USEION ca 
  225                 SOLVE states METHOD cnexp 
  235     GIVEN(
"ion current, no CONDUCTANCE hint, existing var") {
 
  236         std::string nmodl_text = R
"( 
  239                 USEION ca READ eca WRITE ica 
  240                 RANGE gCabar, gCa, ica 
  250                 gCabar = 0.00001 (S/cm2) 
  274                 SOLVE states METHOD cnexp 
  289         std::string breakpoint_text = R"( 
  291                 CONDUCTANCE gCa USEION ca 
  292                 SOLVE states METHOD cnexp 
  297         THEN("Add CONDUCTANCE hint using existing var") {
 
  302     GIVEN(
"ion current, no CONDUCTANCE hint, no existing var") {
 
  303         std::string nmodl_text = R
"( 
  306                 USEION ca READ eca WRITE ica 
  317                 gCabar = 0.00001 (S/cm2) 
  340                 SOLVE states METHOD cnexp 
  341                 ica = (gCabar*m*m*h)*(v-eca) 
  354         std::string breakpoint_text = R"( 
  357                 CONDUCTANCE g_ca_0 USEION ca 
  358                 g_ca_0 = gCabar*h*pow(m, 2) 
  359                 SOLVE states METHOD cnexp 
  360                 ica = (gCabar*m*m*h)*(v-eca) 
  363         THEN("Add CONDUCTANCE hint with new local var") {
 
  368     GIVEN(
"2 ion currents, 1 CONDUCTANCE hint, 1 existing var") {
 
  369         std::string nmodl_text = R
"( 
  372                 USEION ca READ eca WRITE ica 
  373                 USEION na READ ena WRITE ina 
  374                 RANGE gCabar, gNabar, ica, ina 
  384                 gCabar = 0.00001 (S/cm2) 
  385                 gNabar = 0.00005 (S/cm2) 
  410                 CONDUCTANCE gCa USEION ca 
  411                 SOLVE states METHOD cnexp 
  414                 ina = (gNabar*m*h)*(v-eca) 
  427         std::string breakpoint_text = R"( 
  430                 CONDUCTANCE g_na_0 USEION na 
  432                 CONDUCTANCE gCa USEION ca 
  433                 SOLVE states METHOD cnexp 
  436                 ina = (gNabar*m*h)*(v-eca) 
  439         THEN("Add 1 CONDUCTANCE hint with new local var") {
 
  444     GIVEN(
"2 ion currents, no CONDUCTANCE hints, 1 existing var") {
 
  445         std::string nmodl_text = R
"( 
  448                 USEION ca READ eca WRITE ica 
  449                 USEION na READ ena WRITE ina 
  450                 RANGE gCabar, gNabar, ica, ina 
  460                 gCabar = 0.00001 (S/cm2) 
  461                 gNabar = 0.00005 (S/cm2) 
  486                 SOLVE states METHOD cnexp 
  489                 ina = (gNabar*m*h)*(v-eca) 
  502         std::string breakpoint_text = R"( 
  505                 CONDUCTANCE g_na_0 USEION na 
  506                 CONDUCTANCE gCa USEION ca 
  508                 SOLVE states METHOD cnexp 
  511                 ina = (gNabar*m*h)*(v-eca) 
  514         THEN("Add 2 CONDUCTANCE hints, 1 with existing var, 1 with new local var") {
 
  519     GIVEN(
"2 ion currents, no CONDUCTANCE hints, no existing vars") {
 
  520         std::string nmodl_text = R
"( 
  523                 USEION ca READ eca WRITE ica 
  524                 USEION na READ ena WRITE ina 
  525                 RANGE gCabar, gNabar, ica, ina 
  535                 gCabar = 0.00001 (S/cm2) 
  536                 gNabar = 0.00005 (S/cm2) 
  561                 SOLVE states METHOD cnexp 
  562                 ica = (gCabar*m*m*h)*(v-eca) 
  563                 ina = (gNabar*m*h)*(v-eca) 
  576         std::string breakpoint_text = R"( 
  579                 CONDUCTANCE g_na_0 USEION na 
  580                 CONDUCTANCE g_ca_0 USEION ca 
  581                 g_ca_0 = gCabar*h*pow(m, 2) 
  583                 SOLVE states METHOD cnexp 
  584                 ica = (gCabar*m*m*h)*(v-eca) 
  585                 ina = (gNabar*m*h)*(v-eca) 
  588         THEN("Add 2 CONDUCTANCE hints with 2 new local vars") {
 
  593     GIVEN(
"1 ion current, 1 nonspecific current, no CONDUCTANCE hints, no existing vars") {
 
  594         std::string nmodl_text = R
"( 
  597                 USEION ca READ eca WRITE ica 
  598                 NONSPECIFIC_CURRENT ihcn 
  609                 gCabar = 0.00001 (S/cm2) 
  634                 SOLVE states METHOD cnexp 
  635                 ica = (gCabar*m*m*h)*(v-eca) 
  636                 ihcn = (0.1235*m*h)*(v-eca) 
  649         std::string breakpoint_text = R"( 
  653                 CONDUCTANCE g_ca_0 USEION ca 
  654                 g_ca_0 = gCabar*h*pow(m, 2) 
  656                 SOLVE states METHOD cnexp 
  657                 ica = (gCabar*m*m*h)*(v-eca) 
  658                 ihcn = (0.1235*m*h)*(v-eca) 
  661         THEN("Add 2 CONDUCTANCE hints with 2 new local vars") {
 
  666     GIVEN(
"1 ion current, 1 nonspecific current, no CONDUCTANCE hints, 1 existing var") {
 
  667         std::string nmodl_text = R
"( 
  670                 USEION ca READ eca WRITE ica 
  671                 NONSPECIFIC_CURRENT ihcn 
  672                 RANGE gCabar, ica, gihcn 
  682                 gCabar = 0.00001 (S/cm2) 
  708                 SOLVE states METHOD cnexp 
  710                 ica = (gCabar*m*m*h)*(v-eca) 
  724         std::string breakpoint_text = R"( 
  728                 CONDUCTANCE g_ca_0 USEION ca 
  729                 g_ca_0 = gCabar*h*pow(m, 2) 
  730                 SOLVE states METHOD cnexp 
  732                 ica = (gCabar*m*m*h)*(v-eca) 
  736         THEN("Add 2 CONDUCTANCE hints, 1 using existing var, 1 with new local var") {
 
  743         "2 ion currents, 1 nonspecific current, no CONDUCTANCE hints, indirect relation between " 
  745         std::string nmodl_text = R
"( 
  748                     POINT_PROCESS ProbAMPANMDA 
  749                     RANGE tau_r_AMPA, tau_d_AMPA, tau_r_NMDA, tau_d_NMDA 
  750                     RANGE Use, u, Dep, Fac, u0, mg, NMDA_ratio 
  751                     RANGE i, i_AMPA, i_NMDA, g_AMPA, g_NMDA, g, e 
  752                     NONSPECIFIC_CURRENT i, i_AMPA,i_NMDA 
  754                     RANGE synapseID, verboseLevel 
  757                     tau_r_AMPA = 0.2   (ms)  : dual-exponential conductance profile 
  758                     tau_d_AMPA = 1.7    (ms)  : IMPORTANT: tau_r < tau_d 
  759                     tau_r_NMDA = 0.29   (ms) : dual-exponential conductance profile 
  760                     tau_d_NMDA = 43     (ms) : IMPORTANT: tau_r < tau_d 
  761                     Use = 1.0   (1)   : Utilization of synaptic efficacy (just initial values! Use, Dep and Fac are overwritten by BlueBuilder assigned values) 
  762                     Dep = 100   (ms)  : relaxation time constant from depression 
  763                     Fac = 10   (ms)  :  relaxation time constant from facilitation 
  764                     e = 0     (mV)  : AMPA and NMDA reversal potential 
  765                     mg = 1   (mM)  : initial concentration of mg2+ 
  767                     gmax = .001 (uS) : weight conversion factor (from nS to uS) 
  768                     u0 = 0 :initial value of u, which is the running value of Use 
  769                     NMDA_ratio = 0.71 (1) : The ratio of NMDA to AMPA 
  786                     A_AMPA       : AMPA state variable to construct the dual-exponential profile - decays with conductance tau_r_AMPA 
  787                     B_AMPA       : AMPA state variable to construct the dual-exponential profile - decays with conductance tau_d_AMPA 
  788                     A_NMDA       : NMDA state variable to construct the dual-exponential profile - decays with conductance tau_r_NMDA 
  789                     B_NMDA       : NMDA state variable to construct the dual-exponential profile - decays with conductance tau_d_NMDA 
  792                     SOLVE state METHOD cnexp 
  794                     g_AMPA = gmax*(B_AMPA-A_AMPA) :compute time varying conductance as the difference of state variables B_AMPA and A_AMPA 
  795                     g_NMDA = gmax*(B_NMDA-A_NMDA) * mggate :compute time varying conductance as the difference of state variables B_NMDA and A_NMDA and mggate kinetics 
  797                     i_AMPA = g_AMPA*(v-e) :compute the AMPA driving force based on the time varying conductance, membrane potential, and AMPA reversal 
  798                     i_NMDA = g_NMDA*(v-e) :compute the NMDA driving force based on the time varying conductance, membrane potential, and NMDA reversal 
  802                     A_AMPA' = -A_AMPA/tau_r_AMPA 
  803                     B_AMPA' = -B_AMPA/tau_d_AMPA 
  804                     A_NMDA' = -A_NMDA/tau_r_NMDA 
  805                     B_NMDA' = -B_NMDA/tau_d_NMDA 
  808         std::string breakpoint_text = R"( 
  813                     SOLVE state METHOD cnexp 
  815                     g_AMPA = gmax*(B_AMPA-A_AMPA) :compute time varying conductance as the difference of state variables B_AMPA and A_AMPA 
  816                     g_NMDA = gmax*(B_NMDA-A_NMDA) * mggate :compute time varying conductance as the difference of state variables B_NMDA and A_NMDA and mggate kinetics 
  818                     i_AMPA = g_AMPA*(v-e) :compute the AMPA driving force based on the time varying conductance, membrane potential, and AMPA reversal 
  819                     i_NMDA = g_NMDA*(v-e) :compute the NMDA driving force based on the time varying conductance, membrane potential, and NMDA reversal 
  823         THEN("Add 3 CONDUCTANCE hints, using existing vars") {
 
  829     GIVEN(
"1 nonspecific current, no CONDUCTANCE hints, many eqs & a function involved") {
 
  830         std::string nmodl_text = R
"( 
  832                 GLOBAL tau_r_AMPA, E_AMPA 
  833                 RANGE tau_d_AMPA, gmax_AMPA 
  835                 GLOBAL tau_r_NMDA, tau_d_NMDA, E_NMDA 
  837                 RANGE Use, Dep, Fac, Nrrp, u 
  838                 RANGE tsyn, unoccupied, occupied 
  841                 GLOBAL ljp_VDCC, vhm_VDCC, km_VDCC, mtau_VDCC, vhh_VDCC, kh_VDCC, htau_VDCC 
  842                 RANGE gca_bar_VDCC, ica_VDCC 
  843                 GLOBAL gamma_ca_CR, tau_ca_CR, min_ca_CR, cao_CR 
  844                 GLOBAL tau_GB, gamma_d_GB, gamma_p_GB, rho_star_GB, tau_Use_GB, tau_effca_GB 
  845                 RANGE theta_d_GB, theta_p_GB 
  847                 RANGE enable_GB, depress_GB, potentiate_GB 
  848                 RANGE Use_d_GB, Use_p_GB 
  849                 GLOBAL p_gen_RW, p_elim0_RW, p_elim1_RW 
  850                 RANGE enable_RW, synstate_RW 
  851                 GLOBAL mg, scale_mg, slope_mg 
  852                 RANGE vsyn, NMDA_ratio, synapseID, selected_for_report, verbose 
  853                 NONSPECIFIC_CURRENT i 
  858                 (uS)    = (microsiemens) 
  865                 FARADAY = (faraday) (coulomb) 
  867                 R       = (k-mole)  (joule/degC) 
  880             FUNCTION nernst(ci(mM), co(mM), z) (mV) { 
  881                 nernst = (1000) * R * (celsius + 273.15) / (z*FARADAY) * log(co/ci) 
  884                 LOCAL Eca_syn, mggate, i_AMPA, gmax_NMDA, i_NMDA, Pf_NMDA, gca_bar_abs_VDCC, gca_VDCC 
  885                 g_AMPA = (1e-3)*gmax_AMPA*(B_AMPA-A_AMPA) 
  886                 i_AMPA = g_AMPA*(v-E_AMPA) 
  887                 gmax_NMDA = gmax_AMPA*NMDA_ratio 
  888                 mggate = 1 / (1 + exp(slope_mg * -(v)) * (mg / scale_mg)) 
  889                 g_NMDA = (1e-3)*gmax_NMDA*mggate*(B_NMDA-A_NMDA) 
  890                 i_NMDA = g_NMDA*(v-E_NMDA) 
  891                 Pf_NMDA  = (4*cao_CR) / (4*cao_CR + (1/1.38) * 120 (mM)) * 0.6 
  892                 ica_NMDA = Pf_NMDA*g_NMDA*(v-40.0) 
  893                 gca_bar_abs_VDCC = gca_bar_VDCC * 4(um2)*PI*(3(1/um3)/4*volume_CR*1/PI)^(2/3) 
  894                 gca_VDCC = (1e-3) * gca_bar_abs_VDCC * m_VDCC * m_VDCC * h_VDCC 
  895                 Eca_syn = FARADAY*nernst(cai_CR, cao_CR, 2) 
  896                 ica_VDCC = gca_VDCC*(v-Eca_syn) 
  898                 i = i_AMPA + i_NMDA + ica_VDCC 
  901         std::string breakpoint_text = R"( 
  903                 LOCAL Eca_syn, mggate, i_AMPA, gmax_NMDA, i_NMDA, Pf_NMDA, gca_bar_abs_VDCC, gca_VDCC, nernst_in_0, g__0 
  905                 g__0 = (0.001*gmax_NMDA*mg*scale_mg*slope_mg*(A_NMDA-B_NMDA)*(E_NMDA-v)*exp(slope_mg*v)-0.001*gmax_NMDA*scale_mg*(A_NMDA-B_NMDA)*(mg+scale_mg*exp(slope_mg*v))*exp(slope_mg*v)+(g_AMPA+gca_VDCC)*pow(mg+scale_mg*exp(slope_mg*v), 2))/pow(mg+scale_mg*exp(slope_mg*v), 2) 
  906                 g_AMPA = 1e-3*gmax_AMPA*(B_AMPA-A_AMPA) 
  907                 i_AMPA = g_AMPA*(v-E_AMPA) 
  908                 gmax_NMDA = gmax_AMPA*NMDA_ratio 
  909                 mggate = 1/(1+exp(slope_mg*-v)*(mg/scale_mg)) 
  910                 g_NMDA = 1e-3*gmax_NMDA*mggate*(B_NMDA-A_NMDA) 
  911                 i_NMDA = g_NMDA*(v-E_NMDA) 
  912                 Pf_NMDA = (4*cao_CR)/(4*cao_CR+0.7246376811594204*120(mM))*0.6 
  913                 ica_NMDA = Pf_NMDA*g_NMDA*(v-40.0) 
  914                 gca_bar_abs_VDCC = gca_bar_VDCC*4(um2)*PI*(3(1/um3)/4*volume_CR*1/PI)^0.6666666666666666 
  915                 gca_VDCC = 1e-3*gca_bar_abs_VDCC*m_VDCC*m_VDCC*h_VDCC 
  917                     LOCAL ci_in_0, co_in_0, z_in_0 
  921                     nernst_in_0 = 1000*R*(celsius+273.15)/(z_in_0*FARADAY)*log(co_in_0/ci_in_0) 
  923                 Eca_syn = FARADAY*nernst_in_0 
  924                 ica_VDCC = gca_VDCC*(v-Eca_syn) 
  926                 i = i_AMPA+i_NMDA+ica_VDCC 
  929         THEN("Add 1 CONDUCTANCE hint using new var") {