void nest::pif_psc_delta_canon_cvv::emit_spike_(Time const &origin, const long_t lag, const double_t offset_U) { assert(S_.U_ >= P_.U_th_); // ensure we are superthreshold // compute time since threhold crossing double_t dt = P_.c_m_ * (S_.U_ - P_.U_th_) / P_.I_e_; // set stamp and offset for spike set_spiketime(Time::step(origin.get_steps() + lag + 1)); S_.last_spike_offset_ = offset_U + dt; // reset neuron and make it refractory // if we are in emit_spike, the crossing was due to DC input, so threshold was exactly reached S_.U_t_spike_plus_ = P_.U_th_; S_.U_ = P_.U_reset_; S_.is_refractory_ = true; // send spike SpikeEvent se; se.set_offset(S_.last_spike_offset_); network()->send(*this, se, lag); return; }
void nest::iaf_psc_delta_canon::emit_spike_( Time const& origin, const long lag, const double offset_U ) { assert( S_.U_ >= P_.U_th_ ); // ensure we are superthreshold // compute time since threshold crossing const double v_inf = V_.R_ * ( S_.I_ + P_.I_e_ ); const double dt = -P_.tau_m_ * std::log( ( v_inf - S_.U_ ) / ( v_inf - P_.U_th_ ) ); // set stamp and offset for spike S_.last_spike_step_ = origin.get_steps() + lag + 1; S_.last_spike_offset_ = offset_U + dt; // reset neuron and make it refractory S_.U_ = P_.U_reset_; S_.is_refractory_ = true; // send spike set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; se.set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); return; }
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 ); } }
void nest::amat2_psc_exp::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 ); // evolve from timestep 'from' to timestep 'to' with steps of h each for ( long_t lag = from; lag < to; ++lag ) { // evolve voltage dependency (6,7) S_.V_th_v_ = ( P_.I_e_ + S_.i_0_ ) * V_.P70_ + S_.i_syn_ex_ * V_.P71_ + S_.i_syn_in_ * V_.P72_ + S_.V_m_ * V_.P73_ + S_.V_th_dv_ * V_.P76_ + S_.V_th_v_ * V_.P77_; S_.V_th_dv_ = ( P_.I_e_ + S_.i_0_ ) * V_.P60_ + S_.i_syn_ex_ * V_.P61_ + S_.i_syn_in_ * V_.P62_ + S_.V_m_ * V_.P63_ + S_.V_th_dv_ * V_.P66_; // evolve membrane potential (3) S_.V_m_ = ( P_.I_e_ + S_.i_0_ ) * V_.P30_ + S_.i_syn_ex_ * V_.P31_ + S_.i_syn_in_ * V_.P32_ + S_.V_m_ * V_.P33_; // evolve adaptive threshold (4,5) S_.V_th_1_ *= V_.P44_; S_.V_th_2_ *= V_.P55_; // exponential decaying PSCs (1,2) S_.i_syn_ex_ *= V_.P11_; S_.i_syn_in_ *= V_.P22_; S_.i_syn_ex_ += B_.spikes_ex_.get_value( lag ); // the spikes arriving at T+1 have an S_.i_syn_in_ += B_.spikes_in_.get_value( lag ); // the spikes arriving at T+1 have an if ( S_.r_ == 0 ) // neuron is allowed to fire { if ( S_.V_m_ >= P_.omega_ + S_.V_th_2_ + S_.V_th_1_ + S_.V_th_v_ ) // threshold crossing { S_.r_ = V_.RefractoryCountsTot_; // procedure for adaptive potential S_.V_th_1_ += P_.alpha_1_; // short time S_.V_th_2_ += P_.alpha_2_; // long time set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } } else --S_.r_; // neuron is totally refractory (cannot generate spikes) // set new input current S_.i_0_ = B_.currents_.get_value( lag ); // log state data 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::izhikevich::update( Time const& origin, const long from, const long to ) { assert( to >= 0 && ( delay ) from < kernel().connection_manager.get_min_delay() ); assert( from < to ); const double h = Time::get_resolution().get_ms(); double v_old, u_old; for ( long lag = from; lag < to; ++lag ) { // neuron is never refractory // use standard forward Euler numerics in this case if ( P_.consistent_integration_ ) { v_old = S_.v_; u_old = S_.u_; S_.v_ += h * ( 0.04 * v_old * v_old + 5.0 * v_old + 140.0 - u_old + S_.I_ + P_.I_e_ ) + B_.spikes_.get_value( lag ); S_.u_ += h * P_.a_ * ( P_.b_ * v_old - u_old ); } // use numerics published in Izhikevich (2003) in this case (not // recommended) else { double I_syn = B_.spikes_.get_value( lag ); S_.v_ += h * 0.5 * ( 0.04 * S_.v_ * S_.v_ + 5.0 * S_.v_ + 140.0 - S_.u_ + S_.I_ + P_.I_e_ + I_syn ); S_.v_ += h * 0.5 * ( 0.04 * S_.v_ * S_.v_ + 5.0 * S_.v_ + 140.0 - S_.u_ + S_.I_ + P_.I_e_ + I_syn ); S_.u_ += h * P_.a_ * ( P_.b_ * S_.v_ - S_.u_ ); } // lower bound of membrane potential S_.v_ = ( S_.v_ < P_.V_min_ ? P_.V_min_ : S_.v_ ); // threshold crossing if ( S_.v_ >= P_.V_th_ ) { S_.v_ = P_.c_; S_.u_ = S_.u_ + P_.d_; // compute spike time set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } // set new input current S_.I_ = B_.currents_.get_value( lag ); // voltage logging B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::iaf_psc_delta::update( Time const& origin, const long_t from, const long_t to ) { assert( to >= 0 && ( delay ) from < Scheduler::get_min_delay() ); assert( from < to ); const double_t h = Time::get_resolution().get_ms(); for ( long_t lag = from; lag < to; ++lag ) { if ( S_.r_ == 0 ) { // neuron not refractory S_.y3_ = V_.P30_ * ( S_.y0_ + P_.I_e_ ) + V_.P33_ * S_.y3_ + B_.spikes_.get_value( lag ); // if we have accumulated spikes from refractory period, // add and reset accumulator if ( P_.with_refr_input_ && S_.refr_spikes_buffer_ != 0.0 ) { S_.y3_ += S_.refr_spikes_buffer_; S_.refr_spikes_buffer_ = 0.0; } // lower bound of membrane potential S_.y3_ = ( S_.y3_ < P_.V_min_ ? P_.V_min_ : S_.y3_ ); } else // neuron is absolute refractory { // read spikes from buffer and accumulate them, discounting // for decay until end of refractory period if ( P_.with_refr_input_ ) S_.refr_spikes_buffer_ += B_.spikes_.get_value( lag ) * std::exp( -S_.r_ * h / P_.tau_m_ ); else B_.spikes_.get_value( lag ); // clear buffer entry, ignore spike --S_.r_; } // threshold crossing if ( S_.y3_ >= P_.V_th_ ) { S_.r_ = V_.RefractoryCounts_; S_.y3_ = P_.V_reset_; // EX: must compute spike time set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; network()->send( *this, se, lag ); } // set new input current S_.y0_ = B_.currents_.get_value( lag ); // voltage logging B_.logger_.record_data( origin.get_steps() + lag ); } }
void iaf_psc_alpha_multisynapse::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 ) { if ( S_.r_ == 0 ) { // neuron not refractory S_.y3_ = V_.P30_ * ( S_.y0_ + P_.I_e_ ) + V_.P33_ * S_.y3_; S_.current_ = 0.0; for ( size_t i = 0; i < P_.num_of_receptors_; i++ ) { S_.y3_ += V_.P31_syn_[ i ] * S_.y1_syn_[ i ] + V_.P32_syn_[ i ] * S_.y2_syn_[ i ]; S_.current_ += S_.y2_syn_[ i ]; } // lower bound of membrane potential S_.y3_ = ( S_.y3_ < P_.LowerBound_ ? P_.LowerBound_ : S_.y3_ ); } else // neuron is absolute refractory --S_.r_; for ( size_t i = 0; i < P_.num_of_receptors_; i++ ) { // alpha shape PSCs S_.y2_syn_[ i ] = V_.P21_syn_[ i ] * S_.y1_syn_[ i ] + V_.P22_syn_[ i ] * S_.y2_syn_[ i ]; S_.y1_syn_[ i ] *= V_.P11_syn_[ i ]; // collect spikes S_.y1_syn_[ i ] += V_.PSCInitialValues_[ i ] * B_.spikes_[ i ].get_value( lag ); } if ( S_.y3_ >= P_.Theta_ ) // threshold crossing { S_.r_ = V_.RefractoryCounts_; S_.y3_ = P_.V_reset_; // A supra-threshold membrane potential should never be observable. // The reset at the time of threshold crossing enables accurate integration // independent of the computation step size, see [2,3] for details. set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } // set new input current S_.y0_ = B_.currents_.get_value( lag ); // log state data B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::iaf_tum_2000::update( Time const& origin, const long from, const long to ) { assert( to >= 0 && ( delay ) from < kernel().connection_manager.get_min_delay() ); assert( from < to ); // evolve from timestep 'from' to timestep 'to' with steps of h each for ( long lag = from; lag < to; ++lag ) { if ( S_.r_abs_ == 0 ) // neuron not refractory, so evolve V { S_.V_m_ = S_.V_m_ * V_.P22_ + S_.i_syn_ex_ * V_.P21ex_ + S_.i_syn_in_ * V_.P21in_ + ( P_.I_e_ + S_.i_0_ ) * V_.P20_; } else { --S_.r_abs_; } // neuron is absolute refractory // exponential decaying PSCs S_.i_syn_ex_ *= V_.P11ex_; S_.i_syn_in_ *= V_.P11in_; // the spikes arriving at T+1 have an immediate effect on the // state of the neuron S_.i_syn_ex_ += B_.spikes_ex_.get_value( lag ); S_.i_syn_in_ += B_.spikes_in_.get_value( lag ); if ( S_.r_tot_ == 0 ) { if ( S_.V_m_ >= P_.Theta_ ) // threshold crossing { S_.r_abs_ = V_.RefractoryCountsAbs_; S_.r_tot_ = V_.RefractoryCountsTot_; S_.V_m_ = P_.V_reset_; set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } } else { --S_.r_tot_; } // neuron is totally refractory (cannot generate spikes) // set new input current S_.i_0_ = B_.currents_.get_value( lag ); // logging B_.logger_.record_data( origin.get_steps() + lag ); } }
void iaf_psc_exp_multisynapse::update( const Time& origin, const long from, const long to ) { assert( to >= 0 && ( delay ) from < kernel().connection_manager.get_min_delay() ); assert( from < to ); // evolve from timestep 'from' to timestep 'to' with steps of h each for ( long lag = from; lag < to; ++lag ) { if ( S_.refractory_steps_ == 0 ) // neuron not refractory, so evolve V { S_.V_m_ = S_.V_m_ * V_.P22_ + ( P_.I_e_ + S_.I_const_ ) * V_.P20_; // not sure about this S_.current_ = 0.0; for ( size_t i = 0; i < P_.n_receptors_(); i++ ) { S_.V_m_ += V_.P21_syn_[ i ] * S_.i_syn_[ i ]; S_.current_ += S_.i_syn_[ i ]; // not sure about this } } else { --S_.refractory_steps_; // neuron is absolute refractory } for ( size_t i = 0; i < P_.n_receptors_(); i++ ) { // exponential decaying PSCs S_.i_syn_[ i ] *= V_.P11_syn_[ i ]; // collect spikes S_.i_syn_[ i ] += B_.spikes_[ i ].get_value( lag ); // not sure about this } if ( S_.V_m_ >= P_.Theta_ ) // threshold crossing { S_.refractory_steps_ = V_.RefractoryCounts_; S_.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 current S_.I_const_ = B_.currents_.get_value( lag ); // log state data B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::iaf_neuron_dif_alpha_stdp::update(Time const & origin, const long_t from, const long_t to) { //bool ok=true; assert(to >= 0 && (delay) from < Scheduler::get_min_delay()); assert(from < to); const double_t h = Time::get_resolution().get_ms(); double_t v_old; double_t t=origin.get_ms(); //std::cout<<S_.v_<<"\t"; for ( long_t lag = from ; lag < to ; ++lag ) { if ( S_.r_ == 0 ) // neuron not refractory { v_old = S_.v_; //S_.v_ +=h*( ((P_.E_L_-v_old)/P_.Tau_) + (P_.I_e_/P_.C_) + (S_.I_/P_.C_) )+B_.spikes_.get_value(lag); S_.v_ +=h*( ((P_.E_L_-v_old)/P_.Tau_) + (P_.I_e_/P_.C_) + (S_.I_/P_.C_)) ; //std::cout<<"fun S_.I_="<<S_.I_<<"\t"<<"delta_V="<<h*(S_.I_/P_.C_)<<"\n"; } else // neuron is absolute refractory --S_.r_; // threshold crossing //std::cout<<"index "<<this->get_gid()<<" to "<<to<<"\t"<<"lag "<<lag<<"\t"<<"h "<<h<<"\n"; //if (emission_procedure(S_.v_)) if (S_.v_ >= P_.V_th_) { stdp_procedure(t+h*lag); //std::cout<<"spike_time"<<"\n"; //clean spike history S_.r_ = V_.RefractoryCounts_; S_.v_= P_.V_reset_; set_spiketime(Time::step(origin.get_steps()+lag)); // change -1 //std::cout<<"fun time spike from neuron "<<Time::step(origin.get_steps()+lag)<<"\n";// change -1 SpikeEvent se; //se.set_weight(-1.0); network()->send(*this, se, lag); clear_spike_history(t+h*lag); //ok=false; } //B_.spikes_.get_value(lag);// Need for clean buffer. It's necessary for working log-device wrapper. S_.I_=B_.currents_.get_value(lag); S_.I_ =S_.I_+get_sum_I(t+h*lag); // надо делать инач //std::cout<<"fun S_.I_="<<S_.I_<<"\n\n"; // voltage logging B_.logger_.record_data(origin.get_steps()+lag); } //std::cout<<"\n"; // delete after use }
void IzhikevichBranch::update(nest::Time const & origin, const nest::long_t from, const nest::long_t to) { assert(to >= 0 && (nest::delay) from < nest::Scheduler::get_min_delay()); assert(from < to); nest::long_t current_steps = origin.get_steps(); for (nest::long_t lag = from; lag < to; ++lag) { /***** Solve ODE over timestep *****/ B_.current_regime->step_ode(); /***** Transition handling *****/ // Get multiplicity incoming events for the current lag and reset multiplicity of outgoing events refresh_events(lag); Transition_* transition; int simultaneous_transition_count = 0; double prev_t = origin.get_ms(); while ((transition = B_.current_regime->transition(origin, lag))) { // Check for a transition (i.e. the output of current_regime->transition is not NULL) and record it in the 'transition' variable. double t = transition->time_occurred(origin, lag); // Get the exact time the transition occurred. if (t == prev_t) ++simultaneous_transition_count; else simultaneous_transition_count = 0; if (simultaneous_transition_count > MAX_SIMULTANEOUS_TRANSITIONS) throw ExceededMaximumSimultaneousTransitions("IzhikevichBranch", simultaneous_transition_count, t); bool discontinuous = transition->body(t) || (transition->get_target_regime() != B_.current_regime); B_.current_regime = transition->get_target_regime(); B_.current_regime->set_triggers(t); if (discontinuous) B_.current_regime->init_solver(); // Reset the solver if the transition contains state assignments or switches to a new regime. } /***** Send output events for each event send port *****/ // FIXME: Need to specify different output ports in a way that can be read by the receiving nodes // Output events if (B_.num_spike_events) { set_spiketime(nest::Time::step(origin.get_steps()+lag+1)); nest::SpikeEvent se; se.set_multiplicity(B_.num_spike_events); network()->send(*this, se, lag); } /***** Get analog port values *****/ B_.Isyn_value = B_.Isyn_analog_port.get_value(lag); /***** Record data *****/ B_.logger_.record_data(current_steps + lag); } }
void nest::sli_neuron::update( Time const& origin, const long_t from, const long_t to ) { assert( to >= 0 && ( delay ) from < kernel().connection_manager.get_min_delay() ); assert( from < to ); ( *state_ )[ names::t_origin ] = origin.get_steps(); if ( state_->known( names::error ) ) { std::string msg = String::compose( "Node %1 still has its error state set.", get_gid() ); LOG( M_ERROR, "sli_neuron::update", msg.c_str() ); LOG( M_ERROR, "sli_neuron::update", "Please check /calibrate and /update for errors" ); kernel().simulation_manager.terminate(); return; } for ( long_t lag = from; lag < to; ++lag ) { ( *state_ )[ names::in_spikes ] = B_.in_spikes_.get_value( lag ); // in spikes arriving at right border ( *state_ )[ names::ex_spikes ] = B_.ex_spikes_.get_value( lag ); // ex spikes arriving at right border ( *state_ )[ names::currents ] = B_.currents_.get_value( lag ); ( *state_ )[ names::t_lag ] = lag; #pragma omp critical( sli_neuron ) { execute_sli_protected( state_, names::update_node ); // call interpreter } bool spike_emission = false; if ( state_->known( names::spike ) ) spike_emission = ( *state_ )[ names::spike ]; // threshold crossing if ( spike_emission ) { set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::iaf_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 ) { if ( S_.r_ == 0 ) { // neuron not refractory S_.y3_ = V_.P30_ * ( S_.y0_ + P_.I_e_ ) + V_.P31_ * S_.y1_ + V_.P32_ * S_.y2_ + V_.P33_ * S_.y3_; } else // neuron is absolute refractory --S_.r_; // alpha shape PSCs S_.y2_ = V_.P21_ * S_.y1_ + V_.P22_ * S_.y2_; S_.y1_ *= V_.P11_; // Apply spikes delivered in this step: The spikes arriving at T+1 have an // immediate effect on the state of the neuron S_.y1_ += V_.PSCInitialValue_ * B_.spikes_.get_value( lag ); // threshold crossing if ( S_.y3_ >= P_.Theta_ ) { S_.r_ = V_.RefractoryCounts_; S_.y3_ = P_.V_reset_; // A supra-threshold membrane potential should never be observable. // The reset at the time of threshold crossing enables accurate integration // independent of the computation step size, see [2,3] for details. set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; network()->send( *this, se, lag ); } // set new input current S_.y0_ = B_.currents_.get_value( lag ); // voltage logging B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::iaf_psc_exp_ps::emit_instant_spike_(const Time & origin, const long_t lag, const double_t spike_offs) { assert( S_.y2_ >= P_.U_th_ ); // ensure we are superthreshold // set stamp and offset for spike set_spiketime(Time::step(origin.get_steps() + lag + 1)); S_.last_spike_offset_ = spike_offs; // reset neuron and make it refractory S_.y2_ = P_.U_reset_; S_.is_refractory_ = true; // send spike SpikeEvent se; se.set_offset(S_.last_spike_offset_); network()->send(*this, se, lag); }
void nest::iaf_chs_2007::update(const Time &origin, const long_t from, const long_t to) { assert(to >= 0 && (delay) from < Scheduler::get_min_delay()); assert(from < to); // evolve from timestep 'from' to timestep 'to' with steps of h each for ( long_t lag = from; lag < to; ++lag ) { S_.V_syn_ = S_.V_syn_*V_.P22_ + S_.i_syn_ex_*V_.P21ex_; // exponential decaying PSCs S_.i_syn_ex_ *= V_.P11ex_; // the spikes arriving at T+1 have an immediate effect on the state of the neuron S_.i_syn_ex_ += B_.spikes_ex_.get_value(lag); // exponentially decaying ahp S_.V_spike_ *= V_.P30_; double noise_term = P_.U_noise_ > 0.0 && !P_.noise_.empty() ? P_.U_noise_ * P_.noise_[S_.position_++] : 0.0; S_.V_m_ = S_.V_syn_ + S_.V_spike_ + noise_term; if ( S_.V_m_ >= P_.U_th_ ) // threshold crossing { S_.V_spike_ -= P_.U_reset_; S_.V_m_ -= P_.U_reset_; set_spiketime(Time::step(origin.get_steps()+lag+1)); SpikeEvent se; network()->send(*this, se, lag); } // log state data B_.logger_.record_data(origin.get_steps() + lag); } }
void parrot_neuron_ps::update( Time const& origin, long_t const from, long_t const to ) { assert( to >= 0 ); assert( static_cast< delay >( from ) < kernel().connection_manager.get_min_delay() ); assert( from < to ); // at start of slice, tell input queue to prepare for delivery if ( from == 0 ) B_.events_.prepare_delivery(); for ( long_t lag = from; lag < to; ++lag ) { // time at start of update step long_t const T = origin.get_steps() + lag; double_t ev_offset; double_t ev_multiplicity; // parrot stores multiplicity in weight bool end_of_refract; while ( B_.events_.get_next_spike( T, ev_offset, ev_multiplicity, end_of_refract ) ) { const ulong_t multiplicity = static_cast< ulong_t >( ev_multiplicity ); // send spike SpikeEvent se; se.set_multiplicity( multiplicity ); se.set_offset( ev_offset ); kernel().event_delivery_manager.send( *this, se, lag ); for ( ulong_t i = 0; i < multiplicity; ++i ) { set_spiketime( Time::step( T + 1 ), ev_offset ); } } } }
void nest::iaf_psc_exp_ps::emit_spike_(const Time & origin, const long_t lag, const double_t t0, const double_t dt) { // we know that the potential is subthreshold at t0, super at t0+dt // compute spike time relative to beginning of step const double_t spike_offset = V_.h_ms_ - (t0 + bisectioning_(dt)); set_spiketime(Time::step(origin.get_steps() + lag + 1)); S_.last_spike_offset_ = spike_offset; // reset neuron and make it refractory S_.y2_ = P_.U_reset_; S_.is_refractory_ = true; // send spike SpikeEvent se; se.set_offset(spike_offset); network()->send(*this, se, lag); }
void nest::iaf_psc_exp_canon::emit_spike_(Time const &origin, long_t const lag, double_t const t0, double_t const dt) { // we know that the potential is subthreshold at t0, super at t0+dt // compute spike time relative to beginning of step double_t const spike_offset = V_.h_ms_ - (t0+thresh_find_(dt)); set_spiketime(Time::step(origin.get_steps() + lag + 1)); S_.last_spike_offset_ = spike_offset; // reset neuron and make it refractory S_.y2_ = P_.U_reset_; S_.is_refractory_ = true; // send spike SpikeEvent se; se.set_offset(S_.last_spike_offset_); network()->send(*this, se, lag); return; }
void nest::iaf_cond_delta::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 ) { if ( S_.r_ == 0 ) { // neuron not refractory S_.V_m_ = V_.P_L_*S_.V_m_; S_.V_m_ += (P_.E_ex_ - S_.V_m_)*B_.spikes_ex_.get_value(lag) + (P_.E_in_ - S_.V_m_)*B_.spikes_in_.get_value(lag); } else // neuron is absolute refractory { B_.spikes_ex_.get_value(lag); // clear buffer entry, ignore spike B_.spikes_in_.get_value(lag); // clear buffer entry, ignore spike --S_.r_; } // threshold crossing if (S_.V_m_ >= P_.V_th_) { S_.r_ = V_.RefractoryCounts_; S_.V_m_ = P_.V_reset_; // EX: must compute spike time set_spiketime(Time::step(origin.get_steps()+lag+1)); SpikeEvent se; network()->send(*this, se, lag); } // voltage logging B_.potentials_.record_data(origin.get_steps()+lag, S_.V_m_ + P_.E_L_); } }
void nest::iaf_psc_alpha_canon::emit_instant_spike_( Time const& origin, const long_t lag, const double_t spike_offs ) { assert( S_.y3_ >= P_.U_th_ ); // ensure we are superthreshold // set stamp and offset for spike S_.last_spike_step_ = origin.get_steps() + lag + 1; S_.last_spike_offset_ = spike_offs; // reset neuron and make it refractory S_.y3_ = P_.U_reset_; S_.is_refractory_ = true; // send spike set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; se.set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); return; }
void nest::iaf_psc_alpha_canon::emit_spike_( Time const& origin, const long_t lag, const double_t t0, const double_t dt ) { // we know that the potential is subthreshold at t0, super at t0+dt // compute spike time relative to beginning of step S_.last_spike_step_ = origin.get_steps() + lag + 1; S_.last_spike_offset_ = V_.h_ms_ - ( t0 + thresh_find_( dt ) ); // reset neuron and make it refractory S_.y3_ = P_.U_reset_; S_.is_refractory_ = true; // send spike set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; se.set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); return; }
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 ); } }
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::pp_psc_delta::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 ) { S_.y3_ = V_.P30_ * ( S_.y0_ + P_.I_e_ ) + V_.P33_ * S_.y3_ + B_.spikes_.get_value( lag ); double_t q_temp_ = 0; for ( uint_t i = 0; i < S_.q_elems_.size(); i++ ) { S_.q_elems_[ i ] = V_.Q33_[ i ] * S_.q_elems_[ i ]; q_temp_ += S_.q_elems_[ i ]; } S_.q_ = q_temp_; if ( S_.r_ == 0 ) { // Neuron not refractory // Calculate instantaneous rate from transfer function: // rate = c1 * y3' + c2 * exp(c3 * y3') // Adaptive threshold leads to effective potential V_eff instead of y3 double_t V_eff; V_eff = S_.y3_ - S_.q_; double_t rate = ( P_.c_1_ * V_eff + P_.c_2_ * std::exp( P_.c_3_ * V_eff ) ); if ( rate > 0.0 ) { ulong_t n_spikes = 0; if ( P_.dead_time_ > 0.0 ) { // Draw random number and compare to prob to have a spike if ( V_.rng_->drand() <= -numerics::expm1( -rate * V_.h_ * 1e-3 ) ) { n_spikes = 1; } } else { // Draw Poisson random number of spikes V_.poisson_dev_.set_lambda( rate * V_.h_ * 1e-3 ); n_spikes = V_.poisson_dev_.ldev( V_.rng_ ); } if ( n_spikes > 0 ) // Is there a spike? Then set the new dead time. { // Set dead time interval according to paramters if ( P_.dead_time_random_ ) { S_.r_ = Time( Time::ms( V_.gamma_dev_( V_.rng_ ) / V_.dt_rate_ ) ).get_steps(); } else S_.r_ = V_.DeadTimeCounts_; for ( uint_t i = 0; i < S_.q_elems_.size(); i++ ) { S_.q_elems_[ i ] += P_.q_sfa_[ i ] * n_spikes; } // And send the spike event SpikeEvent se; se.set_multiplicity( n_spikes ); kernel().event_delivery_manager.send( *this, se, lag ); // set spike time for STDP to work, // see https://github.com/nest/nest-simulator/issues/77 for ( uint_t i = 0; i < n_spikes; i++ ) { set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); } // Reset the potential if applicable if ( P_.with_reset_ ) { S_.y3_ = 0.0; } } // S_.y3_ = P_.V_reset_; } // if (rate > 0.0) } else // Neuron is within dead time { --S_.r_; } // Set new input current S_.y0_ = B_.currents_.get_value( lag ); // Voltage logging B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::iaf_neuron_dif_alpha::update(Time const & origin, const long_t from, const long_t to) { //bool ok=true; assert(to >= 0 && (delay) from < Scheduler::get_min_delay()); assert(from < to); const double_t h = Time::get_resolution().get_ms(); DictionaryDatum *d = new DictionaryDatum(new Dictionary); //behav_learning_loc->get((*d)); double_t v_old; get_status_user((*d)); //get_status((*d)); double_t t=origin.get_ms(); bool trig_seal_; bool trig_learn_oper_; updateValue<bool>((*d), names::trig_seal,trig_seal_);// d->trig_seal_ updateValue<bool>((*d), names::trig_learn_oper,trig_learn_oper_); if (trig_seal_) { //*std::cout<<"trig_seal\n"; //std::cout<<"grad "<<"\n"; trig_seal_=0; def<bool>((*d), names::trig_seal, trig_seal_); behav_learning_loc->reset_iterator_desired(); behav_learning_loc->set((*d)); clear_spike_history(); S_.I_=0; } if (trig_learn_oper_) { //std::cout<<"learn"<<"\n"; //std::vector<double > v_learn_exam=v_learn_set_desired[P_.number_prim_]; //std::cout<<v_learn_exam.size()<<"\n"; //std::cout<<"l I current="<<(P_.I_e_/P_.C_) + (S_.I_/P_.C_)<<"\n"; for ( long_t lag = from ; lag < to ; ++lag ) { if ( S_.r_ == 0 ) // neuron not refractory { v_old = S_.v_; //S_.v_ +=h*( ((P_.E_L_-v_old)/P_.Tau_) + (P_.I_e_/P_.C_) + (S_.I_/P_.C_) )+B_.spikes_.get_value(lag); S_.v_ +=h*( ((P_.E_L_-v_old)/P_.Tau_) + (P_.I_e_/P_.C_) + (S_.I_/P_.C_) ); //std::cout<<"learn S_.I_="<<S_.I_<<"\t"<<"S_.v_="<<S_.v_<<"\n"; } else // neuron is absolute refractory --S_.r_; //*std::cout<<"index "<<this->get_gid()<<" to "<<to<<"\t"<<"lag "<<lag<<"\t"<<"h "<<h<<"\t time"<<t+h*lag<<"\t"<<" S_.I_="<<S_.I_<<"\n"; //behav_learning_loc->get_learning_vector(P_.number_prim_) //calculate currents //add value to t_parametrs def<double>((*d), names::time,t+h*lag);// t+h*lag->d //std::cout<<"S_.v_="<<S_.v_<<"\t"; //std::cout<<"norm="<<normalization(S_.v_)<<"\t"; def<double>((*d), names::potential,S_.v_); //std::cout<<"op"<<"\n"; std::vector<double > currents; set_learning_variables((*d),t+h*lag,currents); //std::cout<<"opop"<<"\n"; if (behav_learning_loc->learn(behav_loc,(*d),currents)) { //*std::cout<<"spike_time"<<"\n"; //clean spike history S_.r_ = V_.RefractoryCounts_; S_.v_= P_.E_L_; set_spiketime(Time::step(origin.get_steps()+lag)); //std::cout<<"learn time spike from neuron "<<Time::step(origin.get_steps()+lag)<<"\n"; SpikeEvent se; //se.set_weight(-1.0); network()->send(*this, se, lag); //clear_spike_history(); //ok=false; } else if (S_.v_ >= P_.V_th_) { //std::cout<<"spike_time"<<"\n"; //clean spike history S_.r_ = V_.RefractoryCounts_; S_.v_= P_.E_L_; set_spiketime(Time::step(origin.get_steps()+lag)); // change -1 SpikeEvent se; //se.set_weight(-1.0); network()->send(*this, se, lag); //clear_spike_history(); //ok=false; } //B_.spikes_.get_value(lag);// Need for clean buffer. It's necessary for working log-device wrapper. S_.I_=B_.currents_.get_value(lag); S_.I_ =S_.I_+get_sum_I(t+h*lag); //two time calclulate //std::cout<<"S_.I_="<<S_.I_<<"\n";; // voltage logging B_.logger_.record_data(origin.get_steps()+lag); } //std::cout<<"opop3"<<"\n"; } else /*function mode */ { //std::cout<<"function"<<"\n"; //std::cout<<"I current="<<(P_.I_e_/P_.C_) + (S_.I_/P_.C_)<<"\t"; for ( long_t lag = from ; lag < to ; ++lag ) { if ( S_.r_ == 0 ) // neuron not refractory { v_old = S_.v_; //S_.v_ +=h*( ((P_.E_L_-v_old)/P_.Tau_) + (P_.I_e_/P_.C_) + (S_.I_/P_.C_) )+B_.spikes_.get_value(lag); S_.v_ +=h*( ((P_.E_L_-v_old)/P_.Tau_) + (P_.I_e_/P_.C_) + (S_.I_/P_.C_) ); //std::cout<<"fun S_.I_="<<S_.I_<<"\t"<<"S_.v_="<<S_.v_<<"\n"; std::cout<<"fun S_.I_="<<S_.I_<<"\n"; } else // neuron is absolute refractory --S_.r_; // threshold crossing std::cout<<"index "<<this->get_gid()<<" to "<<to<<"\t"<<"lag "<<lag<<"\t"<<"h "<<h<<"\t"; std::cout<<S_.v_<<"\t"<<"\n"; //if (emission_procedure(S_.v_)) if (S_.v_ >= P_.V_th_) { //std::cout<<"spike_time"<<"\n"; //clean spike history S_.r_ = V_.RefractoryCounts_; S_.v_= P_.E_L_; set_spiketime(Time::step(origin.get_steps()+lag)); // change -1 //std::cout<<"fun time spike from neuron "<<Time::step(origin.get_steps()+lag)<<"\n";// change -1 SpikeEvent se; //se.set_weight(-1.0); network()->send(*this, se, lag); //clear_spike_history(); //ok=false; } //B_.spikes_.get_value(lag);// Need for clean buffer. It's necessary for working log-device wrapper. S_.I_=B_.currents_.get_value(lag); S_.I_ =S_.I_+get_sum_I(t+h*lag); // надо делать инач //std::cout<<"fun S_.I_="<<S_.I_<<"\n"; // voltage logging B_.logger_.record_data(origin.get_steps()+lag); } //std::cout<<"\n"; /*function mode */ } delete d; }
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 iaf_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 ); for ( long lag = from; lag < to; ++lag ) { if ( S_.r_ == 0 ) { // neuron not refractory S_.y3_ = V_.P30_ * ( S_.y0_ + P_.I_e_ ) + V_.P31_ex_ * S_.y1_ex_ + V_.P32_ex_ * S_.y2_ex_ + V_.P31_in_ * S_.y1_in_ + V_.P32_in_ * S_.y2_in_ + V_.expm1_tau_m_ * S_.y3_ + S_.y3_; // lower bound of membrane potential S_.y3_ = ( S_.y3_ < P_.LowerBound_ ? P_.LowerBound_ : S_.y3_ ); } else // neuron is absolute refractory --S_.r_; // alpha shape EPSCs S_.y2_ex_ = V_.P21_ex_ * S_.y1_ex_ + V_.P22_ex_ * S_.y2_ex_; S_.y1_ex_ *= V_.P11_ex_; // Apply spikes delivered in this step; spikes arriving at T+1 have // an immediate effect on the state of the neuron V_.weighted_spikes_ex_ = B_.ex_spikes_.get_value( lag ); S_.y1_ex_ += V_.EPSCInitialValue_ * V_.weighted_spikes_ex_; // alpha shape EPSCs S_.y2_in_ = V_.P21_in_ * S_.y1_in_ + V_.P22_in_ * S_.y2_in_; S_.y1_in_ *= V_.P11_in_; // Apply spikes delivered in this step; spikes arriving at T+1 have // an immediate effect on the state of the neuron V_.weighted_spikes_in_ = B_.in_spikes_.get_value( lag ); S_.y1_in_ += V_.IPSCInitialValue_ * V_.weighted_spikes_in_; // threshold crossing if ( S_.y3_ >= P_.Theta_ ) { S_.r_ = V_.RefractoryCounts_; S_.y3_ = P_.V_reset_; // A supra-threshold membrane potential should never be observable. // The reset at the time of threshold crossing enables accurate // integration independent of the computation step size, see [2,3] for // details. set_spiketime( Time::step( origin.get_steps() + lag + 1 ) ); SpikeEvent se; kernel().event_delivery_manager.send( *this, se, lag ); } // set new input current S_.y0_ = B_.currents_.get_value( lag ); // log state data B_.logger_.record_data( origin.get_steps() + lag ); } }
void nest::iaf_psc_alpha_presc::update( Time const& origin, const long_t from, const long_t to ) { assert( to >= 0 ); assert( static_cast< delay >( from ) < kernel().connection_manager.get_min_delay() ); assert( from < to ); /* Neurons may have been initialized to superthreshold potentials. We need to check for this here and issue spikes at the beginning of the interval. */ if ( S_.y3_ >= P_.U_th_ ) { S_.last_spike_step_ = origin.get_steps() + from + 1; S_.last_spike_offset_ = V_.h_ms_ * ( 1 - std::numeric_limits< double_t >::epsilon() ); // reset neuron and make it refractory S_.y3_ = P_.U_reset_; S_.r_ = V_.refractory_steps_; // send spike set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; se.set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, from ); } for ( long_t lag = from; lag < to; ++lag ) { // time at start of update step const long_t T = origin.get_steps() + lag; // save state at beginning of interval for spike-time interpolation V_.y0_before_ = S_.y0_; V_.y1_before_ = S_.y1_; V_.y2_before_ = S_.y2_; V_.y3_before_ = S_.y3_; /* obtain input to y3_ We need to collect this value even while the neuron is refractory, since we need to clear any spikes that have come in from the ring buffer. */ const double_t dy3 = B_.spike_y3_.get_value( lag ); if ( S_.r_ == 0 ) { // neuron is not refractory S_.y3_ = V_.P30_ * ( P_.I_e_ + S_.y0_ ) + V_.P31_ * S_.y1_ + V_.P32_ * S_.y2_ + V_.expm1_tau_m_ * S_.y3_ + S_.y3_; S_.y3_ += dy3; // add input // enforce lower bound S_.y3_ = ( S_.y3_ < P_.U_min_ ? P_.U_min_ : S_.y3_ ); } else if ( S_.r_ == 1 ) { // neuron returns from refractoriness during interval S_.r_ = 0; // Iterate third component (membrane pot) from end of // refractory period to end of interval. As first-order // approximation, add a proportion of the effect of synaptic // input during the interval to membrane pot. The proportion // is given by the part of the interval after the end of the // refractory period. S_.y3_ = P_.U_reset_ + // try fix 070623, md update_y3_delta_() + dy3 - dy3 * ( 1 - S_.last_spike_offset_ / V_.h_ms_ ); // enforce lower bound S_.y3_ = ( S_.y3_ < P_.U_min_ ? P_.U_min_ : S_.y3_ ); } else { // neuron is refractory // y3_ remains unchanged at 0.0 --S_.r_; } // update synaptic currents S_.y2_ = V_.expm1_tau_syn_ * V_.h_ms_ * S_.y1_ + V_.expm1_tau_syn_ * S_.y2_ + V_.h_ms_ * S_.y1_ + S_.y2_; S_.y1_ = V_.expm1_tau_syn_ * S_.y1_ + S_.y1_; // add synaptic inputs from the ring buffer // this must happen BEFORE threshold-crossing interpolation, // since synaptic inputs occured during the interval S_.y1_ += B_.spike_y1_.get_value( lag ); S_.y2_ += B_.spike_y2_.get_value( lag ); // neuron spikes if ( S_.y3_ >= P_.U_th_ ) { // compute spike time S_.last_spike_step_ = T + 1; // The time for the threshpassing S_.last_spike_offset_ = V_.h_ms_ - thresh_find_( V_.h_ms_ ); // reset AFTER spike-time interpolation S_.y3_ = P_.U_reset_; S_.r_ = V_.refractory_steps_; // sent event set_spiketime( Time::step( S_.last_spike_step_ ), S_.last_spike_offset_ ); SpikeEvent se; se.set_offset( S_.last_spike_offset_ ); kernel().event_delivery_manager.send( *this, se, lag ); } // Set new input current. The current change occurs at the // end of the interval and thus must come AFTER the threshold- // crossing interpolation S_.y0_ = B_.currents_.get_value( lag ); // logging B_.logger_.record_data( origin.get_steps() + lag ); } // from lag = from ... }
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); } }