void ht_neuron::update( Time const& origin, const long_t from, const long_t to ) { assert( to >= 0 && ( delay ) from < Scheduler::get_min_delay() ); assert( from < to ); for ( long_t lag = from; lag < to; ++lag ) { double tt = 0.0; // it's all relative! // adaptive step integration while ( tt < B_.step_ ) { const int status = gsl_odeiv_evolve_apply( B_.e_, B_.c_, B_.s_, &B_.sys_, // system of ODE &tt, // from t... B_.step_, // ...to t=t+h &B_.IntegrationStep_, // integration window (written on!) S_.y_ ); // neuron state if ( status != GSL_SUCCESS ) throw GSLSolverFailure( get_name(), status ); } // Deactivate potassium current after spike time have expired if ( S_.r_potassium_ && --S_.r_potassium_ == 0 ) S_.g_spike_ = false; // Deactivate potassium current. // Add new spikes to node state array for ( size_t i = 0; i < B_.spike_inputs_.size(); ++i ) S_.y_[ 2 + 2 * i ] += V_.cond_steps_[ i ] * B_.spike_inputs_[ i ].get_value( lag ); // A spike is generated when the membrane potential (V) exceeds // the threshold (Theta). if ( !S_.g_spike_ && S_.y_[ State_::VM ] >= S_.y_[ State_::THETA ] ) { // Set V and Theta to the sodium reversal potential. S_.y_[ State_::VM ] = P_.E_Na; S_.y_[ State_::THETA ] = P_.E_Na; // Activate fast potassium current. Drives the // membrane potential towards the potassium reversal // potential (activate only if duration is non-zero). S_.g_spike_ = V_.PotassiumRefractoryCounts_ > 0; S_.r_potassium_ = V_.PotassiumRefractoryCounts_; set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; network()->send( *this, se, lag ); } // set new input current B_.I_stim_ = B_.currents_.get_value( lag ); B_.logger_.record_data( origin.get_steps() + lag ); } }
/* ---------------------------------------------------------------- * Update and spike handling functions * ---------------------------------------------------------------- */ void nest::hh_cond_exp_traub::update( Time const& origin, const long_t from, const long_t to ) { assert( to >= 0 && ( delay ) from < kernel().connection_builder_manager.get_min_delay() ); assert( from < to ); for ( long_t lag = from; lag < to; ++lag ) { double tt = 0.0; // it's all relative! V_.U_old_ = S_.y_[ State_::V_M ]; // adaptive step integration while ( tt < B_.step_ ) { const int status = gsl_odeiv_evolve_apply( B_.e_, B_.c_, B_.s_, &B_.sys_, // system of ODE &tt, // from t... B_.step_, // ...to t=t+h &B_.IntegrationStep_, // integration window (written on!) S_.y_ ); // neuron state if ( status != GSL_SUCCESS ) throw GSLSolverFailure( get_name(), status ); } S_.y_[ State_::G_EXC ] += B_.spike_exc_.get_value( lag ); S_.y_[ State_::G_INH ] += B_.spike_inh_.get_value( lag ); // sending spikes: crossing 0 mV, pseudo-refractoriness and local maximum... // refractory? if ( S_.r_ ) { --S_.r_; } else { // (threshold && maximum ) if ( S_.y_[ State_::V_M ] >= P_.V_T + 30. && V_.U_old_ > S_.y_[ State_::V_M ] ) { S_.r_ = V_.RefractoryCounts_; set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } } // set new input current B_.I_stim_ = B_.currents_.get_value( lag ); // log state data B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::iaf_cond_alpha::update( Time const& origin, const long from, const long to ) { assert( to >= 0 && ( delay ) from < kernel().connection_manager.get_min_delay() ); assert( from < to ); for ( long lag = from; lag < to; ++lag ) { double t = 0.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_.IntegrationStep_, // integration step size S_.y ); // neuronal state if ( status != GSL_SUCCESS ) { throw GSLSolverFailure( get_name(), status ); } } // refractoriness and spike generation if ( S_.r ) { // neuron is absolute refractory --S_.r; S_.y[ State_::V_M ] = P_.V_reset; // clamp potential } else // neuron is not absolute refractory if ( S_.y[ State_::V_M ] >= P_.V_th ) { S_.r = V_.RefractoryCounts; S_.y[ State_::V_M ] = P_.V_reset; // log spike with Archiving_Node set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } // add incoming spikes S_.y[ State_::DG_EXC ] += B_.spike_exc_.get_value( lag ) * V_.PSConInit_E; S_.y[ State_::DG_INH ] += B_.spike_inh_.get_value( lag ) * V_.PSConInit_I; // set new input current B_.I_stim_ = B_.currents_.get_value( lag ); // log state data B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::iaf_cond_exp::update( Time const& origin, const long_t from, const long_t to ) { assert( to >= 0 && ( delay ) from < Scheduler::get_min_delay() ); assert( from < to ); for ( long_t lag = from; lag < to; ++lag ) { double t = 0.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_.IntegrationStep_, // integration step size S_.y_ ); // neuronal state if ( status != GSL_SUCCESS ) throw GSLSolverFailure( get_name(), status ); } S_.y_[ State_::G_EXC ] += B_.spike_exc_.get_value( lag ); S_.y_[ State_::G_INH ] += B_.spike_inh_.get_value( lag ); // absolute refractory period if ( S_.r_ ) { // neuron is absolute refractory --S_.r_; S_.y_[ State_::V_M ] = P_.V_reset_; } else // neuron is not absolute refractory if ( S_.y_[ State_::V_M ] >= P_.V_th_ ) { S_.r_ = V_.RefractoryCounts_; S_.y_[ State_::V_M ] = P_.V_reset_; set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; network()->send( *this, se, lag ); } // set new input current B_.I_stim_ = B_.currents_.get_value( lag ); // log state data B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::aeif_cond_exp::update(const Time &origin, const long_t from, const long_t to) { assert ( to >= 0 && (delay) from < Scheduler::get_min_delay() ); assert ( from < to ); assert ( State_::V_M == 0 ); for ( long_t lag = from; lag < to; ++lag ) { double t = 0.0; if ( S_.r_ > 0 ) --S_.r_; // 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 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_.IntegrationStep_, // integration step size S_.y_); // neuronal state if ( status != GSL_SUCCESS ) throw GSLSolverFailure(get_name(), status); // check for unreasonable values; we allow V_M to explode if ( S_.y_[State_::V_M] < -1e3 || S_.y_[State_::W ] < -1e6 || S_.y_[State_::W] > 1e6 ) throw NumericalInstability(get_name()); // spikes are handled inside the while-loop // due to spike-driven adaptation if ( S_.r_ > 0 ) S_.y_[State_::V_M] = P_.V_reset_; else if ( S_.y_[State_::V_M] >= P_.V_peak_ ) { S_.y_[State_::V_M] = P_.V_reset_; S_.y_[State_::W] += P_.b; // spike-driven adaptation S_.r_ = V_.RefractoryCounts_; set_spiketime(Time::step(origin.get_steps() + lag + 1)); SpikeEvent se; network()->send(*this, se, lag); } } S_.y_[State_::G_EXC] += B_.spike_exc_.get_value(lag); S_.y_[State_::G_INH] += B_.spike_inh_.get_value(lag); // set new input current B_.I_stim_ = B_.currents_.get_value(lag); // log state data B_.logger_.record_data(origin.get_steps() + lag); } }
void nest::iaf_cond_alpha_mc::update( Time const& origin, const long from, const long to ) { assert( to >= 0 && ( delay ) from < kernel().connection_manager.get_min_delay() ); assert( from < to ); for ( long lag = from; lag < to; ++lag ) { double t = 0.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_.IntegrationStep_, // integration step size S_.y_ ); // neuronal state if ( status != GSL_SUCCESS ) { throw GSLSolverFailure( get_name(), status ); } } // add incoming spikes at end of interval // exploit here that spike buffers are compartment for compartment, // alternating between excitatory and inhibitory for ( size_t n = 0; n < NCOMP; ++n ) { S_.y_[ n * State_::STATE_VEC_COMPS + State_::DG_EXC ] += B_.spikes_[ 2 * n ].get_value( lag ) * V_.PSConInit_E_[ n ]; S_.y_[ n * State_::STATE_VEC_COMPS + State_::DG_INH ] += B_.spikes_[ 2 * n + 1 ].get_value( lag ) * V_.PSConInit_I_[ n ]; } // refractoriness and spiking // exploit here that plain offset enum value V_M indexes soma V_M if ( S_.r_ ) { // neuron is absolute refractory --S_.r_; S_.y_[ State_::V_M ] = P_.V_reset; } else if ( S_.y_[ State_::V_M ] >= P_.V_th ) { // neuron fires spike S_.r_ = V_.RefractoryCounts_; S_.y_[ State_::V_M ] = P_.V_reset; set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } // set new input currents for ( size_t n = 0; n < NCOMP; ++n ) { B_.I_stim_[ n ] = B_.currents_[ n ].get_value( lag ); } // log state data B_.logger_.record_data( origin.get_steps() + lag ); } }
bool nest::hh_psc_alpha_gap::update_( Time const& origin, const long from, const long to, const bool wfr_update ) { assert( to >= 0 && ( delay ) from < kernel().connection_manager.get_min_delay() ); assert( from < to ); bool done = true; const size_t interpolation_order = kernel().simulation_manager.get_wfr_interpolation_order(); const double wfr_tol = kernel().simulation_manager.get_wfr_tol(); // allocate memory to store the new interpolation coefficients // to be sent by gap event const size_t quantity = kernel().connection_manager.get_min_delay() * ( interpolation_order + 1 ); std::vector< double > new_coefficients( quantity, 0.0 ); // parameters needed for piecewise interpolation double y_i = 0.0, y_ip1 = 0.0, hf_i = 0.0, hf_ip1 = 0.0; double f_temp[ State_::STATE_VEC_SIZE ]; for ( long lag = from; lag < to; ++lag ) { // B_.lag is needed by hh_psc_alpha_gap_dynamics to // determine the current section B_.lag_ = lag; if ( wfr_update ) { y_i = S_.y_[ State_::V_M ]; if ( interpolation_order == 3 ) { hh_psc_alpha_gap_dynamics( 0, S_.y_, f_temp, reinterpret_cast< void* >( this ) ); hf_i = B_.step_ * f_temp[ State_::V_M ]; } } double t = 0.0; const double U_old = S_.y_[ State_::V_M ]; // 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_.IntegrationStep_, // integration step size S_.y_ ); // neuronal state if ( status != GSL_SUCCESS ) throw GSLSolverFailure( get_name(), status ); } if ( not wfr_update ) { S_.y_[ State_::DI_EXC ] += B_.spike_exc_.get_value( lag ) * V_.PSCurrInit_E_; S_.y_[ State_::DI_INH ] += B_.spike_inh_.get_value( lag ) * V_.PSCurrInit_I_; // sending spikes: crossing 0 mV, pseudo-refractoriness and local // maximum... // refractory? if ( S_.r_ > 0 ) --S_.r_; else // ( threshold && maximum ) if ( S_.y_[ State_::V_M ] >= 0 && U_old > S_.y_[ State_::V_M ] ) { S_.r_ = V_.RefractoryCounts_; set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } // log state data B_.logger_.record_data( origin.get_steps() + lag ); // set new input current B_.I_stim_ = B_.currents_.get_value( lag ); } else // if(wfr_update) { S_.y_[ State_::DI_EXC ] += B_.spike_exc_.get_value_wfr_update( lag ) * V_.PSCurrInit_E_; S_.y_[ State_::DI_INH ] += B_.spike_inh_.get_value_wfr_update( lag ) * V_.PSCurrInit_I_; // check deviation from last iteration done = ( fabs( S_.y_[ State_::V_M ] - B_.last_y_values[ lag ] ) <= wfr_tol ) && done; B_.last_y_values[ lag ] = S_.y_[ State_::V_M ]; // update different interpolations // constant term is the same for each interpolation order new_coefficients[ lag * ( interpolation_order + 1 ) + 0 ] = y_i; switch ( interpolation_order ) { case 0: break; case 1: y_ip1 = S_.y_[ State_::V_M ]; new_coefficients[ lag * ( interpolation_order + 1 ) + 1 ] = y_ip1 - y_i; break; case 3: y_ip1 = S_.y_[ State_::V_M ]; hh_psc_alpha_gap_dynamics( B_.step_, S_.y_, f_temp, reinterpret_cast< void* >( this ) ); hf_ip1 = B_.step_ * f_temp[ State_::V_M ]; new_coefficients[ lag * ( interpolation_order + 1 ) + 1 ] = hf_i; new_coefficients[ lag * ( interpolation_order + 1 ) + 2 ] = -3 * y_i + 3 * y_ip1 - 2 * hf_i - hf_ip1; new_coefficients[ lag * ( interpolation_order + 1 ) + 3 ] = 2 * y_i - 2 * y_ip1 + hf_i + hf_ip1; break; default: throw BadProperty( "Interpolation order must be 0, 1, or 3." ); } } } // end for-loop // if !wfr_update perform constant extrapolation and reset last_y_values if ( not wfr_update ) { for ( long temp = from; temp < to; ++temp ) new_coefficients[ temp * ( interpolation_order + 1 ) + 0 ] = S_.y_[ State_::V_M ]; B_.last_y_values.clear(); B_.last_y_values.resize( kernel().connection_manager.get_min_delay(), 0.0 ); } // Send gap-event GapJunctionEvent ge; ge.set_coeffarray( new_coefficients ); kernel().event_delivery_manager.send_secondary( *this, ge ); // Reset variables B_.sumj_g_ij_ = 0.0; B_.interpolation_coefficients.clear(); B_.interpolation_coefficients.resize( quantity, 0.0 ); return done; }
void nest::aeif_psc_alpha::update( Time const& origin, const long from, const long to ) { assert( to >= 0 && ( delay ) from < kernel().connection_manager.get_min_delay() ); assert( from < to ); assert( State_::V_M == 0 ); for ( long lag = from; lag < to; ++lag ) { double t = 0.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_.IntegrationStep_, // integration step size S_.y_ ); // neuronal state if ( status != GSL_SUCCESS ) { throw GSLSolverFailure( get_name(), status ); } // check for unreasonable values; we allow V_M to explode if ( S_.y_[ State_::V_M ] < -1e3 || S_.y_[ State_::W ] < -1e6 || S_.y_[ State_::W ] > 1e6 ) { throw NumericalInstability( get_name() ); } // spikes are handled inside the while-loop // due to spike-driven adaptation if ( S_.r_ > 0 ) { S_.y_[ State_::V_M ] = P_.V_reset_; } else if ( S_.y_[ State_::V_M ] >= V_.V_peak ) { S_.y_[ State_::V_M ] = P_.V_reset_; S_.y_[ State_::W ] += P_.b; // spike-driven adaptation /* Initialize refractory step counter. * - We need to add 1 to compensate for count-down immediately after * while loop. * - If neuron has no refractory time, set to 0 to avoid refractory * artifact inside while loop. */ S_.r_ = V_.refractory_counts_ > 0 ? V_.refractory_counts_ + 1 : 0; set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } } // decrement refractory count if ( S_.r_ > 0 ) { --S_.r_; } // apply spikes S_.y_[ State_::DI_EXC ] += B_.spike_exc_.get_value( lag ) * V_.i0_ex_; S_.y_[ State_::DI_INH ] += B_.spike_inh_.get_value( lag ) * V_.i0_in_; // set new input current B_.I_stim_ = B_.currents_.get_value( lag ); // log state data B_.logger_.record_data( origin.get_steps() + lag ); } }