From 7f76792700deebbd50b41a6d7e318b0e9267e74f Mon Sep 17 00:00:00 2001
From: Jan Moren <jan.moren@gmail.com>
Date: Tue, 6 Aug 2013 14:58:06 +0900
Subject: [PATCH 1/3] apply patch for SC related models

---
 models/Makefile.am        |  2 ++
 models/modelsmodule.cpp   |  4 ++++
 nestkernel/nest_names.cpp | 15 +++++++++++++++
 nestkernel/nest_names.h   | 14 ++++++++++++++
 4 files changed, 35 insertions(+)

diff --git a/models/Makefile.am b/models/Makefile.am
index c79d6ab..2715c0a 100644
--- a/models/Makefile.am
+++ b/models/Makefile.am
@@ -31,6 +31,8 @@ libmodelsmodule_la_SOURCES= \
 		iaf_cond_exp_sfa_rr.h iaf_cond_exp_sfa_rr.cpp\
 		iaf_cond_alpha_mc.cpp iaf_cond_alpha_mc.h\
 		aeif_cond_alpha.h aeif_cond_alpha.cpp\
+		aeif_cond_nmda_alpha.h aeif_cond_nmda_alpha.cpp\
+		synth_integrator.h synth_integrator.cpp \
 		aeif_cond_exp.h aeif_cond_exp.cpp\
 		hh_psc_alpha.h hh_psc_alpha.cpp\
 		hh_cond_exp_traub.cpp hh_cond_exp_traub.h\
diff --git a/models/modelsmodule.cpp b/models/modelsmodule.cpp
index 9d5c1ae..9fd84c2 100644
--- a/models/modelsmodule.cpp
+++ b/models/modelsmodule.cpp
@@ -43,6 +43,8 @@
 
 // Neuron models
 #include "aeif_cond_alpha.h"
+#include "aeif_cond_nmda_alpha.h"
+#include "synth_integrator.h"
 #include "aeif_cond_exp.h"
 #include "hh_cond_exp_traub.h"
 #include "hh_psc_alpha.h"
@@ -194,6 +196,8 @@ namespace nest
 
 #ifdef HAVE_GSL_1_11
     register_model<aeif_cond_alpha>(net_, "aeif_cond_alpha");
+    register_model<aeif_cond_nmda_alpha>(net_, "aeif_cond_nmda_alpha");
+    register_model<synth_integrator>(net_, "synth_integrator");
     register_model<aeif_cond_exp>(net_, "aeif_cond_exp");
     register_model<ht_neuron>(net_,       "ht_neuron");
 #endif
diff --git a/nestkernel/nest_names.cpp b/nestkernel/nest_names.cpp
index 58b6840..cf86a5a 100644
--- a/nestkernel/nest_names.cpp
+++ b/nestkernel/nest_names.cpp
@@ -337,5 +337,20 @@ namespace nest
     const Name recorder("recorder");
     const Name synapse("synapse");
     const Name other("other");
+
+
+    // These are for the aeiaf model
+    const Name N_V_max("NMDA_V_max");   // Voltage for max NMDA effect (not really)
+    const Name N_V_min("NMDA_V_min");    // Voltage for minimum NMDA
+    const Name N_gain("NMDA_gain");     // Gain for NMDA sigmoid
+    const Name g_n("g_n");      // NMDA conductance
+    const Name dg_n("g_n");     // derivative NMDA conductance
+    const Name E_n("E_n");       // NMDA reversal potential 
+    const Name tau_syn_n("tau_syn_n"); // NMDA time constant
+
+    const Name Smax("Smax");    // Max for spike integrator
+    const Name Gamma("Gamma");  // Gamma factor
+    const Name Reset("Reset");  // Reset threshold
+
   }
 }
diff --git a/nestkernel/nest_names.h b/nestkernel/nest_names.h
index 377bc8d..cc00894 100644
--- a/nestkernel/nest_names.h
+++ b/nestkernel/nest_names.h
@@ -359,6 +359,20 @@ namespace nest
     extern const Name recorder;
     extern const Name synapse;
     extern const Name other;
+
+    // For aeif_cond_nmda_alpha and synnth_integrator
+    extern const Name N_V_max;   
+    extern const Name N_V_min;  
+    extern const Name N_gain;  
+    extern const Name g_n;       // NMDA conductance
+    extern const Name dg_n;      // derivative NMDA conductance
+    extern const Name E_n;       // NMDA reversal potential 
+    extern const Name tau_syn_n; // NMDA time constant
+
+    extern const Name Smax;   // max for integrator
+    extern const Name Gamma;   // gamma factor
+    extern const Name Reset;   // reset threshold
+
   }
 }
 
-- 
1.8.1.2


From 4069b888f50cf5c91943ba0c6f7f897a0ea53fc9 Mon Sep 17 00:00:00 2001
From: Jan Moren <jan.moren@gmail.com>
Date: Tue, 6 Aug 2013 14:59:58 +0900
Subject: [PATCH 2/3] add aeif_nmda model

---
 models/aeif_cond_nmda_alpha.cpp | 521 ++++++++++++++++++++++++++++++++++++++++
 models/aeif_cond_nmda_alpha.h   | 412 +++++++++++++++++++++++++++++++
 2 files changed, 933 insertions(+)
 create mode 100644 models/aeif_cond_nmda_alpha.cpp
 create mode 100644 models/aeif_cond_nmda_alpha.h

diff --git a/models/aeif_cond_nmda_alpha.cpp b/models/aeif_cond_nmda_alpha.cpp
new file mode 100644
index 0000000..746446a
--- /dev/null
+++ b/models/aeif_cond_nmda_alpha.cpp
@@ -0,0 +1,521 @@
+/*
+ *  aeif_cond_nmda_alpha.cpp
+ *
+ * Adaptive exponential integrate-and-fire model (Brette and Gerstner) with
+ * alpha-shaped synaptic conductances, as implemented in aeif_cond_alpha.cpp 
+ * from the nest simulator (v. 1.9.8498).
+ *
+ * This version adds an NMDA synapse-like input with positive
+ * voltage-dependence on the conductance.
+ *
+ * Jan Moren, 2009
+ *
+ * 2011 - Update for nest2
+ *
+ * Original model:
+*
+ *  This file is part of NEST
+ *
+ *  Copyright (C) 2005 by
+ *  The NEST Initiative
+ *
+ *  See the file AUTHORS for details.
+ *
+ *  Permission is granted to compile and modify
+ *  this file for non-commercial use.
+ *  See the file LICENSE for details.
+ *
+ */
+
+
+#include "aeif_cond_nmda_alpha.h"
+//#include "scmodules_names.h"
+#include "nest_names.h"
+
+#ifdef HAVE_GSL_1_11
+
+#include "universal_data_logger_impl.h"
+#include "exceptions.h"
+#include "network.h"
+#include "dict.h"
+#include "integerdatum.h"
+#include "doubledatum.h"
+#include "dictutils.h"
+#include "numerics.h"
+#include <limits>
+
+#include <cmath>
+#include <iomanip>
+#include <iostream>
+#include <cstdio>
+
+/* ---------------------------------------------------------------- 
+ * Recordables map
+ * ---------------------------------------------------------------- */
+
+nest::RecordablesMap<nest::aeif_cond_nmda_alpha> nest::aeif_cond_nmda_alpha::recordablesMap_;
+
+using namespace nest;
+
+namespace nest {
+/*
+   * Override the create() method with one call to RecordablesMap::insert_() 
+   * for each quantity to be recorded.
+   */
+    template <>
+    void RecordablesMap<aeif_cond_nmda_alpha>::create()
+    {
+	// use standard names whereever you can for consistency!
+	insert_(names::V_m, &aeif_cond_nmda_alpha::get_y_elem_<aeif_cond_nmda_alpha::V_M>);
+	insert_(names::g_ex, &aeif_cond_nmda_alpha::get_y_elem_<aeif_cond_nmda_alpha::G_EX>);
+	insert_(names::g_in, &aeif_cond_nmda_alpha::get_y_elem_<aeif_cond_nmda_alpha::G_IN>);
+	insert_(names::g_n, &aeif_cond_nmda_alpha::get_y_elem_<aeif_cond_nmda_alpha::G_N>);
+	insert_(names::w, &aeif_cond_nmda_alpha::get_y_elem_<aeif_cond_nmda_alpha::W>);
+	//insert_("weighted_spikes_ex", &nest::synth_integrator::get_weighted_spikes_ex_);
+	//insert_("weighted_spikes_in", &nest::synth_integrator::get_weighted_spikes_in_);
+    }
+}
+
+ extern "C"
+ int aeif_cond_nmda_alpha_dynamics (double, const double y[], double f[], void* param)
+ {
+   // shorthand for class we work for
+   typedef nest::aeif_cond_nmda_alpha AEIF;
+   
+   // get parameters as reference  
+   AEIF::Parameters_* tmp =
+     reinterpret_cast<AEIF::Parameters_*>(param);
+   assert(tmp);
+   AEIF::Parameters_& p = *tmp;
+
+   // shorthand for state variables
+   const nest::double_t& V     = y[AEIF::V_M  ];
+   const nest::double_t& dg_ex = y[AEIF::DG_EX];
+   const nest::double_t&  g_ex = y[AEIF::G_EX ];
+   const nest::double_t& dg_in = y[AEIF::DG_IN];
+   const nest::double_t&  g_in = y[AEIF::G_IN ];
+   const nest::double_t& w     = y[AEIF::W    ];
+   const nest::double_t& dg_n = y[AEIF::DG_N];
+   const nest::double_t&  g_n = y[AEIF::G_N ];
+
+   const nest::double_t I_syn_exc = g_ex * (V - p.E_ex);
+   const nest::double_t I_syn_inh = g_in * (V - p.E_in);
+   const nest::double_t I_syn_n   = g_n * (V - p.E_n);
+   const nest::double_t I_spike = p.Delta_T * std::exp((V - p.V_th) / p.Delta_T);
+
+   // dv/dt
+   f[AEIF::V_M  ] = ( -p.g_L *( (V-p.E_L) - I_spike) 
+ 	                   - I_syn_exc - I_syn_inh - I_syn_n - w + p.I_e + p.I_stim) / p.C_m;
+
+   f[AEIF::DG_EX] = -dg_ex / p.tau_syn_ex;
+   f[AEIF::G_EX ] =  dg_ex - g_ex / p.tau_syn_ex; // Synaptic Conductance (nS)
+
+   f[AEIF::DG_IN] = -dg_in / p.tau_syn_in;
+   f[AEIF::G_IN ] =  dg_in - g_in / p.tau_syn_in; // Synaptic Conductance (nS)
+
+   f[AEIF::DG_N] = -dg_n / p.tau_syn_n;
+   f[AEIF::G_N ] =  dg_n - g_n / p.tau_syn_n; // Synaptic Conductance (nS)
+
+   // Adaptation current w.
+   f[AEIF::W    ] = ( p.a * (V - p.E_L) - w ) / p.tau_w;
+
+   return GSL_SUCCESS;
+ }
+
+/* ---------------------------------------------------------------- 
+ * Default constructors defining default parameters and state
+ * ---------------------------------------------------------------- */
+    
+nest::aeif_cond_nmda_alpha::Parameters_::Parameters_()
+  : V_peak_    (  0.0    ),  // mV
+    V_reset_   (-60.0    ),  // mV
+    t_ref_     (  0.0    ),  // ms
+    g_L        ( 30.0    ),  // nS
+    C_m        (281.0    ),  // pF
+    E_ex       (  0.0    ),  // mV
+    E_in       (-85.0    ),  // mV
+    E_L        (-70.6    ),  // mV
+    Delta_T    (  2.0    ),  // mV
+    tau_w      (144.0    ),  // ms
+    a          (  4.0    ),  // nS
+    b          ( 80.5    ),  // pA
+    V_th       (-50.4    ),  // mV
+    tau_syn_ex (  0.2    ),  // ms
+    tau_syn_in (  2.0    ),  // ms
+    I_e        (  0.0    ),  // pA
+    
+    N_V_min     (-70.0    ),  // mv
+    N_V_max     (-50.0    ),  // mV
+    N_gain      (  3.0    ),   // -
+    tau_syn_n   (  3.0    ),  // ms
+    E_n         (  0.0    )  // mV
+{}
+
+nest::aeif_cond_nmda_alpha::State_::State_(const Parameters_& p)
+  : r_(0)
+{
+  y_[0] = p.E_L;
+  for ( size_t i = 1 ; i < aeif_cond_nmda_alpha::NSTATES ; ++i )
+    y_[i] = 0;
+}
+
+nest::aeif_cond_nmda_alpha::State_::State_(const State_& s)
+  : r_(s.r_)
+{
+  for ( size_t i = 0 ; i < aeif_cond_nmda_alpha::NSTATES ; ++i )
+    y_[i] = s.y_[i];
+}
+
+nest::aeif_cond_nmda_alpha::State_& nest::aeif_cond_nmda_alpha::State_::operator=(const State_& s)
+{
+  assert(this != &s);  // would be bad logical error in program
+  
+  for ( size_t i = 0 ; i < aeif_cond_nmda_alpha::NSTATES ; ++i )
+    y_[i] = s.y_[i];
+  r_ = s.r_;
+  return *this;
+}
+
+/* ---------------------------------------------------------------- 
+ * Paramater and state extractions and manipulation functions
+ * ---------------------------------------------------------------- */
+
+void nest::aeif_cond_nmda_alpha::Parameters_::get(DictionaryDatum &d) const
+{
+  def<double>(d,names::C_m,    C_m);
+  def<double>(d,names::V_th,   V_th);
+  def<double>(d,names::t_ref,  t_ref_);
+  def<double>(d,names::g_L,    g_L);
+  def<double>(d,names::E_L,    E_L); 
+  def<double>(d,names::V_reset,V_reset_);
+  def<double>(d,names::E_ex,   E_ex);
+  def<double>(d,names::E_in,   E_in);
+  def<double>(d,names::tau_syn_ex, tau_syn_ex);
+  def<double>(d,names::tau_syn_in, tau_syn_in);
+  def<double>(d,names::a,      a);
+  def<double>(d,names::b,      b);
+  def<double>(d,names::Delta_T,Delta_T);
+  def<double>(d,names::tau_w,  tau_w);
+  def<double>(d,names::I_e,    I_e);
+  def<double>(d,names::V_peak, V_peak_);
+
+  def<double>(d, names::N_V_min, N_V_min);
+  def<double>(d, names::N_V_max, N_V_max);
+  def<double>(d, names::N_gain, N_gain);
+  def<double>(d, names::E_n,   E_n);
+  def<double>(d, names::tau_syn_n, tau_syn_n);
+}
+
+void nest::aeif_cond_nmda_alpha::Parameters_::set(const DictionaryDatum& d)
+{
+  updateValue<double>(d,names::V_th,    V_th);
+  updateValue<double>(d,names::V_peak,  V_peak_);
+  updateValue<double>(d,names::t_ref,   t_ref_);
+  updateValue<double>(d,names::E_L,     E_L);
+  updateValue<double>(d,names::V_reset, V_reset_);
+  updateValue<double>(d,names::E_ex,    E_ex);
+  updateValue<double>(d,names::E_in,    E_in);
+    
+  updateValue<double>(d,names::C_m,     C_m);
+  updateValue<double>(d,names::g_L,     g_L);
+    
+  updateValue<double>(d,names::tau_syn_ex, tau_syn_ex);
+  updateValue<double>(d,names::tau_syn_in, tau_syn_in);
+    
+  updateValue<double>(d,names::a,      a);
+  updateValue<double>(d,names::b,      b);
+  updateValue<double>(d,names::Delta_T,Delta_T);
+  updateValue<double>(d,names::tau_w,  tau_w);
+
+  updateValue<double>(d,names::I_e,    I_e);
+
+  updateValue<double>(d, names::N_V_min, N_V_min);
+  updateValue<double>(d, names::N_V_max, N_V_max);
+  updateValue<double>(d, names::N_gain, N_gain);
+  updateValue<double>(d, names::E_n,    E_n);
+  updateValue<double>(d, names::tau_syn_n, tau_syn_n);
+
+  if ( V_reset_ >= V_th )
+    throw BadProperty("Reset potential must be smaller than threshold.");
+    
+  if ( V_peak_ <= V_th )
+    throw BadProperty("V_peak must be larger than threshold.");
+
+  if ( C_m <= 0 )
+  {
+    throw BadProperty("Capacitance must be strictly positive.");
+  }
+    
+  if ( t_ref_ < 0 )
+    throw BadProperty("Refractory time cannot be negative.");
+      
+  if ( tau_syn_ex <= 0 || tau_syn_in <= 0 || tau_syn_n <=0 || tau_w <= 0 )
+    throw BadProperty("All time constants must be strictly positive.");
+}
+
+void nest::aeif_cond_nmda_alpha::State_::get(DictionaryDatum &d) const
+{
+  def<double>(d,names::V_m,    y_[V_M]);
+  def<double>(d,names::g_ex,   y_[G_EX]);
+  def<double>(d,names::dg_ex,  y_[DG_EX]);
+  def<double>(d,names::g_in,   y_[G_IN]);
+  def<double>(d,names::dg_in,  y_[DG_IN]);
+  def<double>(d,names::w,      y_[W]);
+  def<double>(d,names::g_n,   y_[G_N]);
+  def<double>(d,names::dg_n,  y_[DG_N]);
+}
+
+void nest::aeif_cond_nmda_alpha::State_::set(const DictionaryDatum& d, const Parameters_&)
+{
+  updateValue<double>(d,names::V_m,   y_[V_M]);
+  updateValue<double>(d,names::g_ex,  y_[G_EX]);
+  updateValue<double>(d,names::dg_ex, y_[DG_EX]);
+  updateValue<double>(d,names::g_in,  y_[G_IN]);
+  updateValue<double>(d,names::dg_in, y_[DG_IN]);
+  updateValue<double>(d,names::w,     y_[W]);
+
+  updateValue<double>(d,names::g_n,  y_[G_N]);
+  updateValue<double>(d,names::dg_n, y_[DG_N]);
+
+  if ( y_[G_EX] < 0 || y_[G_IN] < 0 || y_[G_N] < 0 )
+    throw BadProperty("Conductances must not be negative.");
+}
+
+nest::aeif_cond_nmda_alpha::Buffers_::Buffers_(aeif_cond_nmda_alpha& n)
+  : logger_(n),
+    s_(0),
+    c_(0),
+    e_(0)
+{
+  // The other member variables are left uninitialised or are
+  // automatically initialised by their default constructor.
+}
+
+nest::aeif_cond_nmda_alpha::Buffers_::Buffers_(const Buffers_&, aeif_cond_nmda_alpha& n)
+  : logger_(n),
+    s_(0),
+    c_(0),
+    e_(0)
+{
+  // The other member variables are left uninitialised or are
+  // automatically initialised by their default constructor.
+}
+
+
+/* ---------------------------------------------------------------- 
+ * Default and copy constructor for node, and destructor
+ * ---------------------------------------------------------------- */
+
+nest::aeif_cond_nmda_alpha::aeif_cond_nmda_alpha()
+  : Archiving_Node(), 
+    P_(), 
+    S_(P_),
+    B_(*this)
+{
+    recordablesMap_.create();
+}
+
+nest::aeif_cond_nmda_alpha::aeif_cond_nmda_alpha(const aeif_cond_nmda_alpha& n)
+  : Archiving_Node(n), 
+    P_(n.P_), 
+    S_(n.S_),
+    B_(n.B_, *this)
+{
+}
+
+nest::aeif_cond_nmda_alpha::~aeif_cond_nmda_alpha()
+{
+  // GSL structs only allocated by init_nodes_(), so we need to protect destruction
+  if ( B_.s_ ) gsl_odeiv_step_free(B_.s_);
+  if ( B_.c_ ) gsl_odeiv_control_free(B_.c_);
+  if ( B_.e_ ) gsl_odeiv_evolve_free(B_.e_);
+}
+
+/* ---------------------------------------------------------------- 
+ * Node initialization functions
+ * ---------------------------------------------------------------- */
+
+void nest::aeif_cond_nmda_alpha::init_node_(const Node& proto)
+{
+  const aeif_cond_nmda_alpha& pr = downcast<aeif_cond_nmda_alpha>(proto);
+  P_ = pr.P_;
+  S_ = pr.S_;
+}
+
+void nest::aeif_cond_nmda_alpha::init_state_(const Node& proto)
+{
+  const aeif_cond_nmda_alpha& pr = downcast<aeif_cond_nmda_alpha>(proto);
+  S_ = pr.S_;
+}
+
+void nest::aeif_cond_nmda_alpha::init_buffers_()
+{
+  B_.spike_exc_.clear();       // includes resize
+  B_.spike_inh_.clear();       // includes resize
+  B_.spike_nmda_.clear();       // includes resize
+  B_.currents_.clear();        // includes resize
+//  B_.potentials_.clear_data(); // includes resize
+//  B_.conductances_.clear_data(); // includes resize
+//  B_.aeif_ws_.clear_data();      // includes resize
+  Archiving_Node::clear_history();
+  
+  B_.logger_.reset();
+
+  B_.step_ = Time::get_resolution().get_ms();
+
+  // We must integrate this model with high-precision to obtain decent results
+  B_.IntegrationStep_ = std::min(0.01, B_.step_);
+
+  static const gsl_odeiv_step_type* T1 = gsl_odeiv_step_rkf45;
+  
+  if ( B_.s_ == 0 )
+    B_.s_ = gsl_odeiv_step_alloc (T1, aeif_cond_nmda_alpha::NSTATES);
+  else 
+    gsl_odeiv_step_reset(B_.s_);
+    
+  if ( B_.c_ == 0 )  
+    B_.c_ = gsl_odeiv_control_yp_new (1e-6,1e-6);
+  else
+    gsl_odeiv_control_init(B_.c_, 1e-6, 1e-6, 0.0, 1.0);
+    
+  if ( B_.e_ == 0 )  
+    B_.e_ = gsl_odeiv_evolve_alloc(aeif_cond_nmda_alpha::NSTATES);
+  else 
+    gsl_odeiv_evolve_reset(B_.e_);
+  
+  B_.sys_.function  = aeif_cond_nmda_alpha_dynamics; 
+  B_.sys_.jacobian  = NULL;
+  B_.sys_.dimension =  aeif_cond_nmda_alpha::NSTATES;
+  B_.sys_.params    = reinterpret_cast<void*>(&P_);
+}
+
+void nest::aeif_cond_nmda_alpha::calibrate()
+{
+      B_.logger_.init();  // ensures initialization in case mm connected after Simulate
+  V_.g0_ex_  = 1.0 * numerics::e / P_.tau_syn_ex;
+  V_.g0_in_  = 1.0 * numerics::e / P_.tau_syn_in;
+  V_.g0_n_  = 1.0 * numerics::e / P_.tau_syn_n;
+  V_.RefractoryCounts_ = Time(Time::ms(P_.t_ref_)).get_steps();
+  assert(V_.RefractoryCounts_ >= 0);  // since t_ref_ >= 0, this can only fail in error
+}
+
+/* ---------------------------------------------------------------- 
+ * Update and spike handling functions
+ * ---------------------------------------------------------------- */
+
+void nest::aeif_cond_nmda_alpha::update(Time const & origin, const long_t from, const long_t to)
+{
+  assert ( to >= 0 && (delay) from < Scheduler::get_min_delay() );
+  assert ( from < to );
+  assert ( 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; 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);
+
+      // spikes are handled inside the while-loop
+      // due to spike-driven adaptation
+      if ( S_.r_ > 0 )
+        S_.y_[V_M] = P_.V_reset_;
+      else if ( S_.y_[V_M] >= P_.V_peak_ )
+      {
+	S_.y_[V_M]  = P_.V_reset_;
+	S_.y_[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_[DG_EX] += B_.spike_exc_.get_value(lag) * V_.g0_ex_;
+    S_.y_[DG_IN] += B_.spike_inh_.get_value(lag) * V_.g0_in_;
+     
+    // NMDA input
+
+    
+    S_.y_[DG_N] += B_.spike_nmda_.get_value(lag) /
+	(1 + std::exp(-4.0 * P_.N_gain * 
+		      ((S_.y_[V_M] - P_.N_V_min)/(P_.N_V_max - P_.N_V_min) - 0.5))) * 
+	V_.g0_n_;
+
+
+    // set new input current
+    P_.I_stim = B_.currents_.get_value(lag);
+
+    // voltage logging
+//    B_.potentials_.record_data(origin.get_steps()+lag, S_.y_[V_M]);
+//    B_.conductances_.record_data(origin.get_steps()+lag, 
+//				   std::pair<nest::double_t, nest::double_t>(S_.y_[G_EX], S_.y_[G_IN]));
+//    B_.aeif_ws_.record_data(origin.get_steps()+lag, S_.y_[W]);
+    
+        B_.logger_.record_data(origin.get_steps() + lag);
+  }
+}
+  
+void nest::aeif_cond_nmda_alpha::handle(SpikeEvent & e)
+{
+  assert(e.get_delay() > 0);
+//printf ("\tSynapse: %d\n", e.get_rport());
+  if (e.get_rport() == 0) {
+
+      if(e.get_weight() > 0.0)
+	B_.spike_exc_.add_value(e.get_rel_delivery_steps(network()->get_slice_origin()),
+			     e.get_weight() * e.get_multiplicity());
+      else
+	B_.spike_inh_.add_value(e.get_rel_delivery_steps(network()->get_slice_origin()),
+			     -e.get_weight() * e.get_multiplicity());  // keep conductances positive
+
+  } else if (e.get_rport() == 1) {
+	B_.spike_nmda_.add_value(e.get_rel_delivery_steps(network()->get_slice_origin()),
+			     e.get_weight() * e.get_multiplicity());
+  }
+}
+
+void nest::aeif_cond_nmda_alpha::handle(CurrentEvent& e)
+{
+  assert(e.get_delay() > 0);
+
+  const nest::double_t c=e.get_current();
+  const nest::double_t w=e.get_weight();
+
+  // add weighted current; HEP 2002-10-04
+  B_.currents_.add_value(e.get_rel_delivery_steps(network()->get_slice_origin()), 
+		      w *c);
+}
+
+void nest::aeif_cond_nmda_alpha::handle(DataLoggingRequest& e)
+{
+      B_.logger_.handle(e);
+}
+
+
+#endif //HAVE_GSL_1_11
diff --git a/models/aeif_cond_nmda_alpha.h b/models/aeif_cond_nmda_alpha.h
new file mode 100644
index 0000000..fb9f285
--- /dev/null
+++ b/models/aeif_cond_nmda_alpha.h
@@ -0,0 +1,412 @@
+/*
+ *  aeif_cond_nmda_alpha.h
+ *
+ * Adaptive exponential integrate-and-fire model (Brette and Gerstner) with
+ * alpha-shaped synaptic conductances, as implemented in aeif_cond_alpha.h 
+ * from the nest simulator (v. 1.9.8498).
+ *
+ * This version adds an NMDA synapse-like input with positive
+ * voltage-dependence on the conductance.
+ *
+ * Jan Moren, 2009
+ *
+ * 2011 - Update for nest2
+ *
+ * Original model:
+ *
+ *  Copyright (C) 2005 by
+ *  The NEST Initiative
+ *
+ *  See the file AUTHORS for details.
+ *
+ *  Permission is granted to compile and modify
+ *  this file for non-commercial use.
+ *  See the file LICENSE for details.
+ *
+ */
+
+#ifndef AEIF_COND_NMDA_ALPHA_H
+#define AEIF_COND_NMDA_ALPHA_H
+
+#include "config.h"
+
+#ifdef HAVE_GSL_1_11
+
+#include "nest.h"
+#include "event.h"
+#include "archiving_node.h"
+#include "ring_buffer.h"
+#include "connection.h"
+
+#include "universal_data_logger.h"
+#include "recordables_map.h"
+
+//#include "analog_data_logger.h"
+
+#include <gsl/gsl_errno.h>
+#include <gsl/gsl_matrix.h>
+#include <gsl/gsl_odeiv.h>
+
+/* BeginDocumentation
+Name: aeif_cond_nmda_alpha -  Conductance based exponential integrate-and-fire
+neuron model according to Brette and Gerstner (2005).
+
+Description: aeif_cond_nmda_alpha is the adaptive exponential integrate and
+fire neuron according to Brette and Gerstner (2005).  Synaptic conductances
+are modelled as alpha-functions.
+
+This implementation uses the embedded 4th order Runge-Kutta-Fehlberg solver
+with adaptive stepsize to integrate the differential equation.
+
+The membrane potential is given by the following differential equation: C
+dV/dt= -g_L(V-E_L)+g_L*Delta_T*exp((V-V_T)/Delta_T)-g_e(t)(V-E_e)
+-g_i(t)(V-E_i)-w +I_e
+
+and
+
+tau_w * dw/dt= a(V-E_L) -W
+
+Parameters: 
+The following parameters can be set in the status dictionary.
+
+Dynamic state variables:
+  V_m        double - Membrane potential in mV
+  g_ex       double - Excitatory synaptic conductance in nS.
+  dg_ex      double - First derivative of g_ex in nS/ms
+  g_in       double - Inhibitory synaptic conductance in nS.
+  dg_in      double - First derivative of g_in in nS/ms.
+  w          double - Spike-adaptation current in pA.
+
+Membrane Parameters:
+  C_m        double - Capacity of the membrane in pF
+  t_ref      double - Duration of refractory period in ms. 
+  V_peak     double - Spike detection threshold in mV.
+  V_reset    double - Reset value for V_m after a spike. In mV.
+  E_L        double - Leak reversal potential in mV. 
+  g_L        double - Leak conductance in nS.
+  I_e        double - Constant external input current in pA.
+
+Spike adaptation parameters:
+  a          double - Subthreshold adaptation in nS.
+  b          double - Spike-triggered adaptation in pA.
+  Delta_T    double - Slope factor in mV
+  tau_w      double - Adaptation time constant in ms
+  V_t        double - Spike initiation threshold in mV (V_th can also be used for compatibility).
+
+Synaptic parameters
+  E_ex       double - Excitatory reversal potential in mV.
+  tau_syn_ex double - Rise time of excitatory synaptic conductance in ms (alpha function).
+  E_in       double - Inhibitory reversal potential in mV.
+  tau_syn_in double - Rise time of the inhibitory synaptic conductance in ms (alpha function).
+
+NMDA parameters
+  NMDA_V_max double - Membrane voltage for the upper "shoulder" of the NMDA sigmoid 
+  NMDA_V_min double - Membrane voltage for the lower "shoulder" of the NMDA sigmoid
+  NMDA_gain  double - gain factor for unit sigmoid _before_ scaling 
+  E_n       double - NMDA reversal potential in mV.
+  tau_syn_n  double - Rise time of nmda synaptic conductance in ms (alpha function).
+    
+Author: Marc-Oliver Gewaltig
+
+Sends: SpikeEvent
+
+Receives: SpikeEvent, CurrentEvent, DataLoggingRequest
+
+References: Brette R and Gerstner W (2005) Adaptive Exponential Integrate-and-Fire Model as 
+            an Effective Description of Neuronal Activity. J
+            Neurophysiol 94:3637-3642
+
+SeeAlso: iaf_cond_alpha
+*/
+
+namespace nest
+{
+  class Network;
+
+  class aeif_cond_nmda_alpha:
+  public Archiving_Node
+  {
+    
+  public:        
+    
+    aeif_cond_nmda_alpha();
+    aeif_cond_nmda_alpha(const aeif_cond_nmda_alpha&);
+    ~aeif_cond_nmda_alpha();
+
+    /**
+     * Import sets of overloaded virtual functions.
+     * We need to explicitly include sets of overloaded
+     * virtual functions into the current scope.
+     * According to the SUN C++ FAQ, this is the correct
+     * way of doing things, although all other compilers
+     * happily live without.
+     */
+/* #ifndef IS_BLUEGENE
+   using Node::check_connection;
+#endif */
+    using Node::connect_sender;
+    using Node::handle;
+
+    port check_connection(Connection&, port);
+    
+    void handle(SpikeEvent &);
+    void handle(CurrentEvent &);
+    void handle(DataLoggingRequest &); 
+    
+    port connect_sender(SpikeEvent &, port);
+    port connect_sender(CurrentEvent &, port);
+    port connect_sender(DataLoggingRequest &, port);
+
+    void get_status(DictionaryDatum &) const;
+    void set_status(const DictionaryDatum &);
+    
+  private:
+    
+    void init_node_(const Node& proto);
+    void init_state_(const Node& proto);
+    void init_buffers_();
+    void calibrate();
+    void update(Time const &, const long_t, const long_t);
+	    friend class RecordablesMap<aeif_cond_nmda_alpha>;
+	    friend class UniversalDataLogger<aeif_cond_nmda_alpha>;
+  public:
+
+    // ---------------------------------------------------------------- 
+
+    /** 
+     * Independent parameters of the model. 
+     * These parameters must be passed to the iteration function that
+     * is passed to the GSL ODE solvers. Since the iteration function
+     * is a C++ function with C linkage, the parameters can be stored
+     * in a C++ struct with member functions, as long as we just pass
+     * it by void* from C++ to C++ function. The struct must be public,
+     * though, since the iteration function is a function with C-linkage,
+     * whence it cannot be a member function of iaf_cond_nmda_alpha.
+     * @note One could achieve proper encapsulation by an extra level
+     *       of indirection: Define the iteration function as a member
+     *       function, plus an additional wrapper function with C linkage.
+     *       Then pass a struct containing a pointer to the node and a
+     *       pointer-to-member-function to the iteration function as void*
+     *       to the wrapper function. The wrapper function can then invoke
+     *       the iteration function on the node (Stroustrup, p 418). But
+     *       this appears to involved, and the extra indirections cost.
+     */
+    struct Parameters_ {
+      double_t V_peak_;     //!< Spike detection threshold in mV
+      double_t V_reset_;    //!< Reset Potential in mV
+      double_t t_ref_;      //!< Refractory period in ms
+
+      double_t g_L;         //!< Leak Conductance in nS
+      double_t C_m;         //!< Membrane Capacitance in pF
+      double_t E_ex;        //!< Excitatory reversal Potential in mV
+      double_t E_in;        //!< Inhibitory reversal Potential in mV
+      double_t E_L;         //!< Leak reversal Potential (aka resting potential) in mV
+      double_t Delta_T;     //!< Slope faktor in ms.
+      double_t tau_w;       //!< adaptation time-constant in ms.
+      double_t a;           //!< Subthreshold adaptation in nS.
+      double_t b;           //!< Spike-triggered adaptation in pA
+      double_t V_th;        //!< Spike threshold in mV.
+      double_t t_ref;       //!< Refractory period in ms.
+      double_t tau_syn_ex;  //!< Excitatory synaptic rise time.
+      double_t tau_syn_in;  //!< Excitatory synaptic rise time.
+      double_t I_e;         //!< Intrinsic current in pA.
+
+      double_t N_V_max;      //!< NMDA max membrane voltage 
+      double_t N_V_min;	  //!< NMDA min membrane voltage
+      double_t N_gain;	  //!< NMDA sigmoid gain
+      double_t E_n;        //!< NMDA reversal Potential in mV
+      double_t tau_syn_n;   //!< NMDA synaptic rise time.
+  
+      /** 
+       * External input current from CurrentEvents.
+       * This is not a parameter but a variable. It is still placed here, since
+       * it needs to be passed to the iteration function. We thus avoid the need
+       * of an additional wrapper structure. It is not revealed or manipulateable.
+       */
+      double_t I_stim;      //!< External Stimulus in pA
+  
+      Parameters_();  //!< Sets default parameter values
+
+      void get(DictionaryDatum&) const;  //!< Store current values in dictionary
+      void set(const DictionaryDatum&);  //!< Set values from dicitonary
+    };
+  
+  /**
+   * Enumeration identifying elements in state array State_::y_.
+   * The state vector must be passed to GSL as a C array. This enum
+   * identifies the elements of the vector. It must be public to be
+   * accessible from the iteration function.
+   */  
+  enum Statevars
+  {
+    V_M   = 0,
+    DG_EX    ,  // 1
+    G_EX     ,  // 2
+    DG_IN    ,  // 3
+    G_IN     ,  // 4
+    W        ,  // 5
+    DG_N    ,   // 6
+    G_N     ,   // 7
+    NSTATES
+  };
+    
+    
+  private:
+    // ---------------------------------------------------------------- 
+
+    /**
+     * State variables of the model.
+     * @note Copy constructor and assignment operator required because
+     *       of C-style array.
+     */
+    struct State_ {
+      double_t y_[NSTATES];  //!< neuron state, must be C-array for GSL solver
+      int_t    r_;           //!< number of refractory steps remaining
+
+      State_(const Parameters_&);  //!< Default initialization
+      State_(const State_&);
+      State_& operator=(const State_&);
+
+      void get(DictionaryDatum&) const;
+      void set(const DictionaryDatum&, const Parameters_&);
+    };    
+
+    // ---------------------------------------------------------------- 
+
+    /**
+     * Buffers of the model.
+     */
+    struct Buffers_ {
+	Buffers_(aeif_cond_nmda_alpha&);
+	Buffers_(const Buffers_&, aeif_cond_nmda_alpha&);
+//	Buffers_(); //!<Sets buffer pointers to 0
+      /** buffers and sums up incoming spikes/currents */
+      RingBuffer spike_exc_;
+      RingBuffer spike_inh_;
+      RingBuffer spike_nmda_;
+      RingBuffer currents_;
+	UniversalDataLogger<aeif_cond_nmda_alpha> logger_;
+      
+//	AnalogDataLogger<PotentialRequest>           potentials_;
+//      AnalogDataLogger<SynapticConductanceRequest> conductances_;
+//      AnalogDataLogger<AeifWRequest>               aeif_ws_;
+
+      /** GSL ODE stuff */
+      gsl_odeiv_step*    s_;    //!< stepping function
+      gsl_odeiv_control* c_;    //!< adaptive stepsize control function
+      gsl_odeiv_evolve*  e_;    //!< evolution function
+      gsl_odeiv_system   sys_;  //!< struct describing system
+      
+      // IntergrationStep_ should be reset with the neuron on ResetNetwork,
+      // but remain unchanged during calibration. Since it is initialized with
+      // step_, and the resolution cannot change after nodes have been created,
+      // it is safe to place both here.
+      double_t step_;           //!< step size in ms
+      double   IntegrationStep_;//!< current integration time step, updated by GSL
+    };
+
+     // ---------------------------------------------------------------- 
+
+     /**
+      * Internal variables of the model.
+      */
+     struct Variables_ { 
+      /** initial value to normalise excitatory synaptic conductance */
+      double_t g0_ex_; 
+   
+      /** initial value to normalise inhibitory synaptic conductance */
+      double_t g0_in_;    
+
+      /** initial value to normalise NMDA synaptic conductance */
+      double_t g0_n_; 
+
+      int_t    RefractoryCounts_;
+     };
+
+    // Access functions for UniversalDataLogger -------------------------------
+    
+    //! Read out state vector elements, used by UniversalDataLogger
+    template <Statevars elem>
+    double_t get_y_elem_() const { return S_.y_[elem]; }
+    // ---------------------------------------------------------------- 
+
+    Parameters_ P_;
+    State_      S_;
+    Variables_  V_;
+    Buffers_    B_;
+    static RecordablesMap<aeif_cond_nmda_alpha> recordablesMap_;
+  };
+
+  inline  
+  port aeif_cond_nmda_alpha::check_connection(Connection& c, port receptor_type)
+  {
+
+    //  printf ("\tCheckSynapse: %d\n", receptor_type);
+    SpikeEvent e;
+    e.set_sender(*this);
+    c.check_event(e);
+    return c.get_target()->connect_sender(e, receptor_type);
+  }
+
+  inline
+  port aeif_cond_nmda_alpha::connect_sender(SpikeEvent&, port receptor_type)
+  {
+    // 0: normal synapse, 1: NMDA synapse
+    //  printf ("\n\tSynapse: %d \n\n", receptor_type);
+    if (receptor_type >= 2)
+      throw UnknownReceptorType(receptor_type, get_name());
+    return receptor_type;
+  }
+ 
+  inline
+  port aeif_cond_nmda_alpha::connect_sender(CurrentEvent&, port receptor_type)
+  {
+    if (receptor_type != 0)
+      throw UnknownReceptorType(receptor_type, get_name());
+    return 0;
+  }
+ 
+  inline
+  port aeif_cond_nmda_alpha::connect_sender(DataLoggingRequest& dlr, port receptor_type)
+  {
+    if (receptor_type != 0)
+      throw UnknownReceptorType(receptor_type, get_name());
+    //B_.potentials_.connect_logging_device(pr);
+    //return 0;
+      return B_.logger_.connect_logging_device(dlr, recordablesMap_);
+  }
+
+
+  inline
+  void aeif_cond_nmda_alpha::get_status(DictionaryDatum &d) const
+  {
+    P_.get(d);
+    S_.get(d);
+    Archiving_Node::get_status(d);
+
+    (*d)[names::recordables] = recordablesMap_.get_list();
+  }
+
+  inline
+  void aeif_cond_nmda_alpha::set_status(const DictionaryDatum &d)
+  {
+    Parameters_ ptmp = P_;  // temporary copy in case of errors
+    ptmp.set(d);                       // throws if BadProperty
+    State_      stmp = S_;  // temporary copy in case of errors
+    stmp.set(d, ptmp);                 // throws if BadProperty
+
+    // We now know that (ptmp, stmp) are consistent. We do not 
+    // write them back to (P_, S_) before we are also sure that 
+    // the properties to be set in the parent class are internally 
+    // consistent.
+    Archiving_Node::set_status(d);
+
+    // if we get here, temporaries contain consistent set of properties
+    P_ = ptmp;
+    S_ = stmp;
+  }
+  
+} // namespace
+
+#endif //HAVE_GSL
+#endif //AEIF_COND_NMDA_ALPHA_H
-- 
1.8.1.2


From bde56ea180450dfdd5f5604d2a65f39756b9248d Mon Sep 17 00:00:00 2001
From: Jan Moren <jan.moren@gmail.com>
Date: Tue, 6 Aug 2013 15:00:24 +0900
Subject: [PATCH 3/3] add synth_integrator model

---
 models/synth_integrator.cpp | 219 ++++++++++++++++++++++++++++++++++
 models/synth_integrator.h   | 285 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 504 insertions(+)
 create mode 100644 models/synth_integrator.cpp
 create mode 100644 models/synth_integrator.h

diff --git a/models/synth_integrator.cpp b/models/synth_integrator.cpp
new file mode 100644
index 0000000..e84e2c7
--- /dev/null
+++ b/models/synth_integrator.cpp
@@ -0,0 +1,219 @@
+/*
+ *  synth_integrator.cpp
+ *
+ *  This file is part of NEST
+ *
+ *  Copyright (C) 2004-2008 by
+ *  The NEST Initiative
+ *
+ *  See the file AUTHORS for details.
+ *
+ *  Permission is granted to compile and modify
+ *  this file for non-commercial use.
+ *  See the file LICENSE for details.
+ *
+ *  (C) 2010 Jan Morén 
+ */
+
+//#include "scmodules_names.h"
+#include "exceptions.h"
+#include "synth_integrator.h"
+#include "network.h"
+#include "dict.h"
+#include "integerdatum.h"
+#include "doubledatum.h"
+#include "dictutils.h"
+#include "numerics.h"
+//#include "analog_data_logger_impl.h"
+#include "universal_data_logger_impl.h"
+
+#include <limits>
+
+/* ---------------------------------------------------------------- 
+ * Recordables map
+ * ---------------------------------------------------------------- */
+
+nest::RecordablesMap<nest::synth_integrator> nest::synth_integrator::recordablesMap_;
+
+using namespace nest;
+
+namespace nest {
+/*
+   * Override the create() method with one call to RecordablesMap::insert_() 
+   * for each quantity to be recorded.
+   */
+    template <>
+    void RecordablesMap<nest::synth_integrator>::create()
+    {
+	// use standard names whereever you can for consistency!
+	//insert_(nest::names::V_m, &nest::synth_integrator::get_V_m_);
+	insert_("weighted_spikes_ex", &nest::synth_integrator::get_weighted_spikes_ex_);
+	insert_("weighted_spikes_in", &nest::synth_integrator::get_weighted_spikes_in_);
+    }
+}
+/* ---------------------------------------------------------------- 
+ * Default constructors defining default parameters and state
+ * ---------------------------------------------------------------- */
+
+nest::synth_integrator::Parameters_::Parameters_()
+    : Smax_	    ( 1000.0    ),	// integrated value for 1/ms spike
+    Gamma_	    (1.0    ),		//  gamma scale
+    Reset_	    (10.0    )		//  reset input threshold
+{}
+
+nest::synth_integrator::State_::State_()
+    : acc_   (0.0)
+{}
+
+/* ---------------------------------------------------------------- 
+ * Paramater and state extractions and manipulation functions
+ * ---------------------------------------------------------------- */
+
+void nest::synth_integrator::Parameters_::get(DictionaryDatum &d) const
+{
+
+    def<double>(d, names::Smax, Smax_);
+    def<double>(d, names::Gamma, Gamma_);
+    def<double>(d, names::Reset, Reset_);
+}
+
+void nest::synth_integrator::Parameters_::set(const DictionaryDatum& d)
+{
+    updateValue<double>(d, names::Gamma, Gamma_);
+    updateValue<double>(d, names::Reset, Reset_);
+    updateValue<double>(d, names::Smax, Smax_);
+}
+
+void nest::synth_integrator::State_::get(DictionaryDatum &d, const Parameters_& p) const
+{
+    //  def<double>(d, nest::names::V_m, y3_ + p.U0_); // Membrane potential
+}
+
+void nest::synth_integrator::State_::set(const DictionaryDatum& d, const Parameters_& p)
+{
+    //if ( updateValue<double>(d, nest::names::V_m, y3_) )
+    //  y3_ -= p.U0_;
+}
+nest::synth_integrator::Buffers_::Buffers_(synth_integrator& n)
+  : logger_(n)
+{}
+
+nest::synth_integrator::Buffers_::Buffers_(const Buffers_&, synth_integrator& n)
+  : logger_(n)
+{}
+/* ---------------------------------------------------------------- 
+ * Default and copy constructor for node
+ * ---------------------------------------------------------------- */
+
+    nest::synth_integrator::synth_integrator()
+: Archiving_Node(), 
+    P_(), 
+    S_(),
+    B_(*this)
+{
+  recordablesMap_.create();
+}
+
+    nest::synth_integrator::synth_integrator(const synth_integrator& n)
+: Archiving_Node(n), 
+    P_(n.P_), 
+    S_(n.S_),
+    B_(n.B_, *this)
+{}
+
+/* ---------------------------------------------------------------- 
+ * Node initialization functions
+ * ---------------------------------------------------------------- */
+
+void nest::synth_integrator::init_node_(const Node& proto)
+{
+    const synth_integrator& pr = downcast<synth_integrator>(proto);
+    P_ = pr.P_;
+    S_ = pr.S_;
+}
+
+void nest::synth_integrator::init_state_(const Node& proto)
+{
+    const synth_integrator& pr = downcast<synth_integrator>(proto);
+    S_ = pr.S_;
+}
+
+void nest::synth_integrator::init_buffers_()
+{
+    B_.ex_spikes_.clear();       // includes resize
+    B_.in_spikes_.clear();       // includes resize
+    B_.logger_.reset();
+    Archiving_Node::clear_history();
+}
+
+void nest::synth_integrator::calibrate()
+{
+    B_.logger_.init();  // ensures initialization in case mm connected after Simulate
+    V_.t_res = Time::get_resolution().get_ms(); 
+}
+
+/* ---------------------------------------------------------------- 
+ * Update and spike handling functions
+ */
+
+void nest::synth_integrator::update(Time const & origin, const long_t from, const long_t to)
+{
+    assert(to >= 0 && (delay) from < Scheduler::get_min_delay());
+    assert(from < to);
+
+    double rn, prop;
+
+    double resetc = 0.0;
+
+    for ( long_t lag = from ; lag < to ; ++lag )
+    {
+
+	V_.weighted_spikes_ex_ = B_.ex_spikes_.get_value(lag);	
+	V_.weighted_spikes_in_ = B_.in_spikes_.get_value(lag);
+
+	S_.acc_ += V_.weighted_spikes_ex_;
+	
+
+	resetc += (-V_.weighted_spikes_in_);
+	if (resetc > P_.Reset_)
+	    S_.acc_ = 0.0;
+
+	prop = pow((S_.acc_/(P_.Smax_)),(1.0/P_.Gamma_));
+	rn = random()/(RAND_MAX+1.0)/V_.t_res;
+
+	if (rn<= prop) { 
+	    SpikeEvent se;
+	    network()->send(*this, se, lag);
+	}
+    
+	B_.logger_.record_data(origin.get_steps() + lag);
+    }                           
+}
+
+
+void nest::synth_integrator::handle(SpikeEvent & e)
+{
+    assert(e.get_delay() > 0);
+
+    //printf ("\tSynapse: %d\n", e.get_rport());
+    if (e.get_rport()==0) {
+	if(e.get_weight() > 0.0)
+	    B_.ex_spikes_.add_value(e.get_rel_delivery_steps(network()->get_slice_origin()),
+		    e.get_weight() * e.get_multiplicity() );
+	else if (e.get_weight() < 0.0)
+	    B_.in_spikes_.add_value(e.get_rel_delivery_steps(network()->get_slice_origin()),
+		    e.get_weight() * e.get_multiplicity() );
+    }
+}
+
+void nest::synth_integrator::handle(CurrentEvent& e)
+{
+    assert(e.get_delay() > 0);
+}
+
+void nest::synth_integrator::handle(DataLoggingRequest& e)
+{
+    B_.logger_.handle(e);
+}
+
+// namespace
diff --git a/models/synth_integrator.h b/models/synth_integrator.h
new file mode 100644
index 0000000..d7667ab
--- /dev/null
+++ b/models/synth_integrator.h
@@ -0,0 +1,285 @@
+/*
+ *  synth_integrator.h
+ *
+ *  This file is part of NEST
+ *
+ *  Copyright (C) 2004-2008 by
+ *  The NEST Initiative
+ *
+ *  See the file AUTHORS for details.
+ *
+ *  Permission is granted to compile and modify
+ *  this file for non-commercial use.
+ *  See the file LICENSE for details.
+ *
+ *  (C) 2010 Jan Morén 
+ *
+ * This version is for nest2 prereleases. The logging API has changed so we
+ * can no longer use the same module code for different nest versions.
+ *
+ */
+
+#ifndef SYNTH_INTEGRATOR
+#define SYNTH_INTEGRATOR
+
+#include "nest.h"
+#include "event.h"
+#include "archiving_node.h"
+#include "ring_buffer.h"
+#include "connection.h"
+#include "universal_data_logger.h"
+#include "recordables_map.h"
+
+//#include "analog_data_logger.h"
+
+namespace nest
+{
+
+  class Network;
+
+  /* BeginDocumentation
+Name: synth_integrator - Input integrator.
+
+Description:
+
+  synth integrator takes weighted spiking input, sums it over time, and emits 
+  spikes at a rate proportional to the summed input. 
+
+  This is intended as a synthetic replacement or placeholder to a real spike
+  integrator circuit. Useful for testing networks where an integrating input 
+  is assumed, or to tune a real integrating circuit.
+
+  Hacked-up from iaf_psc_nmda_alpha
+
+Parameters: 
+
+  The following parameters can be set in the status dictionary.
+
+    Smax    double	The accumulated spike*weight at which point the 
+			model emits 1 spike/ms.
+    Gamma   double	nonlinear scaling factor
+    Reset   double	Negative rate input for resetting the integrator
+
+
+Receives: SpikeEvent, DataLoggingRequest
+
+Author:  February 2010, Moren
+*/
+
+  /**
+   * Leaky integrate-and-fire neuron with alpha-shaped PSCs.
+   */
+  class synth_integrator : public Archiving_Node
+    {
+
+	public:        
+
+	    typedef Node base;
+
+	    synth_integrator();
+	    synth_integrator(const synth_integrator&);
+
+	    /**
+	     * Import sets of overloaded virtual functions.
+	     * We need to explicitly include sets of overloaded
+	     * virtual functions into the current scope.
+	     * According to the SUN C++ FAQ, this is the correct
+	     * way of doing things, although all other compilers
+	     * happily live without.
+	     */
+/*#ifndef IS_BLUEGENE
+	    using Node::check_connection;
+#endif*/
+	    using Node::connect_sender;
+	    using Node::handle;
+
+	    port check_connection(Connection&, port);
+
+	    void handle(SpikeEvent &);
+	    void handle(CurrentEvent &);
+	    //void handle(PotentialRequest &);
+	    void handle(DataLoggingRequest &);
+
+	    port connect_sender(SpikeEvent&, port);
+	    port connect_sender(CurrentEvent&, port);
+	    //port connect_sender(PotentialRequest&, port);
+	    port connect_sender(DataLoggingRequest&, port);
+
+	    void get_status(DictionaryDatum &) const;
+	    void set_status(const DictionaryDatum &);
+
+	private:
+
+	    void init_node_(const Node& proto);
+	    void init_state_(const Node& proto);
+	    void init_buffers_();
+	    void calibrate();
+
+	    void update(Time const &, const long_t, const long_t);
+	    friend class RecordablesMap<synth_integrator>;
+	    friend class UniversalDataLogger<synth_integrator>;
+
+	    // ---------------------------------------------------------------- 
+
+	    /** 
+	     * Independent parameters of the model. 
+	     */
+	    struct Parameters_ {
+
+		/** event limit - at this point we do one spike per ms **/
+		double_t Smax_;
+
+		/** gamma factor for probability scaling **/
+		double_t Gamma_;
+		double_t Reset_;
+
+
+
+		Parameters_();  //!< Sets default parameter values
+
+		void get(DictionaryDatum&) const;  //!< Store current values in dictionary
+		void set(const DictionaryDatum&);  //!< Set values from dicitonary
+	    };
+
+	    // ---------------------------------------------------------------- 
+
+	    /**
+	     * State variables of the model.
+	     */
+	    struct State_ {
+		double_t acc_; // Currently accumulated events 
+
+		State_();  //!< Default initialization
+
+		void get(DictionaryDatum&, const Parameters_&) const;
+		void set(const DictionaryDatum&, const Parameters_&);
+	    };    
+
+	    // ---------------------------------------------------------------- 
+
+	    /**
+	     * Buffers of the model.
+	     */
+	    struct Buffers_ {
+		Buffers_(synth_integrator&);
+		Buffers_(const Buffers_&, synth_integrator&);
+		/** buffers and summs up incoming spikes/currents */
+		RingBuffer ex_spikes_;
+		RingBuffer in_spikes_;
+		//RingBuffer currents_;
+
+		/** Buffer for membrane potential. */
+		//AnalogDataLogger<PotentialRequest> potentials_;
+		UniversalDataLogger<synth_integrator> logger_;
+	    };
+
+	    // ---------------------------------------------------------------- 
+
+	    /**
+	     * Internal variables of the model.
+	     */
+	    struct Variables_ { 
+
+		double_t t_res;	    // Time resolution
+		double_t weighted_spikes_ex_; // Not sure we need or want these
+		double_t weighted_spikes_in_;
+
+	    };
+
+	    // Access functions for UniversalDataLogger -------------------------------
+
+	    //! Read out the real membrane potential
+//	    double_t get_V_m_() const { return S_.y3_ + P_.U0_; }
+
+	    double_t get_weighted_spikes_ex_() const { return V_.weighted_spikes_ex_; }
+	    double_t get_weighted_spikes_in_() const { return V_.weighted_spikes_in_; }
+
+	    // ---------------------------------------------------------------- 
+
+	    /**
+	     * @defgroup synth_integrator_data
+	     * Instances of private data structures for the different types
+	     * of data pertaining to the model.
+	     * @note The order of definitions is important for speed.
+	     * @{
+	     */   
+	    Parameters_ P_;
+	    State_      S_;
+	    Variables_  V_;
+	    Buffers_    B_;
+	    /** @} */
+	    
+	    static RecordablesMap<synth_integrator> recordablesMap_;
+    };
+
+  inline
+      port synth_integrator::check_connection(Connection& c, port receptor_type)
+      {
+	  // printf ("\tCheckSynapse: %d\n", receptor_type);
+
+	  SpikeEvent e;
+	  e.set_sender(*this);
+	  c.check_event(e);
+	  return c.get_target()->connect_sender(e, receptor_type);
+      }
+
+  inline
+      port synth_integrator::connect_sender(SpikeEvent&, port receptor_type)
+      {
+	  /* 0: normal receptor; 1: NMDA receptor */
+	  //  printf ("\n\tSynapse: %d \n\n", receptor_type);
+
+	  //if (receptor_type >= 1)
+	  if (receptor_type != 0)
+	      throw UnknownReceptorType(receptor_type, get_name());
+	  return receptor_type;
+      }
+
+  inline
+      port synth_integrator::connect_sender(CurrentEvent&, port receptor_type)
+      {
+	  if (receptor_type != 0)
+	      throw UnknownReceptorType(receptor_type, get_name());
+	  return 0;
+      }
+
+  inline
+      port synth_integrator::connect_sender(DataLoggingRequest& dlr, port receptor_type)
+      {
+	  if (receptor_type != 0)
+	      throw UnknownReceptorType(receptor_type, get_name());
+	  //B_.potentials_.connect_logging_device(pr);
+	  //return 0;
+	  return B_.logger_.connect_logging_device(dlr, recordablesMap_);
+      }
+  inline
+      void synth_integrator::get_status(DictionaryDatum &d) const
+      {
+	  P_.get(d);
+	  S_.get(d, P_);
+	  Archiving_Node::get_status(d);
+	  (*d)[names::recordables] = recordablesMap_.get_list();
+      }
+
+  inline
+      void synth_integrator::set_status(const DictionaryDatum &d)
+      {
+	  Parameters_ ptmp = P_;  // temporary copy in case of errors
+	  ptmp.set(d);                       // throws if BadProperty
+	  State_      stmp = S_;  // temporary copy in case of errors
+	  stmp.set(d, ptmp);                 // throws if BadProperty
+
+	  // We now know that (ptmp, stmp) are consistent. We do not 
+	  // write them back to (P_, S_) before we are also sure that 
+	  // the properties to be set in the parent class are internally 
+	  // consistent.
+	  Archiving_Node::set_status(d);
+
+	  // if we get here, temporaries contain consistent set of properties
+	  P_ = ptmp;
+	  S_ = stmp;
+      }
+
+} // namespace
+
+#endif /* #ifndef SYNTH_INTEGRATOR*/
-- 
1.8.1.2