neuronsimulator / nrn

NEURON Simulator
http://nrn.readthedocs.io
Other
407 stars 118 forks source link

Review DISCRETE. #3082

Open 1uc opened 2 months ago

1uc commented 2 months ago

The following MOD file:

NEURON {
  SUFFIX disc
  GLOBAL k, a0
}

PARAMETER {
  k = 1
}

STATE {
  a
}

INITIAL {
  a = a0
}

BREAKPOINT {
  SOLVE dis
}

DISCRETE dis {
  a = a - k*a@4
}

Slightly modified from: https://github.com/neuronsimulator/nrn/blob/e462814e58383100d43785e84af9380b91d5e98e/docs/nmodl/mod/disc.mod

Generates the following code when using nocmodl:

#define a              _ml->template fpfield<0>(_iml)

static double __a[4];
void dis() {
    {
        int _i;
        for (_i = 3; _i > 0; _i--)
            __a[_i] = __a[_i - 1];
        __a[0] = a;
    }
    { a = a - k * __a[3]; }
}
// ...
static void nrn_state(...) {
/...
    for (_iml = 0; _iml < _cntml; ++_iml) {
        t += dt;
        dis();
    }
}

There's the following comment in the documentation:

Many other features of the model description language, such as DISCRETE blocks, and sensitivity analysis, optimization are not relevant in the NEURON context and may or may not produce meaningful translations.

https://nrn.readthedocs.io/en/8.2.6/hoc/modelspec/programmatic/mechanisms/nmodl.html#initial

I couldn't find any uses on Model DB.

Some question are:

  1. Can we remove the test and not support DISCRETE in the nmodl codegenerator?
  2. Is the behaviour correct, when there's multiple instances of the mechanism?
  3. Do we need to prevent @n with n>1, e.g. by refusing to generate code from NOCMODL?
nrnhines commented 2 months ago

One of the principle differences between the original MODL design and NMODL was that the former used a MOD file to describe the entire simulation model. NMODL extended this in two directions. Multiple instances of a single description and combining multiple descriptions. The first involves an instance per spatial compartment and (for POINT_PROCESSES) the possibility of many instances within a compartment. The second involves many descriptions within a single compartment.

So, when one sees data translated into static double it is occasionally a clue that the translation implementation dates back to MODL and was never examined with regard to whether it was reasonable to extend to NMODL. Also it suggests that the feature was never used in a multicompartment context.

In the case of DISCRETE, it is clearly straight forward to extend to multiple instances by making the internal __a[4] analogous to a RANGE variable (and deciding whether it is a good or bad idea to expose those values to the interpreter).

It is hard to get excited about DISCRETE since it was never used, the naive implementation is dt dependent, and it can't work with CVODE.

It seems to me that the simplest alternatives are to 1: raise a new NMODL error if DISCRETE is used, or, 2: translate the array __a[4] into a container array variable (private) so that each instance has its own array. I guess I would choose alternative 2.