.. _coreneuron-running-a-simulation:

Running a simulation
####################
This section describes how to use CoreNEURON to simulate a NEURON model.

Building MOD files
******************
As in a typical NEURON workflow, you can now use ``nrnivmodl`` to translate MOD files.
In order to enable CoreNEURON support, you must set the ``-coreneuron`` flag.
Make sure any necessary modules (compilers, CUDA, MPI etc.) are loaded before you run ``nrnivmodl``:

.. code-block::

   nrnivmodl -coreneuron <directory containing .mod files>

Even if you don't have additional MOD files (i.e. you are relying on
builtin NEURON MOD files) **you still need to use** ``nrnivmodl
-coreneuron`` **to generate a CoreNEURON library**.
For example, you can run:

.. code-block::

   nrnivmodl -coreneuron .

With the command above, NEURON will create a ``x86_64/special`` binary
that is linked to CoreNEURON (here ``x86_64`` is the architecture name
of your system).

If you see any compilation error then one of the MOD files might be incompatible with CoreNEURON.
In this case, you should first consult the :ref:`CoreNEURON compatibility` section, and if that does not provide a clear explanation then you should `open an issue <https://github.com/BlueBrain/CoreNeuron/issues>`_ with an example of your MOD file.

Enabling CoreNEURON
*******************
With CoreNEURON, existing NEURON models can be run with minimal changes.
For a given NEURON model, the following steps are usually required:

First, enable cache efficiency:

.. code-block:: python

   from neuron import h
   h.CVode().cache_efficient(1)

Second, enable CoreNEURON:

.. code-block:: python

   from neuron import coreneuron
   coreneuron.enable = True

If your build supports GPU execution then you may also enable this at runtime:

.. code-block:: python

   coreneuron.gpu = True

.. warning::

   **If you enable GPU execution you must launch your simulation using the** ``special`` **binary!**
   This is explained in more detail below.

Finally, use ``psolve`` to run the simulation after initialization:

.. code-block:: python

   h.stdinit()
   pc.psolve(h.tstop)

With the above steps, NEURON will build the model in memory and transfer it to CoreNEURON for simulation.
At the end of the simulation CoreNEURON will, by default, transfer spikes, voltages, state variables, NetCon weights, all ``Vector.record``, and most GUI trajectories to NEURON.
These variables can be recorded using the regular NEURON API (e.g. :meth:`Vector.record` or :meth:`ParallelContext.spike_record`).

If you are primarily using HOC then before calling ``psolve`` you can enable CoreNEURON as:

.. code-block::

   // make sure NEURON is compiled with Python
   if (!nrnpython("from neuron import coreneuron")) {
     printf("NEURON not compiled with Python support\n")
     return
   }

   // access coreneuron module via Python object
   py_obj = new PythonObject()
   py_obj.coreneuron.enable = 1

Once you have adapted your model by making the changes described above
then you can execute your model like a normal NEURON simulation.
For example:

.. code-block::

   mpiexec -n <num_process> nrniv -mpi -python your_script.py # python
   mpiexec -n <num_process> nrniv -mpi your_script.hoc        # hoc

Alternatively, instead of ``nrniv`` you can use the ``special`` binary generated by ``nrnivmodl`` command.
Note that for GPU execution you **must** use the ``special`` binary to launch your simulation:

.. code-block::

   mpiexec -n <num_process> x86_64/special -mpi -python your_script.py # python
   mpiexec -n <num_process> x86_64/special -mpi your_script.hoc        # hoc

This is because the GPU-enabled build is statically linked `to avoid issues with OpenACC <https://forums.developer.nvidia.com/t/clarification-on-using-openacc-in-a-shared-library/136279/27>`_, so ``python`` and ``nrniv`` cannot dynamically load CoreNEURON.

As CoreNEURON is used as a library under NEURON, it will use the same number of MPI ranks as NEURON.
Also, if you enable threads using :meth:`ParallelContext.nthread` then CoreNEURON will internally use the same number of OpenMP threads.

.. note::

  You may need to replace mpiexec with an MPI launcher supported on your system, e.g. ``srun`` or ``mpirun``.
