arbor/backends/multicore/mechanism.cpp
// The derived class (typically generated code from modcc) holds pointers that need
// to be set to point inside the shared state, or into the allocated parameter/variable
// data block.
//
// In ths SIMD case, there may be a 'tail' of values that correspond to a partial
// SIMD value when the width is not a multiple of the SIMD data width. In this
// implementation we do not use SIMD masking to avoid tail values, but instead
// extend the vectors to a multiple of the SIMD width: sites/CVs corresponding to
// these past-the-end values are given a weight of zero, and any corresponding
// indices into shared state point to the last valid slot.
The derived class (typically generated code from modcc) holds pointers that need
to be set to point inside the shared state, or into the allocated parameter/variable
data block.

In ths SIMD case, there may be a 'tail' of values that correspond to a partial
SIMD value when the width is not a multiple of the SIMD data width. In this
implementation we do not use SIMD masking to avoid tail values, but instead
extend the vectors to a multiple of the SIMD width: sites/CVs corresponding to
these past-the-end values are given a weight of zero, and any corresponding
indices into shared state point to the last valid slot.
The derived class ( typically generated code from modcc ) holds pointers that need to be set to point inside the shared state or into the allocated parameter / variable data block . In ths SIMD case there may be a ' tail ' of values that correspond to a partial SIMD value when the width is not a multiple of the SIMD data width . In this implementation we do not use SIMD masking to avoid tail values but instead extend the vectors to a multiple of the SIMD width : sites / CVs corresponding to these past - the - end values are given a weight of zero and any corresponding indices into shared state point to the last valid slot .
void mechanism::instantiate(unsigned id, backend::shared_state& shared, const mechanism_overrides& overrides, const mechanism_layout& pos_data) {
    using util::make_range;
    for (auto &kv: overrides.globals) {
        if (auto opt_ptr = value_by_key(global_table(), kv.first)) {
            value_type& global = *opt_ptr.value();
            global = kv.second;
        }
        else {
            throw arbor_internal_error("multicore/mechanism: no such mechanism global");
        }
    }
    mult_in_place_ = !pos_data.multiplicity.empty();
    util::padded_allocator<> pad(shared.alignment);
    mechanism_id_ = id;
    width_ = pos_data.cv.size();
    vec_ci_   = shared.cv_to_intdom.data();
    vec_t_    = shared.time.data();
    vec_t_to_ = shared.time_to.data();
    vec_dt_   = shared.dt_cv.data();
    vec_v_    = shared.voltage.data();
    vec_i_    = shared.current_density.data();
    vec_g_    = shared.conductivity.data();
    temperature_degC_ = shared.temperature_degC.data();
    diam_um_  = shared.diam_um.data();
    auto ion_state_tbl = ion_state_table();
    n_ion_ = ion_state_tbl.size();
    for (auto i: ion_state_tbl) {
        auto ion_binding = value_by_key(overrides.ion_rebind, i.first).value_or(i.first);
        util::optional<ion_state&> oion = value_by_key(shared.ion_data, ion_binding);
        if (!oion) {
            throw arbor_internal_error("multicore/mechanism: mechanism holds ion with no corresponding shared state");
        }
        ion_state_view& ion_view = *i.second;
        ion_view.current_density = oion->iX_.data();
        ion_view.reversal_potential = oion->eX_.data();
        ion_view.internal_concentration = oion->Xi_.data();
        ion_view.external_concentration = oion->Xo_.data();
        ion_view.ionic_charge = oion->charge.data();
    }
    event_stream_ptr_ = &shared.deliverable_events;
    if (width_==0) {
        return;
    }
    width_padded_ = math::round_up(width_, shared.alignment);
    auto fields = field_table();
    std::size_t n_field = fields.size();
    data_ = array((1+n_field)*width_padded_, NAN, pad);
    for (std::size_t i = 0; i<n_field; ++i) {
        fvm_value_type*& field_ptr = *(fields[i].second);
        field_ptr = data_.data()+(i+1)*width_padded_;
        if (auto opt_value = value_by_key(field_default_table(), fields[i].first)) {
            std::fill(field_ptr, field_ptr+width_padded_, *opt_value);
        }
    }
    weight_ = data_.data();
     * For entries in the padded tail of weight_, set weight to zero.
     * For indices in the padded tail of node_index_, set index to last valid CV index.
     * For indices in the padded tail of ion index maps, set index to last valid ion index.
    node_index_ = iarray(width_padded_, pad);
    copy_extend(pos_data.cv, node_index_, pos_data.cv.back());
    copy_extend(pos_data.weight, make_range(data_.data(), data_.data()+width_padded_), 0);
    index_constraints_ = make_constraint_partition(node_index_, width_, simd_width);
    if (mult_in_place_) {
        multiplicity_ = iarray(width_padded_, pad);
        copy_extend(pos_data.multiplicity, multiplicity_, 1);
    }
    for (auto i: ion_index_table()) {
        auto ion_binding = value_by_key(overrides.ion_rebind, i.first).value_or(i.first);
        util::optional<ion_state&> oion = value_by_key(shared.ion_data, ion_binding);
        if (!oion) {
            throw arbor_internal_error("multicore/mechanism: mechanism holds ion with no corresponding shared state");
        }
        auto indices = util::index_into(node_index_, oion->node_index_);
         Take reference to derived (generated) mechanism ion index member.
        auto& ion_index = *i.second;
        ion_index = iarray(width_padded_, pad);
        copy_extend(indices, ion_index, util::back(indices));
        arb_assert(compatible_index_constraints(node_index_, ion_index, simd_width));
    }
}
void mechanism :: instantiate ( unsigned id , backend :: shared_state & shared , const mechanism_overrides & overrides , const mechanism_layout & pos_data ) { using util :: make_range ; for ( auto & kv : overrides . globals ) { if ( auto opt_ptr = value_by_key ( global_table ( ) , kv . first ) ) { value_type & global = * opt_ptr . value ( ) ; global = kv . second ; } else { throw arbor_internal_error ( " " ) ; } } mult_in_place_ = ! pos_data . multiplicity . empty ( ) ; util :: padded_allocator < > pad ( shared . alignment ) ; mechanism_id_ = id ; width_ = pos_data . cv . size ( ) ; vec_ci_ = shared . cv_to_intdom . data ( ) ; vec_t_ = shared . time . data ( ) ; vec_t_to_ = shared . time_to . data ( ) ; vec_dt_ = shared . dt_cv . data ( ) ; vec_v_ = shared . voltage . data ( ) ; vec_i_ = shared . current_density . data ( ) ; vec_g_ = shared . conductivity . data ( ) ; temperature_degC_ = shared . temperature_degC . data ( ) ; diam_um_ = shared . diam_um . data ( ) ; auto ion_state_tbl = ion_state_table ( ) ; n_ion_ = ion_state_tbl . size ( ) ; for ( auto i : ion_state_tbl ) { auto ion_binding = value_by_key ( overrides . ion_rebind , i . first ) . value_or ( i . first ) ; util :: optional < ion_state & > oion = value_by_key ( shared . ion_data , ion_binding ) ; if ( ! oion ) { throw arbor_internal_error ( " " ) ; } ion_state_view & ion_view = * i . second ; ion_view . current_density = oion -> iX_ . data ( ) ; ion_view . reversal_potential = oion -> eX_ . data ( ) ; ion_view . internal_concentration = oion -> Xi_ . data ( ) ; ion_view . external_concentration = oion -> Xo_ . data ( ) ; ion_view . ionic_charge = oion -> charge . data ( ) ; } event_stream_ptr_ = & shared . deliverable_events ; if ( width_ == 0 ) { return ; } width_padded_ = math :: round_up ( width_ , shared . alignment ) ; auto fields = field_table ( ) ; std :: size_t n_field = fields . size ( ) ; data_ = array ( ( 1 + n_field ) * width_padded_ , NAN , pad ) ; for ( std :: size_t i = 0 ; i < n_field ; ++ i ) { fvm_value_type * & field_ptr = * ( fields [ i ] . second ) ; field_ptr = data_ . data ( ) + ( i + 1 ) * width_padded_ ; if ( auto opt_value = value_by_key ( field_default_table ( ) , fields [ i ] . first ) ) { std :: fill ( field_ptr , field_ptr + width_padded_ , * opt_value ) ; } } weight_ = data_ . data ( ) ; node_index_ = iarray ( width_padded_ , pad ) ; copy_extend ( pos_data . cv , node_index_ , pos_data . cv . back ( ) ) ; copy_extend ( pos_data . weight , make_range ( data_ . data ( ) , data_ . data ( ) + width_padded_ ) , 0 ) ; index_constraints_ = make_constraint_partition ( node_index_ , width_ , simd_width ) ; if ( mult_in_place_ ) { multiplicity_ = iarray ( width_padded_ , pad ) ; copy_extend ( pos_data . multiplicity , multiplicity_ , 1 ) ; } for ( auto i : ion_index_table ( ) ) { auto ion_binding = value_by_key ( overrides . ion_rebind , i . first ) . value_or ( i . first ) ; util :: optional < ion_state & > oion = value_by_key ( shared . ion_data , ion_binding ) ; if ( ! oion ) { throw arbor_internal_error ( " " ) ; } auto indices = util :: index_into ( node_index_ , oion -> node_index_ ) ; auto & ion_index = * i . second ; ion_index = iarray ( width_padded_ , pad ) ; copy_extend ( indices , ion_index , util :: back ( indices ) ) ; arb_assert ( compatible_index_constraints ( node_index_ , ion_index , simd_width ) ) ; } }
The derived class (typically generated code from modcc) holds pointers that need
to be set to point inside the shared state, or into the allocated parameter/variable
data block.
The derived class ( typically generated code from modcc ) holds pointers that need to be set to point inside the shared state or into the allocated parameter / variable data block .
// Assign global scalar parameters: // Take reference to corresponding derived (generated) mechanism value member. // Assign non-owning views onto shared state: // If there are no sites (is this ever meaningful?) there is nothing more to do. // Extend width to account for requisite SIMD padding. // Allocate and initialize state and parameter vectors with default values. // (First sub-array of data_ is used for width_, below.) // Take reference to corresponding derived (generated) mechanism value pointer member. // Allocate and copy local state: weight, node indices, ion indices. // The tail comprises those elements between width_ and width_padded_: // // * For entries in the padded tail of weight_, set weight to zero. // * For indices in the padded tail of node_index_, set index to last valid CV index. // * For indices in the padded tail of ion index maps, set index to last valid ion index. // Take reference to derived (generated) mechanism ion index member.