/*
* madexp_psc_alpha.cpp
*
* This file is part of NEST.
*
* Copyright (C) 2004 The NEST Initiative
*
* NEST is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* NEST is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NEST. If not, see <http://www.gnu.org/licenses/>.
*
* Generated from NESTML at time: 2021-09-17 08:49:05.363400
**/
// C++ includes:
#include <limits>
// Includes from libnestutil:
#include "numerics.h"
// Includes from nestkernel:
#include "exceptions.h"
#include "kernel_manager.h"
#include "universal_data_logger_impl.h"
// Includes from sli:
#include "dict.h"
#include "dictutils.h"
#include "doubledatum.h"
#include "integerdatum.h"
#include "lockptrdatum.h"
#include "madexp_psc_alpha.h"
// ---------------------------------------------------------------------------
// Recordables map
// ---------------------------------------------------------------------------
nest::RecordablesMap<madexp_psc_alpha> madexp_psc_alpha::recordablesMap_;
namespace nest
{
// Override the create() method with one call to RecordablesMap::insert_()
// for each quantity to be recorded.
template <> void RecordablesMap<madexp_psc_alpha>::create()
{
// add state variables to recordables map
insert_("epsilon", &madexp_psc_alpha::get_epsilon);
insert_("V_m", &madexp_psc_alpha::get_V_m);
insert_("w", &madexp_psc_alpha::get_w);
insert_("I_syn_ex__X__spikesExc", &madexp_psc_alpha::get_I_syn_ex__X__spikesExc);
insert_("I_syn_ex__X__spikesExc__d", &madexp_psc_alpha::get_I_syn_ex__X__spikesExc__d);
insert_("I_syn_in__X__spikesInh", &madexp_psc_alpha::get_I_syn_in__X__spikesInh);
insert_("I_syn_in__X__spikesInh__d", &madexp_psc_alpha::get_I_syn_in__X__spikesInh__d);
}
}
// ---------------------------------------------------------------------------
// Default constructors defining default parameters and state
// Note: the implementation is empty. The initialization is of variables
// is a part of madexp_psc_alpha's constructor.
// ---------------------------------------------------------------------------
madexp_psc_alpha::Parameters_::Parameters_()
{
}
madexp_psc_alpha::State_::State_()
{
}
// ---------------------------------------------------------------------------
// Parameter and state extractions and manipulation functions
// ---------------------------------------------------------------------------
madexp_psc_alpha::Buffers_::Buffers_(madexp_psc_alpha &n):
logger_(n)
, __s( 0 ), __c( 0 ), __e( 0 )
{
// Initialization of the remaining members is deferred to init_buffers_().
}
madexp_psc_alpha::Buffers_::Buffers_(const Buffers_ &, madexp_psc_alpha &n):
logger_(n)
, __s( 0 ), __c( 0 ), __e( 0 )
{
// Initialization of the remaining members is deferred to init_buffers_().
}
// ---------------------------------------------------------------------------
// Default constructor for node
// ---------------------------------------------------------------------------
madexp_psc_alpha::madexp_psc_alpha():ArchivingNode(), P_(), S_(), B_(*this)
{
recordablesMap_.create();
calibrate();
// use a default "good enough" value for the absolute error. It can be adjusted via `node.set()`
P_.__gsl_error_tol = 1e-3;
// initial values for parameters
P_.C_m = 100.0; // as pF
P_.g_L = 9.0; // as nS
P_.Delta_T = 1.0; // as mV
P_.V_peak = 0; // as mV
P_.E_0 = (-65.0); // as mV
P_.E_u = (-58.0); // as mV
P_.E_d = (-50.0); // as mV
P_.E_f = (-60.0); // as mV
P_.epsilon_0 = 0.5; // as real
P_.epsilon_c = 0.2; // as real
P_.alpha = 1.0; // as real
P_.delta = 0.1; // as real
P_.tau_e = 1000.0; // as ms
P_.I_e = 0.0; // as pA
P_.V_th = (-55.0); // as mV
P_.a = 1.0; // as nS
P_.b = 2.0; // as pA
P_.gamma = 1000.0; // as pA
P_.I_KATP = 10.0; // as pA
P_.tau_w = 300.0; // as ms
P_.V_reset = (-62.0); // as mV
P_.tau_syn_ex = 0.2; // as ms
P_.tau_syn_in = 2.0; // as ms
P_.t_ref = 2.0; // as ms
// initial values for state variables
S_.ode_state[State_::r] = 0; // as integer
S_.ode_state[State_::epsilon] = P_.alpha * P_.epsilon_0; // as real
S_.ode_state[State_::V_m] = P_.E_0 + ((-P_.E_0) + P_.E_u) * ((-S_.ode_state[State_::epsilon]) / P_.epsilon_0 + 1); // as mV
S_.ode_state[State_::w] = 0; // as pA
S_.ode_state[State_::I_syn_ex__X__spikesExc] = 0; // as real
S_.ode_state[State_::I_syn_ex__X__spikesExc__d] = 0; // as real
S_.ode_state[State_::I_syn_in__X__spikesInh] = 0; // as real
S_.ode_state[State_::I_syn_in__X__spikesInh__d] = 0; // as real
}
// ---------------------------------------------------------------------------
// Copy constructor for node
// ---------------------------------------------------------------------------
madexp_psc_alpha::madexp_psc_alpha(const madexp_psc_alpha& __n):
ArchivingNode(), P_(__n.P_), S_(__n.S_), B_(__n.B_, *this) {
// copy parameter struct P_
P_.C_m = __n.P_.C_m;
P_.g_L = __n.P_.g_L;
P_.Delta_T = __n.P_.Delta_T;
P_.V_peak = __n.P_.V_peak;
P_.E_0 = __n.P_.E_0;
P_.E_u = __n.P_.E_u;
P_.E_d = __n.P_.E_d;
P_.E_f = __n.P_.E_f;
P_.epsilon_0 = __n.P_.epsilon_0;
P_.epsilon_c = __n.P_.epsilon_c;
P_.alpha = __n.P_.alpha;
P_.delta = __n.P_.delta;
P_.tau_e = __n.P_.tau_e;
P_.I_e = __n.P_.I_e;
P_.V_th = __n.P_.V_th;
P_.a = __n.P_.a;
P_.b = __n.P_.b;
P_.gamma = __n.P_.gamma;
P_.I_KATP = __n.P_.I_KATP;
P_.tau_w = __n.P_.tau_w;
P_.V_reset = __n.P_.V_reset;
P_.tau_syn_ex = __n.P_.tau_syn_ex;
P_.tau_syn_in = __n.P_.tau_syn_in;
P_.t_ref = __n.P_.t_ref;
// copy state struct S_
S_.ode_state[State_::r] = __n.S_.ode_state[State_::r];
S_.ode_state[State_::epsilon] = __n.S_.ode_state[State_::epsilon];
S_.ode_state[State_::V_m] = __n.S_.ode_state[State_::V_m];
S_.ode_state[State_::w] = __n.S_.ode_state[State_::w];
S_.ode_state[State_::I_syn_ex__X__spikesExc] = __n.S_.ode_state[State_::I_syn_ex__X__spikesExc];
S_.ode_state[State_::I_syn_ex__X__spikesExc__d] = __n.S_.ode_state[State_::I_syn_ex__X__spikesExc__d];
S_.ode_state[State_::I_syn_in__X__spikesInh] = __n.S_.ode_state[State_::I_syn_in__X__spikesInh];
S_.ode_state[State_::I_syn_in__X__spikesInh__d] = __n.S_.ode_state[State_::I_syn_in__X__spikesInh__d];
S_.ode_state[State_::r] = __n.S_.ode_state[State_::r];
S_.ode_state[State_::epsilon] = __n.S_.ode_state[State_::epsilon];
S_.ode_state[State_::V_m] = __n.S_.ode_state[State_::V_m];
S_.ode_state[State_::w] = __n.S_.ode_state[State_::w];
S_.ode_state[State_::I_syn_ex__X__spikesExc] = __n.S_.ode_state[State_::I_syn_ex__X__spikesExc];
S_.ode_state[State_::I_syn_ex__X__spikesExc__d] = __n.S_.ode_state[State_::I_syn_ex__X__spikesExc__d];
S_.ode_state[State_::I_syn_in__X__spikesInh] = __n.S_.ode_state[State_::I_syn_in__X__spikesInh];
S_.ode_state[State_::I_syn_in__X__spikesInh__d] = __n.S_.ode_state[State_::I_syn_in__X__spikesInh__d];
// copy internals V_
V_.RefractoryCounts = __n.V_.RefractoryCounts;
V_.__h = __n.V_.__h;
V_.invae = __n.V_.invae;
V_.inveps = __n.V_.inveps;
V_.invEdEf = __n.V_.invEdEf;
V_.invte = __n.V_.invte;
V_.invCm = __n.V_.invCm;
V_.invDT = __n.V_.invDT;
V_.invtw = __n.V_.invtw;
V_.invgamma = __n.V_.invgamma;
V_.invtau_syn_in = __n.V_.invtau_syn_in;
V_.invtau_syn_ex = __n.V_.invtau_syn_ex;
V_.Vspike = __n.V_.Vspike;
V_.__P__I_syn_ex__X__spikesExc__I_syn_ex__X__spikesExc = __n.V_.__P__I_syn_ex__X__spikesExc__I_syn_ex__X__spikesExc;
V_.__P__I_syn_ex__X__spikesExc__I_syn_ex__X__spikesExc__d = __n.V_.__P__I_syn_ex__X__spikesExc__I_syn_ex__X__spikesExc__d;
V_.__P__I_syn_ex__X__spikesExc__d__I_syn_ex__X__spikesExc = __n.V_.__P__I_syn_ex__X__spikesExc__d__I_syn_ex__X__spikesExc;
V_.__P__I_syn_ex__X__spikesExc__d__I_syn_ex__X__spikesExc__d = __n.V_.__P__I_syn_ex__X__spikesExc__d__I_syn_ex__X__spikesExc__d;
V_.__P__I_syn_in__X__spikesInh__I_syn_in__X__spikesInh = __n.V_.__P__I_syn_in__X__spikesInh__I_syn_in__X__spikesInh;
V_.__P__I_syn_in__X__spikesInh__I_syn_in__X__spikesInh__d = __n.V_.__P__I_syn_in__X__spikesInh__I_syn_in__X__spikesInh__d;
V_.__P__I_syn_in__X__spikesInh__d__I_syn_in__X__spikesInh = __n.V_.__P__I_syn_in__X__spikesInh__d__I_syn_in__X__spikesInh;
V_.__P__I_syn_in__X__spikesInh__d__I_syn_in__X__spikesInh__d = __n.V_.__P__I_syn_in__X__spikesInh__d__I_syn_in__X__spikesInh__d;
}
// ---------------------------------------------------------------------------
// Destructor for node
// ---------------------------------------------------------------------------
madexp_psc_alpha::~madexp_psc_alpha()
{
// GSL structs may not have been allocated, so we need to protect destruction
if (B_.__s)
{
gsl_odeiv_step_free( B_.__s );
}
if (B_.__c)
{
gsl_odeiv_control_free( B_.__c );
}
if (B_.__e)
{
gsl_odeiv_evolve_free( B_.__e );
}
}
// ---------------------------------------------------------------------------
// Node initialization functions
// ---------------------------------------------------------------------------
void madexp_psc_alpha::init_buffers_()
{
get_spikesInh().clear(); //includes resize
get_spikesExc().clear(); //includes resize
get_currents().clear(); //includes resize
B_.logger_.reset(); // includes resize
ArchivingNode::clear_history();
if ( B_.__s == 0 )
{
B_.__s = gsl_odeiv_step_alloc( gsl_odeiv_step_rkf45, 8 );
}
else
{
gsl_odeiv_step_reset( B_.__s );
}
if ( B_.__c == 0 )
{
B_.__c = gsl_odeiv_control_y_new( P_.__gsl_error_tol, 0.0 );
}
else
{
gsl_odeiv_control_init( B_.__c, P_.__gsl_error_tol, 0.0, 1.0, 0.0 );
}
if ( B_.__e == 0 )
{
B_.__e = gsl_odeiv_evolve_alloc( 8 );
}
else
{
gsl_odeiv_evolve_reset( B_.__e );
}
B_.__sys.function = madexp_psc_alpha_dynamics;
B_.__sys.jacobian = NULL;
B_.__sys.dimension = 8;
B_.__sys.params = reinterpret_cast< void* >( this );
B_.__step = nest::Time::get_resolution().get_ms();
B_.__integration_step = nest::Time::get_resolution().get_ms();
}
void madexp_psc_alpha::calibrate()
{
B_.logger_.init();
// internals V_
V_.RefractoryCounts =nest::Time(nest::Time::ms((double) (P_.t_ref))).get_steps();
V_.__h =nest::Time::get_resolution().get_ms();
V_.invae =1.0 / (P_.alpha * P_.epsilon_0);
V_.inveps =1.0 / P_.epsilon_0;
V_.invEdEf =1.0 / (P_.E_d - P_.E_f);
V_.invte =1.0 / P_.tau_e;
V_.invCm =1.0 / P_.C_m;
V_.invDT =1.0 / P_.Delta_T;
V_.invtw =1.0 / P_.tau_w;
V_.invgamma =1.0 / P_.gamma;
V_.invtau_syn_in =1.0 / P_.tau_syn_in;
V_.invtau_syn_ex =1.0 / P_.tau_syn_ex;
V_.Vspike =(P_.Delta_T==0) ? (std::min(P_.V_th, P_.V_peak)) : (P_.V_peak);
V_.__P__I_syn_ex__X__spikesExc__I_syn_ex__X__spikesExc =1.0 * (V_.__h * V_.invtau_syn_ex + 1) * std::exp((-V_.__h) * V_.invtau_syn_ex);
V_.__P__I_syn_ex__X__spikesExc__I_syn_ex__X__spikesExc__d =1.0 * V_.__h * std::exp((-V_.__h) * V_.invtau_syn_ex);
V_.__P__I_syn_ex__X__spikesExc__d__I_syn_ex__X__spikesExc =(-1.0) * V_.__h * pow(V_.invtau_syn_ex, 2) * std::exp((-V_.__h) * V_.invtau_syn_ex);
V_.__P__I_syn_ex__X__spikesExc__d__I_syn_ex__X__spikesExc__d =1.0 * ((-V_.__h) * V_.invtau_syn_ex + 1) * std::exp((-V_.__h) * V_.invtau_syn_ex);
V_.__P__I_syn_in__X__spikesInh__I_syn_in__X__spikesInh =1.0 * (V_.__h * V_.invtau_syn_in + 1) * std::exp((-V_.__h) * V_.invtau_syn_in);
V_.__P__I_syn_in__X__spikesInh__I_syn_in__X__spikesInh__d =1.0 * V_.__h * std::exp((-V_.__h) * V_.invtau_syn_in);
V_.__P__I_syn_in__X__spikesInh__d__I_syn_in__X__spikesInh =(-1.0) * V_.__h * pow(V_.invtau_syn_in, 2) * std::exp((-V_.__h) * V_.invtau_syn_in);
V_.__P__I_syn_in__X__spikesInh__d__I_syn_in__X__spikesInh__d =1.0 * ((-V_.__h) * V_.invtau_syn_in + 1) * std::exp((-V_.__h) * V_.invtau_syn_in);
// state S_
// buffers B_
}
// ---------------------------------------------------------------------------
// Functions defined in the NESTML model
// ---------------------------------------------------------------------------
//
double madexp_psc_alpha::I_spike(double epsilon, double V_m) const
{
double Ispk = 0.0;
double arg_exp = 0.0;
if (P_.Delta_T>0.0)
{
arg_exp = std::min(20.0, std::max((-20.0), (V_m - P_.V_th) * V_.invDT));
Ispk = (epsilon - P_.epsilon_c) * P_.g_L * P_.Delta_T * std::exp(arg_exp) * V_.inveps;
}
return Ispk;
}
// ---------------------------------------------------------------------------
// Update and spike handling functions
// ---------------------------------------------------------------------------
extern "C" inline int madexp_psc_alpha_dynamics(double, const double ode_state[], double f[], void* pnode)
{
typedef madexp_psc_alpha::State_ State_;
// get access to node so we can almost work as in a member function
assert( pnode );
const madexp_psc_alpha& node = *( reinterpret_cast< madexp_psc_alpha* >( pnode ) );
// ode_state[] here is---and must be---the state vector supplied by the integrator,
// not the state vector in the node, node.S_.ode_state[].
f[State_::V_m] = node.get_g_L() * (node.get_E_0() * node.get_invCm() * node.get_inveps() * std::max(0.0, ode_state[State_::epsilon]) - node.get_E_u() * node.get_invCm() * node.get_inveps() * std::max(0.0, ode_state[State_::epsilon]) + node.get_E_u() * node.get_invCm() - node.get_invCm() * std::min(ode_state[State_::V_m], node.get_V_peak())) + node.get_invCm() * (node.get_I_e() + ode_state[State_::I_syn_ex__X__spikesExc] + ode_state[State_::I_syn_in__X__spikesInh] + node.B_.currents_grid_sum_ - ode_state[State_::w] + node.I_spike(std::max(0.0, ode_state[State_::epsilon]), std::min(ode_state[State_::V_m], node.get_V_peak())));
f[State_::w] = node.get_E_0() * (-(node.get_a()) * node.get_epsilon_c() * node.get_inveps() * node.get_invtw() * std::max(0.0, ode_state[State_::epsilon]) / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])) - 2 * node.get_a() * node.get_inveps() * node.get_invtw() * pow(std::max(0.0, ode_state[State_::epsilon]), 2) / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon]))) + node.get_invtw() * (node.get_E_u() * node.get_a() * node.get_epsilon_c() * node.get_inveps() * std::max(0.0, ode_state[State_::epsilon]) / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])) - node.get_E_u() * node.get_a() * node.get_epsilon_c() / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])) + 2 * node.get_E_u() * node.get_a() * node.get_inveps() * pow(std::max(0.0, ode_state[State_::epsilon]), 2) / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])) - 2 * node.get_E_u() * node.get_a() * std::max(0.0, ode_state[State_::epsilon]) / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])) + node.get_I_KATP() * node.get_epsilon_c() / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])) + node.get_a() * node.get_epsilon_c() * std::min(ode_state[State_::V_m], node.get_V_peak()) / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])) + 2 * node.get_a() * std::max(0.0, ode_state[State_::epsilon]) * std::min(ode_state[State_::V_m], node.get_V_peak()) / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])) - node.get_epsilon_c() * ode_state[State_::w] / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])) - 2 * ode_state[State_::w] * std::max(0.0, ode_state[State_::epsilon]) / (node.get_epsilon_c() + 2 * std::max(0.0, ode_state[State_::epsilon])));
f[State_::epsilon] = node.get_invEdEf() * (node.get_E_f() * node.get_invte() - node.get_invte() * std::min(ode_state[State_::V_m], node.get_V_peak())) - pow(node.get_invae(), 3) * node.get_invte() * pow(std::max(0.0, ode_state[State_::epsilon]), 3) + 3 * pow(node.get_invae(), 2) * node.get_invte() * pow(std::max(0.0, ode_state[State_::epsilon]), 2) - 3 * node.get_invae() * node.get_invte() * std::max(0.0, ode_state[State_::epsilon]) + node.get_invte() * (-(node.get_invgamma()) * ode_state[State_::w] + 1);
f[State_::I_syn_ex__X__spikesExc] = 1.0 * ode_state[State_::I_syn_ex__X__spikesExc__d];
f[State_::I_syn_ex__X__spikesExc__d] = -(ode_state[State_::I_syn_ex__X__spikesExc]) * pow(node.get_invtau_syn_ex(), 2) - 2 * ode_state[State_::I_syn_ex__X__spikesExc__d] * node.get_invtau_syn_ex();
f[State_::I_syn_in__X__spikesInh] = 1.0 * ode_state[State_::I_syn_in__X__spikesInh__d];
f[State_::I_syn_in__X__spikesInh__d] = -(ode_state[State_::I_syn_in__X__spikesInh]) * pow(node.get_invtau_syn_in(), 2) - 2 * ode_state[State_::I_syn_in__X__spikesInh__d] * node.get_invtau_syn_in();
f[State_::r] = 0.;
return GSL_SUCCESS;
}
void madexp_psc_alpha::update(nest::Time const & origin,const long from, const long to)
{
double __t = 0;
for ( long lag = from ; lag < to ; ++lag )
{
B_.spikesInh_grid_sum_ = get_spikesInh().get_value(lag);
B_.spikesExc_grid_sum_ = get_spikesExc().get_value(lag);
B_.currents_grid_sum_ = get_currents().get_value(lag);
// NESTML generated code for the update block:
double I_syn_ex__X__spikesExc__tmp = S_.ode_state[State_::I_syn_ex__X__spikesExc] * V_.__P__I_syn_ex__X__spikesExc__I_syn_ex__X__spikesExc + S_.ode_state[State_::I_syn_ex__X__spikesExc__d] * V_.__P__I_syn_ex__X__spikesExc__I_syn_ex__X__spikesExc__d;
double I_syn_ex__X__spikesExc__d__tmp = S_.ode_state[State_::I_syn_ex__X__spikesExc] * V_.__P__I_syn_ex__X__spikesExc__d__I_syn_ex__X__spikesExc + S_.ode_state[State_::I_syn_ex__X__spikesExc__d] * V_.__P__I_syn_ex__X__spikesExc__d__I_syn_ex__X__spikesExc__d;
double I_syn_in__X__spikesInh__tmp = S_.ode_state[State_::I_syn_in__X__spikesInh] * V_.__P__I_syn_in__X__spikesInh__I_syn_in__X__spikesInh + S_.ode_state[State_::I_syn_in__X__spikesInh__d] * V_.__P__I_syn_in__X__spikesInh__I_syn_in__X__spikesInh__d;
double I_syn_in__X__spikesInh__d__tmp = S_.ode_state[State_::I_syn_in__X__spikesInh] * V_.__P__I_syn_in__X__spikesInh__d__I_syn_in__X__spikesInh + S_.ode_state[State_::I_syn_in__X__spikesInh__d] * V_.__P__I_syn_in__X__spikesInh__d__I_syn_in__X__spikesInh__d;
__t = 0;
// numerical integration with adaptive step size control:
// ------------------------------------------------------
// gsl_odeiv_evolve_apply performs only a single numerical
// integration step, starting from t and bounded by step;
// the while-loop ensures integration over the whole simulation
// step (0, step] if more than one integration step is needed due
// to a small integration step size;
// note that (t+IntegrationStep > step) leads to integration over
// (t, step] and afterwards setting t to step, but it does not
// enforce setting IntegrationStep to step-t; this is of advantage
// for a consistent and efficient integration across subsequent
// simulation intervals
while ( __t < B_.__step )
{
const int status = gsl_odeiv_evolve_apply(B_.__e,
B_.__c,
B_.__s,
&B_.__sys, // system of ODE
&__t, // from t
B_.__step, // to t <= step
&B_.__integration_step, // integration step size
S_.ode_state); // neuronal state
if ( status != GSL_SUCCESS )
{
throw nest::GSLSolverFailure( get_name(), status );
}
}
/* replace analytically solvable variables with precisely integrated values */
S_.ode_state[State_::I_syn_ex__X__spikesExc] = I_syn_ex__X__spikesExc__tmp;
S_.ode_state[State_::I_syn_ex__X__spikesExc__d] = I_syn_ex__X__spikesExc__d__tmp;
S_.ode_state[State_::I_syn_in__X__spikesInh] = I_syn_in__X__spikesInh__tmp;
S_.ode_state[State_::I_syn_in__X__spikesInh__d] = I_syn_in__X__spikesInh__d__tmp;
S_.ode_state[State_::I_syn_ex__X__spikesExc__d] += (B_.spikesExc_grid_sum_) * (numerics::e * V_.invtau_syn_ex) / (1.0);
S_.ode_state[State_::I_syn_in__X__spikesInh__d] += (B_.spikesInh_grid_sum_) * (numerics::e * V_.invtau_syn_in) / (1.0);
if (S_.ode_state[State_::epsilon]<0.0)
{
S_.ode_state[State_::epsilon] = 0.0;
}
if (S_.ode_state[State_::r]>0)
{
S_.ode_state[State_::r] -= 1;
S_.ode_state[State_::V_m] = P_.V_reset;
}
else if (S_.ode_state[State_::V_m]>=V_.Vspike&&S_.ode_state[State_::epsilon]>P_.epsilon_c)
{
S_.ode_state[State_::V_m] = P_.V_reset;
S_.ode_state[State_::epsilon] -= P_.delta;
S_.ode_state[State_::w] += P_.b;
set_spiketime(nest::Time::step(origin.get_steps()+lag+1));
nest::SpikeEvent se;
nest::kernel().event_delivery_manager.send(*this, se, lag);
S_.ode_state[State_::r] = V_.RefractoryCounts;
}
// voltage logging
B_.logger_.record_data(origin.get_steps() + lag);
}
}
// Do not move this function as inline to h-file. It depends on
// universal_data_logger_impl.h being included here.
void madexp_psc_alpha::handle(nest::DataLoggingRequest& e)
{
B_.logger_.handle(e);
}
void madexp_psc_alpha::handle(nest::SpikeEvent &e)
{
assert(e.get_delay_steps() > 0);
const double weight = e.get_weight();
const double multiplicity = e.get_multiplicity();
if ( weight < 0.0 )
{
// inhibitory
get_spikesInh().
add_value(e.get_rel_delivery_steps( nest::kernel().simulation_manager.get_slice_origin()),
weight * multiplicity );
}
if ( weight >= 0.0 )
{
// excitatory
get_spikesExc().
add_value(e.get_rel_delivery_steps( nest::kernel().simulation_manager.get_slice_origin()),
weight * multiplicity );
}
}
void madexp_psc_alpha::handle(nest::CurrentEvent& e)
{
assert(e.get_delay_steps() > 0);
const double current = e.get_current(); // we assume that in NEST, this returns a current in pA
const double weight = e.get_weight();
get_currents().add_value(
e.get_rel_delivery_steps( nest::kernel().simulation_manager.get_slice_origin()),
weight * current );
}