// finds threshpassing inline nest::double_t nest::iaf_psc_alpha_canon::thresh_find_(double_t const dt) const { switch (P_.Interpol_) { case NO_INTERPOL: return dt; case LINEAR : return thresh_find1_(dt); case QUADRATIC : return thresh_find2_(dt); case CUBIC : return thresh_find3_(dt); default: throw BadProperty("Invalid interpolation order in iaf_psc_alpha_canon."); } return 0; }
// finds threshpassing inline nest::double_t nest::iaf_psc_alpha_presc::thresh_find_(double_t const dt) const { switch (P_.Interpol_) { case NO_INTERPOL: return dt; case LINEAR : return thresh_find1_(dt); case QUADRATIC : return thresh_find2_(dt); case CUBIC : return thresh_find3_(dt); default: network()->message(SLIInterpreter::M_ERROR, "iaf_psc_alpha_presc::thresh_find_()", "Invalid interpolation---Internal model error."); throw BadProperty(); } return 0; }
nest::double_t nest::iaf_psc_alpha_canon::thresh_find3_( double_t const dt ) const { const double_t h_ms = dt; const double_t h_sq = h_ms * h_ms; const double_t h_cb = h_sq * h_ms; const double_t deriv_t1 = -V_.y3_before_ / P_.tau_m_ + ( P_.I_e_ + V_.y0_before_ + V_.y2_before_ ) / P_.c_m_; const double_t deriv_t2 = -S_.y3_ / P_.tau_m_ + ( P_.I_e_ + S_.y0_ + S_.y2_ ) / P_.c_m_; const double_t w3_ = ( 2 * V_.y3_before_ / h_cb ) - ( 2 * S_.y3_ / h_cb ) + ( deriv_t1 / h_sq ) + ( deriv_t2 / h_sq ); const double_t w2_ = -( 3 * V_.y3_before_ / h_sq ) + ( 3 * S_.y3_ / h_sq ) - ( 2 * deriv_t1 / h_ms ) - ( deriv_t2 / h_ms ); const double_t w1_ = deriv_t1; const double_t w0_ = V_.y3_before_; // normal form : x^3 + r*x^2 + s*x + t with coefficients : r, s, t const double_t r = w2_ / w3_; const double_t s = w1_ / w3_; const double_t t = ( w0_ - P_.U_th_ ) / w3_; const double_t r_sq = r * r; // substitution y = x + r/3 : y^3 + p*y + q == 0 const double_t p = -r_sq / 3 + s; const double_t q = 2 * ( r_sq * r ) / 27 - r * s / 3 + t; // discriminante const double_t D = std::pow( ( p / 3 ), 3 ) + std::pow( ( q / 2 ), 2 ); double_t tau1; double_t tau2; double_t tau3; if ( D < 0 ) { const double_t roh = std::sqrt( -( p * p * p ) / 27 ); const double_t phi = std::acos( -q / ( 2 * roh ) ); const double_t a = 2 * std::pow( roh, ( 1.0 / 3.0 ) ); tau1 = ( a * std::cos( phi / 3 ) ) - r / 3; tau2 = ( a * std::cos( phi / 3 + 2 * numerics::pi / 3 ) ) - r / 3; tau3 = ( a * std::cos( phi / 3 + 4 * numerics::pi / 3 ) ) - r / 3; } else { const double_t sgnq = ( q >= 0 ? 1 : -1 ); const double_t u = -sgnq * std::pow( std::fabs( q ) / 2.0 + std::sqrt( D ), 1.0 / 3.0 ); const double_t v = -p / ( 3 * u ); tau1 = ( u + v ) - r / 3; if ( tau1 >= 0 ) { return tau1; } else { return thresh_find2_( dt ); } } // set tau to the smallest root above 0 double tau = ( tau1 >= 0 ) ? tau1 : 2 * h_ms; if ( ( tau2 >= 0 ) && ( tau2 < tau ) ) tau = tau2; if ( ( tau3 >= 0 ) && ( tau3 < tau ) ) tau = tau3; return ( tau <= V_.h_ms_ ) ? tau : thresh_find2_( dt ); }
// cubic interpolation nest::double_t nest::iaf_psc_exp_canon::thresh_find3_(double_t const dt) const { double_t const h_ms_ = dt; double_t const h_sq = h_ms_*h_ms_; double_t const h_cb = h_sq*h_ms_; // f' at left border used as third condition double_t const deriv_t1 = -V_.y2_before_/P_.tau_m_ + (P_.I_e_ + V_.y1_ex_before_ + V_.y1_in_before_) / P_.c_m_; // f' at right border used as fourth condition double_t const deriv_t2 = -S_.y2_/P_.tau_m_ + (P_.I_e_ + S_.y1_ex_ + S_.y1_in_) / P_.c_m_; double_t const w3_ = (2*V_.y2_before_ / h_cb) - (2*S_.y2_ / h_cb) + (deriv_t1 / h_sq) + (deriv_t2 / h_sq) ; double_t const w2_ = -(3*V_.y2_before_ / h_sq) + (3*S_.y2_ / h_sq) - (2*deriv_t1 / h_ms_) - (deriv_t2 / h_ms_); double_t const w1_ = deriv_t1; double_t const w0_ = V_.y2_before_; // normal form: x^3 + r*x^2 + s*x + t with coefficients: r, s, t double_t const r = w2_/w3_; double_t const s = w1_/w3_; double_t const t = (w0_-P_.U_th_) / w3_; double_t const r_sq = r*r; // substitution y = x + r/3: y^3 + p*y + q == 0 double_t const p = -r_sq/3 + s; double_t const q = 2*(r_sq*r) / 27 - r*s / 3 + t; // discriminante double_t const D = std::pow((p/3), 3) + std::pow((q/2), 2); double_t tau1; double_t tau2; double_t tau3; if ( D < 0 ) { double_t const roh = std::sqrt(-(p*p*p) / 27); double_t const phi = std::acos(-q / (2*roh)); double_t const a = 2*std::pow(roh, (1.0/3.0)); tau1 = (a*std::cos(phi/3)) - r/3; tau2 = (a*std::cos(phi/3 + 2*numerics::pi/3)) - r/3; tau3 = (a*std::cos(phi/3 + 4*numerics::pi/3)) - r/3; } else { double_t const sgnq = ( q >= 0 ? 1 : -1 ); double_t const u = -sgnq*std::pow(std::fabs(q)/2.0 + std::sqrt(D), 1.0/3.0); double_t const v = -p/(3*u); tau1= (u+v) - r/3; if ( tau1 >= 0 ) return tau1; else return thresh_find2_(dt); } // set tau to the smallest root above 0 double tau = ( tau1 >= 0 ? tau1 : 2*h_ms_ ); if (( tau2 >=0 ) && ( tau2 < tau )) tau = tau2; if (( tau3 >=0 ) && ( tau3 < tau )) tau = tau3; return ( tau <= h_ms_ ? tau : thresh_find2_(dt) ); }