nrn icon indicating copy to clipboard operation
nrn copied to clipboard

How many ways are POINTER variables allowed to be used?

Open olupton opened this issue 1 year ago • 3 comments

Context

In the context of https://github.com/neuronsimulator/nrn/pull/1929 some changes are required to the handling of POINTER variables. This issue is supposed to collect the different usage patterns that need to be accounted for.

test_pointer.py example

In this case we have: https://github.com/neuronsimulator/nrn/blob/b226aabd26e0fb4d4ab60fa58b1db5dce12257bc/test/coreneuron/test_pointer.py#L78-L80 where the values referred to by some POINTER variables: https://github.com/neuronsimulator/nrn/blob/b226aabd26e0fb4d4ab60fa58b1db5dce12257bc/test/coreneuron/mod%20files/axial.inc#L7 are set from Python / the interpreter.

The first RHS, seg._ref_v , is a voltage. In #1929 this lives in a "modern" data structure and hence a "smart" data handle must be used to keep track of it.

In this case the generated .cpp code from the MOD file reads and writes the pointed-to values, but never attempts to modify which variable is pointed-to (i.e. the pointer value itself).

invlfire.mod example

In this case we have POINTER r, vecs (link) and the actual pointer value is read inside a VERBATIM section of a NET_RECEIVE block: (link)

NET_RECEIVE (w, srcgid) {
    ...
VERBATIM
    RecvInfo* rip = (RecvInfo*)_p_vecs;

and modified inside a VERBATIM section of a PROCEDURE block: (link)

PROCEDURE set_record() {
VERBATIM
    RecvInfo** rip = (RecvInfo**)(&(_p_vecs));
    if (!(*rip)) {
        *rip = (RecvInfo*)hoc_Emalloc(sizeof(RecvInfo)); hoc_malchk();
    }

which is called from HOC (link).

In this case, the variable is not set up to point at any NEURON data structure, but it is assumed that the value can be written to (in the PROCEDURE) and that that value will be saved.

watchrange.mod example

This is similar to invlfire.mod, but uses BBCOREPOINTER instead of POINTER: https://github.com/neuronsimulator/nrn/blob/b226aabd26e0fb4d4ab60fa58b1db5dce12257bc/test/coreneuron/mod%20files/watchrange.mod#L10

As above, the pointer value is updated in a PROCEDURE block: https://github.com/neuronsimulator/nrn/blob/b226aabd26e0fb4d4ab60fa58b1db5dce12257bc/test/coreneuron/mod%20files/watchrange.mod#L92-L103

and it is used in the INITIAL block: https://github.com/neuronsimulator/nrn/blob/b226aabd26e0fb4d4ab60fa58b1db5dce12257bc/test/coreneuron/mod%20files/watchrange.mod#L39-L44

and a FUNCTION block: https://github.com/neuronsimulator/nrn/blob/b226aabd26e0fb4d4ab60fa58b1db5dce12257bc/test/coreneuron/mod%20files/watchrange.mod#L83-L87

again, the pointer is not set to point to any internal NEURON data structure. There are many other examples using this pattern.

Other patterns

  • What is missing from the above list?
  • Are there any non-VERBATIM patterns that result in translated MOD file code which updates pointer values (as opposed to pointed-to values)?
  • Are there any patterns (including in VERBATIM blocks) where translated MOD file code updates POINTER variables to point to different locations within NEURON's data structures?
  • ... presumably other questions ...

olupton avatar Sep 20 '22 13:09 olupton

@nrnhines your input would be much appreciated when you have some time!

olupton avatar Sep 20 '22 13:09 olupton

I don't think anything is missing from the above list. I know of only 3 kinds of pointers.

  1. pointers to scalar doubles (pointer set by user with interpreter statement)
  2. pointers to Hoc Objects (Vector, Random) and used in the mod file as the void* instance arg of methods on the Object*
  3. Pointers to data allocated and freed by each instance of the mod file mechanism

There are no non-verbatim patterns that update a pointer value except that one may reset a pointer to point to another scalar from the interpreter in the same way one originally set the pointer.

No mod files set pointers into NEURON data structures.

nrnhines avatar Sep 20 '22 14:09 nrnhines

One and a half other patterns that may be outside of the scope of this question, but shouldn't break:

  1. Pointers into non-NEURON managed memory; most commonly this would be by using neuron.numpy_element_ref(numpy_array, index) to get a pointer into a numpy array. These could be used anywhere in the mod file (e.g. in particular, they're fine to use outside a verbatim block).

  2. Using a Pointer to pass in a function. For example, if we have a POINTER on_event, we might set a callback from Python and then have a VERBATIM block in a NET_RECEIVE with lines like

    double (*event_callback)(double) = (double (*)(double)) _p_on_event;
    return_value = event_callback(_args[0]);
    

ramcdougal avatar Sep 20 '22 15:09 ramcdougal

I also came across this example, which has only recently been added to the CTest suite: https://github.com/neuronsimulator/nrn/blob/0cdcc5c74649686d2c512a297d86e870ab6aac73/share/examples/nrniv/nmodl/tstpnt1.hoc

olupton avatar Oct 05 '22 13:10 olupton

Line 16, POINTER in mod file instance that points to an element of a hoc double array, is formally correct. It is mostly to exhibit the syntax of setpointer. The only context I can think of offhand for it to be substantively useful is if the array has the size of pc.nthread() and all instances in a thread,j, accumulate a value into element j for later summation (Though one is more likely to use Vector elements that are pointed to.) In python world the hoc setpointer lines could be written as

h.tp[0]._ref_p1 = h.a(.5)._ref_v
for i in range(1,10):
    h.tp[i]._ref_p1 = h._ref_d[i]

nrnhines avatar Oct 05 '22 14:10 nrnhines

I suppose the HOC Pointer and PtrVector classes should be added to the variants. In particular, PtrVector.ptr_update_callback is presently used to redo the pointers when internal memory is reallocated. An example of the latter is nrn/test/coreneuron/test_pointer.py which ironically only uses an empty PtrVector so that the callback can set up the nmodl POINTER variables.

nrnhines avatar Oct 05 '22 14:10 nrnhines