/*
 *       File name:  libcn/hosted-neurons.cc
 *         Project:  cnrun
 *          Author:  Andrei Zavada <johnhommer@gmail.com>
 *                   building on original work by Thomas Nowotny <tnowotny@ucsd.edu>
 * Initial version:  2008-10-16
 *
 *         Purpose:  hosted neuron classes (those having their
 *                   state vars on parent model's integration vectors)
 *
 *         License:  GPL-2+
 */

#if HAVE_CONFIG_H && !defined(VERSION)
#  include "config.h"
#endif

#include <cmath>
#include <iostream>

#include "libstilton/lang.hh"

#include "types.hh"
#include "model.hh"


cnrun::C_HostedNeuron::
C_HostedNeuron (TUnitType intype, const string& inlabel,
                double inx, double iny, double inz,
                CModel* inM, int s_mask,
                TIncludeOption include_option)
      : C_BaseNeuron (intype, inlabel, inx, iny, inz, inM, s_mask)
{
        if ( M )
                M->include_unit( this, include_option);
        else {
//                _status &= ~CN_UENABLED;
                idx = (unsigned long)-1;
        }
}





void
cnrun::C_HostedConductanceBasedNeuron::
do_detect_spike_or_whatever()
{
        if ( unlikely (E() >= M->options.spike_threshold) ) {
                if ( !(_spikelogger_agent->_status & CN_KL_ISSPIKINGNOW ) ) {
                        _spikelogger_agent->spike_history.push_back(
                                _spikelogger_agent->t_last_spike_start = model_time());
                        _spikelogger_agent->_status |= CN_KL_ISSPIKINGNOW;
                }
        } else
//                if ( model_time() - t_last_spike_end > M->spike_lapse ) {
                if ( _spikelogger_agent->_status & CN_KL_ISSPIKINGNOW ) {
                        _spikelogger_agent->_status &= ~CN_KL_ISSPIKINGNOW;
                        _spikelogger_agent->t_last_spike_end = model_time();
                }
}








// SPECIFIC NEURONS:

// ===== HH and variations

const char* const cnrun::CN_ParamNames_NeuronHH_d[] = {
        "Na conductance, " CN_PU_CONDUCTANCE,
        "Na equi potential, " CN_PU_POTENTIAL,
        "K conductance, " CN_PU_CONDUCTANCE,
        "K equi potential, " CN_PU_POTENTIAL,
        "Leak conductance, " CN_PU_CONDUCTANCE,
        "Leak equi potential, " CN_PU_POTENTIAL,
        "Membrane specific capacitance, " CN_PU_CAPACITY_DENSITY,

        ".alpha_m_a",        ".alpha_m_b",        ".alpha_m_c",        ".beta_m_a",        ".beta_m_b",        ".beta_m_c",
        ".alpha_h_a",        ".alpha_h_b",        ".alpha_h_c",        ".beta_h_a",        ".beta_h_b",        ".beta_h_c",
        ".alpha_n_a",        ".alpha_n_b",        ".alpha_n_c",        ".beta_n_a",        ".beta_n_b",        ".beta_n_c",

        "Externally applied DC, " CN_PU_CURRENT,
};
const char* const cnrun::CN_ParamSyms_NeuronHH_d[] = {
        "gNa",
        "ENa",
        "gK",
        "EK",
        "gl",
        "El",
        "Cmem",

        ".alpha_m_a",        ".alpha_m_b",        ".alpha_m_c",        ".beta_m_a",        ".beta_m_b",        ".beta_m_c",
        ".alpha_h_a",        ".alpha_h_b",        ".alpha_h_c",        ".beta_h_a",        ".beta_h_b",        ".beta_h_c",
        ".alpha_n_a",        ".alpha_n_b",        ".alpha_n_c",        ".beta_n_a",        ".beta_n_b",        ".beta_n_c",

        "Idc",
};
const double cnrun::CN_Params_NeuronHH_d[] = {
        7.15,   //   gNa: Na conductance in 1/(mOhms * cm^2)
       50.0,    //   ENa: Na equi potential in mV
        1.430,  //   gK: K conductance in 1/(mOhms * cm^2)
      -95.0,    //   EK: K equi potential in mV
        0.0267, //   gl: leak conductance in 1/(mOhms * cm^2)
      -63.563,  //   El: leak equi potential in mV
        0.143,  //   Cmem: membr. specific capacitance, muF/cm^2

        0.32,   52.,   4.,
        0.28,   25.,   5.,
        0.128,  48.,  18.,
        4.0,    25.,   5.,
        0.032,  50.,   5.,
        0.5,    55.,  40.,

          0.                // Externally applied constant current
};




const double cnrun::CN_Vars_NeuronHH_d[] = {
        -66.81,         // 0 - membrane potential E
          0.023,        // 1 - prob. for Na channel activation m
          0.800,        // 2 - prob. for not Na channel blocking h
          0.220,        // 3 - prob. for K channel activation n
};

const char* const cnrun::CN_VarNames_NeuronHH_d[] = {
        "Membrane potential, " CN_PU_POTENTIAL,
        "Prob. of Na channel activation",
        "1-Prob. of Na channel blocking",
        "Prob. of K channel activation",
};
const char* const cnrun::CN_VarSyms_NeuronHH_d[] = {
        "E",
        ".m",
        ".h",
        ".n"
};



void
__attribute__ ((hot))
cnrun::CNeuronHH_d::
derivative( vector<double>& x, vector<double>& dx)
{
      // differential eqn for E, the membrane potential
        dE(dx) = (
                     P[gNa] * gsl_pow_3(m(x)) * h(x) * (P[ENa] - E(x))
                   + P[gK]  * gsl_pow_4(n(x))        * (P[EK]  - E(x))
                   + P[gl]                           * (P[El]  - E(x)) + (Isyn(x) + P[Idc])
                  ) / P[Cmem];

        double _a, _b, K;
      // diferential eqn for m, the probability for one Na channel activation
      // particle
        K = -P[alpha_m_b] - E(x),
                _a = P[alpha_m_a] * K / expm1( K / P[alpha_m_c]);
//        _a = 0.32 * (13.0 - E(x) - P[V0]) / expm1( (13.0 - E(x) - P[V0]) / 4.0);
        K =  P[beta_m_b] + E(x),
                _b = P[beta_m_a]  * K / expm1( K / P[beta_m_c]);
//        _b = 0.28 * (E(x) + P[V0] - 40.0) / expm1( (E(x) + P[V0] - 40.0) / 5.0);
        dm(dx) = _a * (1 - m(x)) - _b * m(x);

      // differential eqn for h, the probability for the Na channel blocking
      // particle to be absent
        K = -P[alpha_h_b] - E(x),
                _a = P[alpha_h_a] * exp( K / P[alpha_h_c]);
//        _a = 0.128 * exp( (17.0 - E(x) - P[V0]) / 18.0);
        K = -P[beta_h_b] - E(x),
                _b = P[beta_h_a] / (exp( K / P[beta_h_c]) + 1);
//        _b = 4.0 / (exp( (40.0 - E(x) - P[V0]) / 5.0) + 1.0);
        dh(dx) = _a * (1 - h(x)) - _b * h(x);

      // differential eqn for n, the probability for one K channel activation
      // particle
        K = -P[alpha_n_b] - E(x),
                _a = P[alpha_n_a] * K / expm1( K / P[alpha_n_c]);
//        _a = 0.032 * (15.0 - E(x) - P[V0]) / (exp( (15.0 - E(x) - P[V0]) / 5.0) - 1.0);
        K = -P[beta_n_b] - E(x),
                _b = P[beta_n_a] * exp( K / P[beta_n_c]);
//        _b = 0.5 * exp( (10.0 - E(x) - P[V0]) / 40.0);
        dn(dx)= _a * (1 - n(x)) -_b * n(x);
}

// void
// CNeuronHH::derivative( vector<double>& x, vector<double>& dx)
// {
//        enum TParametersNeuronHH {
//                gNa, ENa, gK,  EK, gl, El, Cmem, Idc
//        };

//       // differential eqn for E, the membrane potential
//        dE(dx) = (
//                   P[gNa] * ___pow3(m(x)) * h(x) * (P[ENa] - E(x))
//                 + P[gK]  * ___pow4(n(x))        * (P[EK]  - E(x))
//                 + P[gl]  *                        (P[El]  - E(x))  + (Isyn(x) + P[Idc])
//                 ) / P[Cmem];

//        double _a, _b;
//       // diferential eqn for m, the probability for Na channel activation
//        _a = (3.5 + 0.1 * E(x)) / -expm1( -3.5 - 0.1 * E(x));
//        _b = 4.0 * exp( -(E(x) + 60.0) / 18.0);
//        dm(dx) = _a * (1.0 - m(x)) - _b * m(x);

//       // differential eqn for h, the probability for Na channel inactivation
//        _a = 0.07 * exp( -E(x) / 20.0 - 3.0);
//        _b = 1.0 / (exp( -3.0 - 0.1 * E(x)) + 1.0);
//        dh(dx) = _a * (1.0 - h(x)) -_b * h(x);

//       // differential eqn for n, the probability for K channel activation
//        _a = (-0.5 - 0.01 * E(x)) / expm1( -5.0 - 0.1 * E(x));
//        _b = 0.125 * exp( -(E(x) + 60.0) / 80.0);
//        dn(dx) = _a * (1.0 - n(x)) - _b * n(x);
// }








const char* const cnrun::CN_ParamNames_NeuronHH2_d[] = {
        "Na conductance, " CN_PU_CONDUCTANCE,
        "Na equi potential, " CN_PU_POTENTIAL,
        "K conductance, " CN_PU_CONDUCTANCE,
        "K equi potential, " CN_PU_POTENTIAL,
        "Leak conductance, " CN_PU_CONDUCTANCE,
        "Leak equi potential, " CN_PU_POTENTIAL,
        "Membrane specific capacitance, " CN_PU_CAPACITY_DENSITY,
        "K leakage conductance, " CN_PU_CONDUCTANCE,
        "K leakage equi potential, " CN_PU_POTENTIAL,

        ".alpha_m_a",        ".alpha_m_b",        ".alpha_m_c",        ".beta_m_a",        ".beta_m_b",        ".beta_m_c",
        ".alpha_h_a",        ".alpha_h_b",        ".alpha_h_c",        ".beta_h_a",        ".beta_h_b",        ".beta_h_c",
        ".alpha_n_a",        ".alpha_n_b",        ".alpha_n_c",        ".beta_n_a",        ".beta_n_b",        ".beta_n_c",

//        "Total equi potential (?), " CN_PU_POTENTIAL,

        "Externally applied DC, " CN_PU_CURRENT,
};
const char* const cnrun::CN_ParamSyms_NeuronHH2_d[] = {
        "gNa",
        "ENa",
        "gK",
        "EK",
        "gl",
        "El",
        "Cmem",
        "gKl",
        "EKl",

        ".alpha_m_a",        ".alpha_m_b",        ".alpha_m_c",        ".beta_m_a",        ".beta_m_b",        ".beta_m_c",
        ".alpha_h_a",        ".alpha_h_b",        ".alpha_h_c",        ".beta_h_a",        ".beta_h_b",        ".beta_h_c",
        ".alpha_n_a",        ".alpha_n_b",        ".alpha_n_c",        ".beta_n_a",        ".beta_n_b",        ".beta_n_c",

//        "V0",

        "Idc",
};
const double cnrun::CN_Params_NeuronHH2_d[] = {
        7.15,    //   gNa: Na conductance in 1/(mOhms * cm^2)
       50.0,     //   ENa: Na equi potential in mV
        1.43,    //   gK: K conductance in 1/(mOhms * cm^2)
      -95.0,     //   EK: K equi potential in mV
        0.0267,  //   gl: leak conductance in 1/(mOhms * cm^2)
      -63.56,    //   El: leak equi potential in mV
        0.143,   //   Cmem: membr. specific capacitance, muF/cm^2
        0.00572, //   gKl: potassium leakage conductivity
      -95.0,     //   EKl: potassium leakage equi pot in mV

        0.32,   52.,   4.,
        0.28,   25.,   5.,
        0.128,  48.,  18.,
        4.0,    25.,   5.,
        0.032,  50.,   5.,
        0.5,    55.,  40.,

//       65.0,                //   V0: ~ total equi potential (?)

        0.,                //   Idc: constant, externally applied current
};


const double cnrun::CN_Vars_NeuronHH2_d[] = {
// as in a single-neuron run
      -66.56,   // 0 - membrane potential E
        0.0217, // 1 - prob. for Na channel activation m
        0.993,  // 2 - prob. for not Na channel blocking h
        0.051,  // 3 - prob. for K channel activation n

// previously thought to be resting state values
//      -60.0,              // 0 - membrane potential E
//        0.0529324,        // 1 - prob. for Na channel activation m
//        0.3176767,        // 2 - prob. for not Na channel blocking h
//        0.5961207,        // 3 - prob. for K channel activation n
};





void
cnrun::CNeuronHH2_d::
derivative( vector<double>& x, vector<double>& dx)
{
        enum TParametersNeuronHH2 {
                gNa, ENa, gK,  EK, gl, El, Cmem,
                gKl, EKl, //V0,
                alpha_m_a,        alpha_m_b,        alpha_m_c,
                beta_m_a,        beta_m_b,        beta_m_c,
                alpha_h_a,        alpha_h_b,        alpha_h_c,
                beta_h_a,        beta_h_b,        beta_h_c,
                alpha_n_a,        alpha_n_b,        alpha_n_c,
                beta_n_a,        beta_n_b,        beta_n_c,
                Idc,
        };

      // differential eqn for E, the membrane potential
        dE(dx) = (
                     P[gNa] * gsl_pow_3(m(x)) * h(x) * (P[ENa] - E(x))
                   + P[gK]  * gsl_pow_4(n(x))        * (P[EK]  - E(x))
                   + P[gl]                           * (P[El]  - E(x))
                   + P[gKl]                          * (P[EKl] - E(x)) + (Isyn(x) + P[Idc])
                  ) / P[Cmem];

        double _a, _b, K;
      // diferential eqn for m, the probability for one Na channel activation
      // particle
        K = -P[alpha_m_b] - E(x),
                _a = P[alpha_m_a] * K / expm1( K / P[alpha_m_c]);
//        _a = 0.32 * (13.0 - E(x) - P[V0]) / expm1( (13.0 - E(x) - P[V0]) / 4.0);
        K =  P[beta_m_b] + E(x),
                _b = P[beta_m_a]  * K / expm1( K / P[beta_m_c]);
//        _b = 0.28 * (E(x) + P[V0] - 40.0) / expm1( (E(x) + P[V0] - 40.0) / 5.0);
        dm(dx) = _a * (1 - m(x)) - _b * m(x);

      // differential eqn for h, the probability for the Na channel blocking
      // particle to be absent
        K = -P[alpha_h_b] - E(x),
                _a = P[alpha_h_a] * exp( K / P[alpha_h_c]);
//        _a = 0.128 * exp( (17.0 - E(x) - P[V0]) / 18.0);
        K = -P[beta_h_b] - E(x),
                _b = P[beta_h_a] / (exp( K / P[beta_h_c]) + 1);
//        _b = 4.0 / (exp( (40.0 - E(x) - P[V0]) / 5.0) + 1.0);
        dh(dx) = _a * (1 - h(x)) - _b * h(x);

      // differential eqn for n, the probability for one K channel activation
      // particle
        K = -P[alpha_n_b] - E(x),
                _a = P[alpha_n_a] * K / expm1( K / P[alpha_n_c]);
//        _a = 0.032 * (15.0 - E(x) - P[V0]) / (exp( (15.0 - E(x) - P[V0]) / 5.0) - 1.0);
        K = -P[beta_n_b] - E(x),
                _b = P[beta_n_a] * exp( K / P[beta_n_c]);
//        _b = 0.5 * exp( (10.0 - E(x) - P[V0]) / 40.0);
        dn(dx)= _a * (1 - n(x)) -_b * n(x);
}








//#ifdef CN_WANT_MORE_NEURONS


const char* const cnrun::CN_ParamNames_NeuronEC_d[] = {
        "Na conductance, " CN_PU_CONDUCTANCE,
        "Na equi potential, " CN_PU_POTENTIAL,
        "K conductance, " CN_PU_CONDUCTANCE,
        "K equi potential, " CN_PU_POTENTIAL,
        "Leak conductance, " CN_PU_CONDUCTANCE,
        "Leak equi potential, " CN_PU_POTENTIAL,
        "Membrane capacity density, " CN_PU_CAPACITY_DENSITY,
        "Externally applied DC, " CN_PU_CURRENT,
        "K leakage conductance, " CN_PU_CONDUCTANCE,
        "K leakage equi potential, " CN_PU_POTENTIAL,
        "Total equi potential, " CN_PU_POTENTIAL,
        "gh1",
        "gh2",
        "Vh, " CN_PU_POTENTIAL
};
const char* const cnrun::CN_ParamSyms_NeuronEC_d[] = {
        "gNa",
        "ENa",
        "gK",
        "EK",
        "gl",
        "El",
        "Cmem",
        "Idc",
        "gKl",
        "EKl",
        "V0",
        "gh1",
        "gh2",
        "Vh"
};
const double cnrun::CN_Params_NeuronEC_d[] = {
        7.15,   //  0 - gNa: Na conductance in 1/(mOhms * cm^2)
       50.0,    //  1 - ENa: Na equi potential in mV
        1.43,   //  2 - gK: K conductance in 1/(mOhms * cm^2)
      -95.0,    //  3 - EK: K equi potential in mV
        0.021,  //  4 - gl: leak conductance in 1/(mOhms * cm^2)
      -55.0,    //  5 - El: leak equi potential in mV
        0.286,  //  6 - Cmem: membr. capacity density in muF/cm^2 // 0.143
        0.,     //  7 - Externally applied constant current
        0.035,  //  8 - gKl: potassium leakage conductivity
      -95.0,    //  9 - EKl: potassium leakage equi pot in mV
       65.0,    // 10 - V0: ~ total equi potential (?)
        0.0185, // 11 - gh1 // 1.85
        0.01,   // 12 - gh2
      -20.0,    // 13 - Vh
};

const char* const cnrun::CN_VarNames_NeuronEC_d[] = {
        "Membrane potential",
        "Prob. of Na channel activation",
        "Prob. of not Na channel blocking",
        "Prob. of K channel activation",
        "Ih1 activation",
        "Ih2 activation"
};
const char* const cnrun::CN_VarSyms_NeuronEC_d[] = {
        "E",
        ".m",
        ".h",
        ".n",
        ".Ih1",
        ".Ih2"
};
const double cnrun::CN_Vars_NeuronEC_d[] = {
      -64.1251,    // 0 - membrane potential E
        0.0176331, // 1 - prob. for Na channel activation m
        0.994931,  // 2 - prob. for not Na channel blocking h
        0.0433969, // 3 - prob. for K channel activation n
        0.443961,  // 4 - Ih1 activation
        0.625308   // 5 - Ih2 activation
};




#define _xfunc(a,b,k,V)  ((a) * (V) + (b)) / (1.0 - exp(((V)+(b)/(a))/(k)))

void
cnrun::CNeuronEC_d::
derivative( vector<double>& x, vector<double>& dx)
{
        enum TParametersNeuronEC {
                gNa, ENa, gK,  EK, gl, El, Cmem, Idc,
                gKl, EKl, V0,
                gh1, gh2,
                Vh
        };

        double _a, _b;
      // differential eqn for E, the membrane potential
        dE(dx) = -(gsl_pow_3( m(x)) * h(x) * P[gNa] * (E(x) - P[ENa]) +
                 gsl_pow_4( n(x)) * P[gK] * (E(x) - P[EK]) +
                 (Ih1(x) * P[gh1] + Ih2(x) * P[gh2]) * (E(x) - P[Vh])+
                 P[gl] * (E(x) - P[El]) + P[gKl] * (E(x) - P[EKl]) - Isyn(x)) / P[Cmem];

      // diferential eqn for m, the probability for one Na channel activation particle
        _a = 0.32 * (13.0 - E(x) - P[V0]) / expm1( (13.0 - E(x) - P[V0]) / 4.0);
        _b = 0.28 * (E(x) + P[V0] - 40.0) / expm1( (E(x) + P[V0] - 40.0) / 5.0);
        dm(dx) = _a * (1.0 - m(x)) - _b * m(x);

      // differential eqn for h, the probability for the Na channel blocking particle to be absent
        _a = 0.128 * exp( (17.0 - E(x) - P[V0]) / 18.0);
        _b = 4.0 / (exp( (40.0 - E(x) - P[V0]) / 5.0) + 1.0);
        dh(dx) = _a * (1.0 - h(x)) - _b * h(x);

      // differential eqn for n, the probability for one K channel activation particle
        _a = 0.032 * (15.0 - E(x) - P[V0]) / expm1( (15.0 - E(x) - P[V0]) / 5.0);
        _b = 0.5 * exp( (10.0 - E(x) - P[V0]) / 40.0);
        dn(dx) = _a * (1.0 - n(x)) - _b * n(x);

      // differential equation for the Ih1 activation variable
        _a = _xfunc (-2.89e-3, -0.445,  24.02, E(x));
        _b = _xfunc ( 2.71e-2, -1.024, -17.40, E(x));
        dIh1(dx) = _a * (1.0 - Ih1(x)) - _b * Ih1(x);

      // differential equation for the Ih2 activation variable
        _a = _xfunc (-3.18e-3, -0.695,  26.72, E(x));
        _b = _xfunc ( 2.16e-2, -1.065, -14.25, E(x));
        dIh2(dx) = _a * (1.0 - Ih2(x)) - _b * Ih2(x);
}

#undef _xfunc












const char* const cnrun::CN_ParamNames_NeuronECA_d[] = {
        "Na conductance, " CN_PU_CONDUCTANCE,
        "Na equi potential, " CN_PU_POTENTIAL,
        "K conductance, " CN_PU_CONDUCTANCE,
        "K equi potential, " CN_PU_POTENTIAL,
        "Leak conductance, " CN_PU_CONDUCTANCE,
        "Leak equi potential, " CN_PU_POTENTIAL,
        "Membrane capacity density, " CN_PU_CAPACITY_DENSITY,
        "Externally applied DC, " CN_PU_CURRENT,
        "gNap",
        "gh",
        "Vh",
};
const char* const cnrun::CN_ParamSyms_NeuronECA_d[] = {
        "gNa",
        "ENa",
        "gK",
        "EK",
        "gl",
        "El",
        "Cmem",
        "Idc",
        "gNap",
        "gh",
        "Vh",
};
const double cnrun::CN_Params_NeuronECA_d[] = {
        52.0,        //  0 - Na conductance in 1/(mOhms * cm^2)
        55.0,        //  1 - Na equi potential in mV
        11.0,        //  2 - K conductance in 1/(mOhms * cm^2)
       -90.0,        //  3 - K equi potential in mV
         0.5,        //  4 - Leak conductance in 1/(mOhms * cm^2)
       -65.0,        //  5 - Leak equi potential in mV
         1.5,        //  6 - Membr. capacity density in muF/cm^2
         0.,         //  7 - Externally applied constant current
         0.5,        //  8 - gNap
         1.5,        //  9 - gh
       -20.0,        // 10 - Vh
};

const char* const cnrun::CN_VarNames_NeuronECA_d[] = {
        "Membrane potential",
        "Prob. of Na channel activation",
        "Prob. of Na channel blocking",
        "Prob. of K channel activation",
        "mNap",
        "Ih1 activation",
        "Ih2 activation"
};
const char* const cnrun::CN_VarSyms_NeuronECA_d[] = {
        "E",
        ".m",
        ".h",
        ".n",
        ".mNap",
        ".Ih1",
        ".Ih2"
};
const double cnrun::CN_Vars_NeuronECA_d[] = {
      -53.77902178,    // E
        0.0262406368,  // prob. for Na channel activation m
        0.9461831106,  // prob. for not Na channel blocking h
        0.1135915933,  // prob. for K channel activation n
        0.08109646237, // Nap
        0.06918464221, // Ih1 activation
        0.09815937825  // Ih2 activation
};



void
cnrun::CNeuronECA_d::
derivative( vector<double>& x, vector<double>& dx)
{
        enum TParametersNeuronECA {  // lacks SParametersNeuronEC's gKl and EKl, so derives directly from HH
                gNa, ENa, gK,  EK, gl, El, Cmem, Idc,
                gNap, gh,
                Vh
        };

      // differential eqn for E, the membrane potential
        dE(dx) = -((gsl_pow_3( m(x)) * h(x) * P[gNa] + P[gNap] * mNap(x)) * (E(x) - P[ENa]) +
                   gsl_pow_4( n(x)) * P[gK] * (E(x) - P[EK]) +
                   P[gh] * (Ih1(x) * 0.65 + Ih2(x) * 0.35) * (E(x) - P[Vh]) +
                   P[gl] * (E(x) - P[El]) - (Isyn(x) + P[Idc]) + 2.85) / P[Cmem];

        double _a, _b;
      // diferential eqn for m, the probability for one Na channel activation particle
        _a = -0.1 * (E(x) + 23) / expm1( -0.1 * (E(x) + 23));
        _b =  4.  * exp( -(E(x) + 48) / 18);
        dm(dx) = _a * (1. - m(x)) - _b * m(x);

      // differential eqn for h, the probability for the Na channel blocking particle to be absent
        _a = 0.07 * exp( -(E(x) + 37.0) / 20.0);
        _b = 1. / (exp( -0.1 * (E(x) + 7.)) + 1.0);
        dh(dx) = _a * (1.0 - h(x)) - _b * h(x);

      // differential eqn for n, the probability for one K channel activation particle
        _a = -0.01  * (E(x) + 27) / expm1( -0.1 * (E(x) + 27));
        _b =  0.125 * exp( -(E(x) + 37) / 80);
        dn(dx) = _a * (1.0 - n(x)) - _b * n(x);

        _a = 1. / (0.15 * (1 + exp( -(E(x) + 38) / 6.5)));
        _b = exp( -(E(x) + 38) / 6.5) / (0.15 * (1 + exp( -(E(x) + 38) / 6.5)));
        dmNap(dx) = _a * (1.0 - mNap(x)) - _b * mNap(x);

      // differential equation for the Ihf activation variable
        _a = 1. / (1 + exp( (E(x) + 79.2) / 9.78));
        _b = 0.51 / (exp( (E(x) - 1.7) / 10) + exp( -(E(x) + 340) / 52)) + 1;
        dIh1(dx) = (_a - Ih1(x)) / _b;

      // differential equation for the Ihs activation variable
        _a = 1. / (1 + exp( (E(x) + 71.3) / 7.9));
        _b = 5.6 / (exp( (E(x) - 1.7) / 14) + exp( -(E(x) + 260) / 43)) + 1;
        dIh2(dx) = (_a - Ih2(x)) / _b;
}




// =========== oscillators

const char* const cnrun::CN_ParamNames_OscillatorColpitts[] = {
        "a",
        "g",
        "q",
        "η"
};
const char* const cnrun::CN_ParamSyms_OscillatorColpitts[] = {
        "a",
        "g",
        "q",
        "eta"
};
const double cnrun::CN_Params_OscillatorColpitts[] = {
        1.0,    // a
        0.0797, // g
        0.6898, // q
        6.2723  // eta
};


const char* const cnrun::CN_VarNames_OscillatorColpitts[] = {
        "x0",
        "x1",
        "x2"
};
const char* const cnrun::CN_VarSyms_OscillatorColpitts[] = {
        "x0",
        "x1",
        "x2"
};
const double cnrun::CN_Vars_OscillatorColpitts[] = {
        0.02,
        0.69,
       -0.53
};


void
cnrun::COscillatorColpitts::
derivative( vector<double>& x, vector<double>& dx)
{
        enum TParametersOscilColpitts {
                a, g, q,
                eta
        };

        dx0(dx) =  P[a]   *  x1(x) + Isyn(x);
        dx1(dx) = -P[g]   * (x0(x) + x2(x)) - P[q] * x1(x);
        dx2(dx) =  P[eta] * (x1(x) + 1.0 - exp( -x0(x)));
//        dx[idx  ] =  p[0] *  x[idx+1] + Isyn;
//        dx[idx+1] = -p[1] * (x[idx  ] + x[idx+2]) - p[2] * x[idx+1];
//        dx[idx+2] =  p[3] * (x[idx+1] + 1.0 - exp(-x[idx]));
}






/*

const char* const CN_ParamNames_OscillatorLV[] = {
        "Self inhibition",
};
const char* const CN_ParamSyms_OscillatorLV[] = {
        "rho_ii",
};
const double CN_Params_OscillatorLV[] = {
        1.0,        // 0 - rho_ii: "self inhibition"
};


const char* const CN_VarNames_OscillatorLV[] = {
        "Membrane potential, " CN_PU_POTENTIAL,
        "Firing rate"
};
const char* const CN_VarSyms_OscillatorLV[] = {
        "E",
        "fr"
};
const double CN_Vars_OscillatorLV[] = {
        0.,        // 0 - added a place for E
        0.1        // 1 - firing rate
};


*/







const char* const cnrun::CN_ParamNames_OscillatorVdPol[] = {
        "η",
        "ω²",
//        "\317\203"
};
const char* const cnrun::CN_ParamSyms_OscillatorVdPol[] = {
        "eta",
        "omegasq", // omega^2
//        "sigma"
};
const double cnrun::CN_Params_OscillatorVdPol[] = {
        1.0,        // eta
        0.1,        // omega^2
//        0.0        // noise level
};

const char* const cnrun::CN_VarNames_OscillatorVdPol[] = {
        "Amplitude",
        "v"
};
const char* const cnrun::CN_VarSyms_OscillatorVdPol[] = {
        "A",
        "v"
};
const double cnrun::CN_Vars_OscillatorVdPol[] = {
        0.1,       // amplitude
        0.0        // internal var
};


//#endif // CN_WANT_MORE_NEURONS

// Local Variables:
// Mode: c++
// indent-tabs-mode: nil
// tab-width: 8
// c-basic-offset: 8
// End:
