diff --git a/include/mechanisms/hh_verb.hpp b/include/mechanisms/hh_verb.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c3999107115f7d21c1c6ac4a70c616796a016e2d
--- /dev/null
+++ b/include/mechanisms/hh_verb.hpp
@@ -0,0 +1,281 @@
+#pragma once
+
+#include <cmath>
+#include <limits>
+
+#include <mechanism.hpp>
+#include <mechanism_interface.hpp>
+#include <algorithms.hpp>
+
+namespace nest{ namespace mc{ namespace mechanisms{ namespace hh{
+
+template<typename T, typename I>
+class mechanism_hh : public mechanism<T, I> {
+public:
+    using base = mechanism<T, I>;
+    using value_type  = typename base::value_type;
+    using size_type   = typename base::size_type;
+    using vector_type = typename base::vector_type;
+    using view_type   = typename base::view_type;
+    using index_type  = typename base::index_type;
+    using index_view  = typename index_type::view_type;
+    using indexed_view_type= typename base::indexed_view_type;
+    using ion_type = typename base::ion_type;
+
+    struct Ionna {
+        view_type ena;
+        view_type ina;
+        index_type index;
+        std::size_t memory() const { return sizeof(size_type)*index.size(); }
+        std::size_t size() const { return index.size(); }
+    };
+    Ionna ion_na;
+    struct Ionk {
+        view_type ek;
+        view_type ik;
+        index_type index;
+        std::size_t memory() const { return sizeof(size_type)*index.size(); }
+        std::size_t size() const { return index.size(); }
+    };
+    Ionk ion_k;
+
+    mechanism_hh(view_type vec_v, view_type vec_i, index_view node_index)
+    :   base(vec_v, vec_i, node_index)
+    {
+        size_type num_fields = 15;
+
+        // calculate the padding required to maintain proper alignment of sub arrays
+        auto alignment  = data_.alignment();
+        auto field_size_in_bytes = sizeof(value_type)*size();
+        auto remainder  = field_size_in_bytes % alignment;
+        auto padding    = remainder ? (alignment - remainder)/sizeof(value_type) : 0;
+        auto field_size = size()+padding;
+
+        // allocate memory
+        data_ = vector_type(field_size * num_fields);
+        data_(memory::all) = std::numeric_limits<value_type>::quiet_NaN();
+
+        // asign the sub-arrays
+        gnabar          = data_(0*field_size, 1*size());
+        minf            = data_(1*field_size, 2*size());
+        h               = data_(2*field_size, 3*size());
+        m               = data_(3*field_size, 4*size());
+        gl              = data_(4*field_size, 5*size());
+        gkbar           = data_(5*field_size, 6*size());
+        el              = data_(6*field_size, 7*size());
+        ninf            = data_(7*field_size, 8*size());
+        mtau            = data_(8*field_size, 9*size());
+        gna             = data_(9*field_size, 10*size());
+        gk              = data_(10*field_size, 11*size());
+        n               = data_(11*field_size, 12*size());
+        hinf            = data_(12*field_size, 13*size());
+        ntau            = data_(13*field_size, 14*size());
+        htau            = data_(14*field_size, 15*size());
+
+        // set initial values for variables and parameters
+        std::fill(gnabar.data(), gnabar.data()+size(), 1.2);
+        std::fill(gl.data(), gl.data()+size(), 0.0029999999999999997);
+        std::fill(gkbar.data(), gkbar.data()+size(), 0.35999999999999997);
+        std::fill(el.data(), el.data()+size(), -54.299999999999997);
+
+    }
+
+    using base::size;
+
+    std::size_t memory() const override {
+        auto s = std::size_t{0};
+        s += data_.size()*sizeof(value_type);
+        s += ion_na.memory();
+        s += ion_k.memory();
+        return s;
+    }
+
+    void set_params(value_type t_, value_type dt_) override {
+        t = t_;
+        dt = dt_;
+    }
+
+    std::string name() const override {
+        return "hh";
+    }
+
+    mechanismKind kind() const override {
+        return mechanismKind::density;
+    }
+
+    bool uses_ion(ionKind k) const override {
+        switch(k) {
+            case ionKind::na : return true;
+            case ionKind::ca : return false;
+            case ionKind::k  : return true;
+        }
+        return false;
+    }
+
+    void set_ion(ionKind k, ion_type& i) override {
+        using nest::mc::algorithms::index_into;
+        if(k==ionKind::na) {
+            ion_na.index = index_into(i.node_index(), node_index_);
+            ion_na.ina = i.current();
+            ion_na.ena = i.reversal_potential();
+            return;
+        }
+        if(k==ionKind::k) {
+            ion_k.index = index_into(i.node_index(), node_index_);
+            ion_k.ik = i.current();
+            ion_k.ek = i.reversal_potential();
+            return;
+        }
+        throw std::domain_error(nest::mc::util::pprintf("mechanism % does not support ion type\n", name()));
+    }
+
+    void nrn_state() {
+        const indexed_view_type vec_v(vec_v_, node_index_);
+        int n_ = node_index_.size();
+        for(int i_=0; i_<n_; ++i_) {
+            value_type v = vec_v[i_];
+            rates(i_, v);
+            m[i_] = minf[i_]+(m[i_]-minf[i_])*exp( -dt/mtau[i_]);
+            h[i_] = hinf[i_]+(h[i_]-hinf[i_])*exp( -dt/htau[i_]);
+            n[i_] = ninf[i_]+(n[i_]-ninf[i_])*exp( -dt/ntau[i_]);
+        }
+    }
+
+    void rates(const int i_, value_type v) {
+        value_type ll3_, ll1_, ll0_, alpha, beta, ll2_, sum, q10;
+        q10 = std::pow( 3, (celsius- 6.2999999999999998)/ 10);
+        //ll2_ =  -v+ 40;
+        ll2_ =  -(v+ 40);
+        ll0_ = ll2_/(exp(ll2_/ 10)- 1);
+        alpha =  0.10000000000000001*ll0_;
+        beta =  4*exp( -(v+ 65)/ 18);
+
+        std::cout << "v  " << v << "\n";
+        //std::cout << "m (alpha, beta) : " << alpha << " " << beta << "\n";
+
+        sum = alpha+beta;
+        mtau[i_] =  1/q10*sum;
+        minf[i_] = alpha/sum;
+
+        //////////////////////////////////////////////////////////
+
+        alpha =  0.070000000000000007*exp( -(v+ 65)/ 20);
+        beta =  1/(exp( -(v+ 35)/ 10)+ 1);
+
+        //std::cout << "h (alpha, beta) : " << alpha << " " << beta << "\n";
+
+        sum = alpha+beta;
+        htau[i_] =  1/q10*sum;
+        hinf[i_] = alpha/sum;
+
+        //////////////////////////////////////////////////////////
+
+        //ll3_ =  -v+ 55; // TODO : inlining is breaking
+        ll3_ =  -(v+ 55);
+        ll1_ = ll3_/(exp(ll3_/ 10)- 1);
+        alpha =  0.01*ll1_;
+        beta =  0.125*exp( -(v+ 65)/ 80);
+
+        //std::cout << "n (alpha, beta) : " << alpha << " " << beta << "\n";
+
+        sum = alpha+beta;
+        ntau[i_] =  1/q10*sum;
+        ninf[i_] = alpha/sum;
+    }
+
+    void nrn_current() {
+        const indexed_view_type ion_ek(ion_k.ek, ion_k.index);
+        indexed_view_type ion_ina(ion_na.ina, ion_na.index);
+        const indexed_view_type ion_ena(ion_na.ena, ion_na.index);
+        indexed_view_type ion_ik(ion_k.ik, ion_k.index);
+        indexed_view_type vec_i(vec_i_, node_index_);
+        const indexed_view_type vec_v(vec_v_, node_index_);
+        int n_ = node_index_.size();
+        for(int i_=0; i_<n_; ++i_) {
+            value_type ek = ion_ek[i_];
+            value_type ena = ion_ena[i_];
+            value_type v = vec_v[i_];
+            value_type il, ina, ik, current_;
+            gna[i_] = gnabar[i_]*m[i_]*m[i_]*m[i_]*h[i_];
+            ina = gna[i_]*(v-ena);
+            current_ = ina;
+            gk[i_] = gkbar[i_]*n[i_]*n[i_]*n[i_]*n[i_];
+            ik = gk[i_]*(v-ek);
+            current_ = current_+ik;
+            il = gl[i_]*(v-el[i_]);
+            current_ = current_+il;
+            ion_ina[i_] += ina;
+            ion_ik[i_] += ik;
+            vec_i[i_] += current_;
+            printf("i = (l+k+na) %18.16f = %18.16f %18.16f %18.16f\n",
+                   current_, il, ik, ina);
+        }
+    }
+
+    void nrn_init() {
+        const indexed_view_type vec_v(vec_v_, node_index_);
+        int n_ = node_index_.size();
+        for(int i_=0; i_<n_; ++i_) {
+            value_type v = vec_v[i_];
+            rates(i_, v);
+            m[i_] = minf[i_];
+            h[i_] = hinf[i_];
+            n[i_] = ninf[i_];
+            printf("initial conditions for m, h, n : %16.14f %16.14f %16.14f\n", m[0], h[0], n[0]);
+        }
+    }
+
+    vector_type data_;
+    view_type gnabar;
+    view_type minf;
+    view_type h;
+    view_type m;
+    view_type gl;
+    view_type gkbar;
+    view_type el;
+    view_type ninf;
+    view_type mtau;
+    view_type gna;
+    view_type gk;
+    view_type n;
+    view_type hinf;
+    view_type ntau;
+    view_type htau;
+    value_type t = std::numeric_limits<value_type>::quiet_NaN();
+    value_type dt = std::numeric_limits<value_type>::quiet_NaN();
+    value_type celsius = 6.3; // TODO change from 37
+
+    using base::vec_v_;
+    using base::vec_i_;
+    using base::node_index_;
+
+};
+
+template<typename T, typename I>
+struct helper : public mechanism_helper<T, I> {
+    using base = mechanism_helper<T, I>;
+    using index_view  = typename base::index_view;
+    using view_type  = typename base::view_type;
+    using mechanism_ptr_type  = typename base::mechanism_ptr_type;
+    using mechanism_type = mechanism_hh<T, I>;
+
+    std::string
+    name() const override
+    {
+        return "hh";
+    }
+
+    mechanism_ptr<T,I>
+    new_mechanism(view_type vec_v, view_type vec_i, index_view node_index) const override
+    {
+        return nest::mc::mechanisms::make_mechanism<mechanism_type>(vec_v, vec_i, node_index);
+    }
+
+    void
+    set_parameters(mechanism_ptr_type&, parameter_list const&) const override
+    {
+    }
+
+};
+
+}}}} // namespaces