Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing & Fixing issues with DBBS-Lab's MOD file collection #888

Open
5 of 6 tasks
pramodk opened this issue Jun 30, 2022 · 2 comments
Open
5 of 6 tasks

Testing & Fixing issues with DBBS-Lab's MOD file collection #888

pramodk opened this issue Jun 30, 2022 · 2 comments
Assignees
Labels
bug Something isn't working codegen Code generation backend

Comments

@pramodk
Copy link
Contributor

pramodk commented Jun 30, 2022

We have been working with Robin in order to run his model with CoreNEURON on GPU (see neuronsimulator/nrn/issues/1839). While testing the model, we have seen quite some issues in NMODL translation. The goal of this ticket is to compile mod files and fix translation+compilation issues.

What to do?

  • Install coreneuron + nmodl with sympy (-DCORENRN_ENABLE_NMODL=ON "-DCORENRN_NMODL_FLAGS=sympy --analytic")
  • Get mod file collection from DBBS Lab
git clone https://github.com/dbbs-lab/dbbs-mod-collection.git

Few mod file has issues and we should do following:

  1. following file is not required and incompatible with coreneuron
rm dbbs-mod-collection/dbbs_mod_collection/mod/glia__dbbs_mod_collection__gap_junction__parallel.mod 
  1. dbbs_mod_collection/mod/glia__dbbs_mod_collection__cdp5__CR.mod file needs following change (state variable can't be in COMPARTMENT)
diff --git a/dbbs_mod_collection/mod/glia__dbbs_mod_collection__cdp5__CR.mod b/dbbs_mod_collection/mod/glia__dbbs_mod_collection__cdp5__CR.mod
index 32df989..7edb9ef 100644
--- a/dbbs_mod_collection/mod/glia__dbbs_mod_collection__cdp5__CR.mod
+++ b/dbbs_mod_collection/mod/glia__dbbs_mod_collection__cdp5__CR.mod
@@ -100,6 +100,7 @@ ASSIGNED {
        cai       (mM)
        mgi     (mM)
        vrat    (1)
+       mg              (mM)^M
 }

 CONSTANT { cao = 2     (mM) }
@@ -110,7 +111,6 @@ STATE {
        : let it be ~1.5 - 2 orders of magnitude smaller than baseline level

        ca              (mM)    <1e-3>
-       mg              (mM)    <1e-6>

        Buff1           (mM)
        Buff1_ca        (mM)
@@ -223,7 +223,7 @@ LOCAL dsq, dsqvol  : can't define local variable in KINETIC block
                    :   or use in COMPARTMENT statement

 KINETIC state {
-  COMPARTMENT diam*diam*vrat {ca mg Buff1 Buff1_ca Buff2 Buff2_ca BTC BTC_ca DMNPE DMNPE_ca CR CR_1C_0N CR_2C_0N CR_2C_1N CR_0C_1N CR_0C_2N CR_1C_2N CR_1C_1N CR_2C_1N CR_1C_2N CR_2C_2N}
+  COMPARTMENT diam*diam*vrat {ca Buff1 Buff1_ca Buff2 Buff2_ca BTC BTC_ca DMNPE DMNPE_ca CR CR_1C_0N CR_2C_0N CR_2C_1N CR_0C_1N CR_0C_2N CR_1C_2N CR_1C_1N CR_2C_1N CR_1C_2N CR_2C_2N}^M
   COMPARTMENT (1e10)*parea {pump pumpca}
  • With above two changes, mod files compile with mod2c but not with NMODL. So our goal is to make sure mod files can be compiled with NMODL as well i.e.
nrnivmodl-core dbbs-mod-collection/dbbs_mod_collection/mod/

Fixed

 x86_64/corenrn/mod2c/glia__dbbs_mod_collection__Nav1_1__0.cpp:191:30: error: duplicate member 'g'
         double* __restrict__ g{};
                              ^
 x86_64/corenrn/mod2c/glia__dbbs_mod_collection__Nav1_1__0.cpp:125:30: note: previous declaration is here
         double* __restrict__ g{};                              ^
 1 error generated.

Typically, g is implicitly defined in the MOD file. In this MOD file, g is declared as a RANGE variable and this causes double member declaration in the instance structure.

     struct glia__dbbs_mod_collection__Nav1_1__0_Instance  {
         double* __restrict__ celsius{&coreneuron::celsius};
         const double* __restrict__ gbar{};
         double* __restrict__ ina{};
         double* __restrict__ i{};
         double* __restrict__ igate{};
         double* __restrict__ g{};
..
         double* __restrict__ DI6{};
         double* __restrict__ g{};
...

To be fixed

  • glia__dbbs_mod_collection__cdp5__0.mod,
    glia__dbbs_mod_collection__cdp5__CAM_GoC.mod
    glia__dbbs_mod_collection__cdp5__CAM.mod,
    glia__dbbs_mod_collection__cdp5__CR.mod

Take updated mod files from dbbs-lab/dbbs-mod-collection#6.

Above mod files define LOCAL variables at global scope as:

 LOCAL dsq, dsqvol  : can't define local variable in KINETIC block
                    :   or use in COMPARTMENT statement

 KINETIC state {
   COMPARTMENT diam*diam*vrat {ca Buff1 Buff1_ca Buff2 Buff2_ca BTC BTC_ca DMNPE DMNPE_ca CR CR_1C_0N CR_2C_0N CR_2C_1N CR_0C_1N CR_0C_2N CR_1C_2N CR_1C_1N CR_2C_1N CR_1C_2N   CR_2C_2N}
   COMPARTMENT (1e10)*parea {pump pumpca}


     :pump
     ~ ca + pump <-> pumpca  (kpmp1*parea*(1e10), kpmp2*parea*(1e10))
     ~ pumpca <-> pump   (kpmp3*parea*(1e10), 0)
     CONSERVE pump + pumpca = TotalPump * parea * (1e10)

     ica_pmp = 2*FARADAY*(f_flux - b_flux)/parea
     : all currents except pump
     : ica is Ca efflux
     ~ ca << (-ica*PI*diam/(2*FARADAY))

and when we compile generated .cpp file then we get:

 x86_64/corenrn/mod2c/glia__dbbs_mod_collection__cdp5__CR.cpp:731:2053: error: use of undeclared identifier 'dsqvol'
 x86_64/corenrn/mod2c/glia__dbbs_mod_collection__cdp5__CR.cpp:700:21: error: use of undeclared identifier 'dsq'
                     dsq = inst->diam[indexes[4*pnodecount + id]] * inst->diam[indexes[4*pnodecount + id]];
                     ^
 x86_64/corenrn/mod2c/glia__dbbs_mod_collection__cdp5__CR.cpp:701:21: error: use of undeclared identifier 'dsqvol'
                     dsqvol = dsq * inst->vrat[id];                     ^
 x86_64/corenrn/mod2c/glia__dbbs_mod_collection__cdp5__CR.cpp:701:30: error: use of undeclared identifier 'dsq'
                     dsqvol = dsq * inst->vrat[id];

It's true that we can not use a LOCAL variable as it's not thread/SIMD safe (and we have a special pass to convert LOCAL to RANGE). But, I am expecting NMODL to show correct error than resulting in incorrect code and then compilation error?

Note: For now we can manually change LOCAL variables to RANGE and have mod file compiled. But, the generated Eigen code seems scary (in terms of complexity) and we need to involve @cattabiani to take a look. See #930.

  • glia__dbbs_mod_collection__Na__granule_cell_FHF.mod and glia__dbbs_mod_collection__Na__granule_cell.mod

These two files have function calls in the KINETIC block, see #927.

 KINETIC kstates {
     : 1 riga
     ~ C1 <-> C2 (n1*alfa(v),n4*beta(v))
     ~ C2 <-> C3 (n2*alfa(v),n3*beta(v))

Note: Temporarily, one could re-write the mod file by first calling function calls before equations and storing the returned values into LOCAL variables?

@pramodk pramodk added bug Something isn't working codegen Code generation backend labels Jun 30, 2022
pramodk added a commit to neuronsimulator/nrn that referenced this issue Aug 17, 2022
* certain mod files use read/write ion variables
  from USEION statements in CONSTANT {} block
* the generated code from such usage is not desired
  I believe. For example, cdp_spiny.mod from ModelDB
  model id 266799 has

  ```console
  NEURON {
  	SUFFIX cdp4Nsp
   	USEION ca READ cao, cai, ica WRITE cai
   	RANGE ica_pmp,scale
	...
  }

  ASSIGNED {
     diam      (um)
     ica       (mA/cm2)
     ica_pmp   (mA/cm2)
     parea     (um)     : pump area per unit length
     cai       (mM)
  }

  CONSTANT { cao = 2  (mM) }
  ```

  In this example, the generated code doesn't set ion variable `cao` to 2
  but declare a static variable `cao` with value 2 and that is not used
  anywhere:

  ```cpp
   #define ica _p[56]
   #define ica_columnindex 56
   #define parea _p[57]
   #define parea_columnindex 57
   #define cai _p[58]
   ...
   #define _ion_cao    *_ppvar[0]._pval
   #define _ion_cai    *_ppvar[1]._pval
   #define _ion_ica    *_ppvar[2]._pval
   #define _style_ca   *((int*)_ppvar[3]._pvoid)
   #define diam    *_ppvar[4]._pval
   ...
   static double cao = 2;
   ...
   static void nrn_state(NrnThread* _nt, _Memb_list* _ml, int _type) {

	...
	cao = _ion_cao;
        cai = _ion_cai;
        ica = _ion_ica;
        cai = _ion_cai;
        ...
   }
  ```

  Note that `cao` variable used/updated here is not ion variable but static one
  defined in the file scope.

  I believe this is not what user "expected" here.

* As we see this pattern in multiple mod files (including glia__dbbs_mod_collection__cdp5__CAM_GoC.mod
  mentioned in BlueBrain/nmodl#888), in this PR we disable
  declaring ion variables as CONSTANT. With this PR, we will get an error like:

  ```console
   $ ./bin/nocmodl /.../nmodldb/models/db/modeldb/266799/mod/cdp_spiny.mod
   ...
   cao used in USEION statement can not be re-declared in the CONSTANT block at line 299 in file /.../nmodldb/models/db/modeldb/266799/mod/cdp_spiny.mod
   ```
pramodk added a commit that referenced this issue Aug 17, 2022
* Similar to neuronsimulator/nrn#1955
* Add semantic analysis check to avoid declaring ion variables
  in CONSTANT {} block
* Addresses first point in #888
  MOD file is glia__dbbs_mod_collection__cdp5__CAM_GoC.mod.
* Updated test
pramodk added a commit that referenced this issue Sep 4, 2022
* table statements can have array variables. Until now only
  scalar variables were supported in code generation.
* we can check symbol table to find out if the variable is
  an array and it's length.
* similar to mod2c implementation, generate code for array
  variable assignments:
     https://github.com/BlueBrain/mod2c/blob/469c74dc7d96bbc5a06a42696422154b4cd2ce28/src/mod2c_core/parsact.c#L942
* with this, `glia__dbbs_mod_collection__Cav2_3__0.mod` from #888
  compiles
pramodk added a commit that referenced this issue Sep 6, 2022
* table statements can have array variables. Until now only
  scalar variables were supported in code generation.
* we can check symbol table to find out if the variable is
  an array and it's length.
* similar to mod2c implementation, generate code for array
  variable assignments:
     https://github.com/BlueBrain/mod2c/blob/469c74dc7d96bbc5a06a42696422154b4cd2ce28/src/mod2c_core/parsact.c#L942
* with this, `glia__dbbs_mod_collection__Cav2_3__0.mod` from #888
  compiles
pramodk added a commit that referenced this issue Sep 6, 2022
…tement

* When we have TABLE statement used in a PROCEDURE and if such procedure
  is called from DERIVATIVE block then we end-up calling table statement
  related function from initialize() function:

  `c++

        struct functor {
            NrnThread* nt;
            glia__dbbs_mod_collection__Ca__granule_cell_Instance* inst;
            int id, pnodecount;
            double v;
            Datum* indexes;
            double old_s, old_u;

            void initialize() {
                rate_glia__dbbs_mod_collection__Ca__granule_cell(id, pnodecount, inst, data, indexes, thread, nt, v, v);
                ...
  `

  Here we are lacking data and thread variable as members in `struct functor`.

* This happens with the `glia__dbbs_mod_collection__Ca__granule_cell.mod` in #888
pramodk added a commit that referenced this issue Sep 6, 2022
…tement

* When we have TABLE statement used in a PROCEDURE and if such procedure
  is called from DERIVATIVE block then we end-up calling table statement
  related function from initialize() function:

  `c++

        struct functor {
            NrnThread* nt;
            glia__dbbs_mod_collection__Ca__granule_cell_Instance* inst;
            int id, pnodecount;
            double v;
            Datum* indexes;
            double old_s, old_u;

            void initialize() {
                rate_glia__dbbs_mod_collection__Ca__granule_cell(id, pnodecount, inst, data, indexes, thread, nt, v, v);
                ...
  `

  Here we are lacking data and thread variable as members in `struct functor`.

* This happens with the `glia__dbbs_mod_collection__Ca__granule_cell.mod` in #888
pramodk added a commit that referenced this issue Sep 7, 2022
* Table statements can have array variables. Until now only
  scalar variables were supported in code generation.
* We can check symbol table to find out if the variable is
  an array and it's length.
* Similar to mod2c implementation, generate code for array
  variable assignments:
     https://github.com/BlueBrain/mod2c/blob/469c74dc7d96bbc5a06a42696422154b4cd2ce28/src/mod2c_core/parsact.c#L942
* with this, `glia__dbbs_mod_collection__Cav2_3__0.mod` from #888
  compiles

* Add test and fix the bug for array variables allocation and access
pramodk added a commit that referenced this issue Sep 7, 2022
…tement (#925)

* When we have TABLE statement used in a PROCEDURE and if such procedure
  is called from DERIVATIVE block then we end-up calling table statement
  related function from initialize() function:

  ```c++

        struct functor {
            NrnThread* nt;
            glia__dbbs_mod_collection__Ca__granule_cell_Instance* inst;
            int id, pnodecount;
            double v;
            Datum* indexes;
            double old_s, old_u;

            void initialize() {
                rate_glia__dbbs_mod_collection__Ca__granule_cell(id, pnodecount, inst, data, indexes, thread, nt, v, v);
                ...
  ```

  Here we are lacking `data` and `thread` variable as members in `struct functor`.

* This happens with the `glia__dbbs_mod_collection__Ca__granule_cell.mod` in #888
pramodk added a commit that referenced this issue Sep 9, 2022
* Similar to neuronsimulator/nrn#1955
* Add semantic analysis check to avoid declaring ion variables
  in CONSTANT {} block
* Addresses first point in #888
  MOD file is glia__dbbs_mod_collection__cdp5__CAM_GoC.mod.
* Updated test
pramodk added a commit that referenced this issue Sep 9, 2022
* Similar to neuronsimulator/nrn#1955,
  add semantic analysis check to avoid declaring ion variables
  in CONSTANT {} block
* Addresses first point in #888
  MOD file is glia__dbbs_mod_collection__cdp5__CAM_GoC.mod.
* Updated test
pramodk added a commit that referenced this issue Sep 9, 2022
* when user defined g as a range variable in a non-threadsafe
  mod file, then instance structure was declaring g as a member
  variable twice
* now, check if variable is already defined before adding new
  declaration
* this is realted to #888 with mod file glia__dbbs_mod_collection__Nav1_1__0.mod
pramodk added a commit to pramodk/dbbs-mod-collection that referenced this issue Sep 9, 2022
@Helveg
Copy link

Helveg commented Sep 10, 2022

Also, to us this is brittle legacy code, if you have any advice/sanitizations to make these mod files more standard; there's likely no technical reason for the weirder things they do, other than that they are 20 years old and noone knows better.

@pramodk
Copy link
Contributor Author

pramodk commented Sep 12, 2022

@Helveg : thanks! Definitely revisit them. Some of the MOD files can be made compatible with some changes but I also wanted to make NMODL to handle all legacy usage patterns. Hence would like to fix the issues.

We will come back to you once few remaining issues are solved.

pramodk added a commit that referenced this issue Sep 13, 2022
* when user defined g as a range variable in a non-threadsafe
  mod file, then instance structure was declaring g as a member
  variable twice
* now, check if variable is already defined before adding new
  declaration
* this is realted to #888 with mod file glia__dbbs_mod_collection__Nav1_1__0.mod
* print v_unused in case mod file is threadsafe
@pramodk pramodk assigned iomaganaris and unassigned alkino Jan 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working codegen Code generation backend
Projects
None yet
Development

No branches or pull requests

4 participants