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::pp_pop_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_.h_ = S_.h_ * V_.P33_ + V_.P30_ * ( S_.y0_ + P_.I_e_ ) + B_.spikes_.get_value( lag ); // get_thetas_ages std::vector< double_t > tmp_vector; double_t integral = 0; tmp_vector.clear(); for ( uint_t i = 0; i < V_.eta_kernel_.size(); i++ ) { tmp_vector.push_back( V_.eta_kernel_[ i ] * S_.n_spikes_past_[ ( S_.p_n_spikes_past_ + i ) % S_.n_spikes_past_.size() ] * V_.h_ * 0.001 ); integral += tmp_vector[ i ]; } S_.thetas_ages_.clear(); S_.thetas_ages_.push_back( integral ); for ( uint_t i = 1; i < V_.eta_kernel_.size(); i++ ) S_.thetas_ages_.push_back( S_.thetas_ages_[ i - 1 ] - tmp_vector[ i - 1 ] ); for ( uint_t i = 0; i < V_.eta_kernel_.size(); i++ ) S_.thetas_ages_[ i ] += V_.theta_kernel_[ i ]; S_.thetas_ages_.push_back( 0 ); // get_escape_rate for ( uint_t i = 0; i < S_.rhos_ages_.size(); i++ ) S_.rhos_ages_[ i ] = P_.rho_0_ * std::exp( ( S_.h_ + S_.thetas_ages_[ i ] ) / P_.delta_u_ ); double p_argument; // generate_spikes for ( uint_t i = 0; i < S_.age_occupations_.size(); i++ ) { if ( S_.age_occupations_[ ( S_.p_age_occupations_ + i ) % S_.age_occupations_.size() ] > 0 ) { p_argument = -numerics::expm1( -S_.rhos_ages_[ i ] * V_.h_ * 0.001 ); // V_.h_ is in ms, S_.rhos_ages_ is in Hz if ( p_argument > V_.min_double_ ) { V_.binom_dev_.set_p_n( p_argument, S_.age_occupations_[ ( S_.p_age_occupations_ + i ) % S_.age_occupations_.size() ] ); S_.n_spikes_ages_[ i ] = V_.binom_dev_.ldev( V_.rng_ ); } else { S_.n_spikes_ages_[ i ] = 0; } } else S_.n_spikes_ages_[ i ] = 0; } S_.p_n_spikes_past_ = ( S_.p_n_spikes_past_ - 1 + S_.n_spikes_past_.size() ) % S_.n_spikes_past_.size(); // shift to the right int_t temp_sum = 0; for ( uint_t i = 0; i < S_.n_spikes_ages_.size(); i++ ) // cumulative sum temp_sum += S_.n_spikes_ages_[ i ]; S_.n_spikes_past_[ S_.p_n_spikes_past_ ] = temp_sum; // update_age_occupations for ( uint_t i = 0; i < S_.age_occupations_.size(); i++ ) S_.age_occupations_[ ( S_.p_age_occupations_ + i ) % S_.age_occupations_.size() ] -= S_.n_spikes_ages_[ i ]; int_t last_element_value = S_.age_occupations_[ ( S_.p_age_occupations_ - 1 + S_.age_occupations_.size() ) % S_.age_occupations_.size() ]; // save the last element S_.p_age_occupations_ = ( S_.p_age_occupations_ - 1 + S_.age_occupations_.size() ) % S_.age_occupations_.size(); // shift to the right S_.age_occupations_[ ( S_.p_age_occupations_ - 1 + S_.age_occupations_.size() ) % S_.age_occupations_.size() ] += last_element_value; S_.age_occupations_[ S_.p_age_occupations_ ] = S_.n_spikes_past_[ S_.p_n_spikes_past_ ]; // Set new input current S_.y0_ = B_.currents_.get_value( lag ); // Voltage logging B_.logger_.record_data( origin.get_steps() + lag ); // test if S_.n_spikes_past_[S_.p_n_spikes_past_]!=0, generate spike and send this number as the // parameter if ( S_.n_spikes_past_[ S_.p_n_spikes_past_ ] > 0 ) // Is there any spike? { SpikeEvent se; se.set_multiplicity( S_.n_spikes_past_[ S_.p_n_spikes_past_ ] ); kernel().event_delivery_manager.send( *this, se, lag ); } } }