Example #1
0
 inline Polynomial<T, Structure>& Polynomial<T, Structure>::operator*=(const Polynomial<T, Structure>& other)
 {
   coefficient_list new_coefficients (deg() + other.deg() + 1, 0);
   for (size_type i = 0; i <= deg(); ++i) {
     for (size_type j = 0; j <= other.deg(); ++j) {
       new_coefficients[i + j] += m_coefficients[i] * other.m_coefficients[j];
     }
   }
   m_coefficients = new_coefficients;
   remove_zeros();
   return *this;
 }
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;
}