Skip to content

Commit

Permalink
no limit on number of ion mechanisms (#3089)
Browse files Browse the repository at this point in the history
* replaces bitset by map of sets.
  • Loading branch information
nrnhines authored Oct 1, 2024
1 parent 95cc05b commit 3fcec76
Showing 1 changed file with 40 additions and 40 deletions.
80 changes: 40 additions & 40 deletions src/nrnoc/eion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
#include <array>
#include <string>

#include <memory>
#include <bitset>
#include <vector>
#include <map>
#include <set>

#undef hoc_retpushx

Expand Down Expand Up @@ -394,17 +393,37 @@ double nrn_nernst_coef(int type) {
/*
It is generally an error for two models to WRITE the same concentration.
This functions checks that there's no write conflict; and warns if it detects
one. It also sets respective write flag in the style of the ion.
nrn_check_conc_write checks that there's no write conflict; and warns if it
detects one. It also sets respective write flag in the style of the ion.
The argument `i` specifies which concentration is being written to. It's 0 for
exterior; and 1 for interior.
*/
void nrn_check_conc_write(Prop* p_ok, Prop* pion, int i) {
const int max_ions = 256;
static long size_;

static std::vector<std::bitset<max_ions>> chk_conc_, ion_bit_;
// Each mechanism type index that writes a concentration has a set of ion
// type indices it writes to.
// ionconctype is coded as iontype*2 + i where i=1 for interior
// So number of distinct ion mechanisms is essentially unlimited, max_int/2.
static std::map<int, std::set<int>> mechtype2ionconctype;

static void add_mechtype2ionconctype(int mechtype, int iontype, int i) {
auto& set_of_ionconctypes = mechtype2ionconctype[mechtype];
set_of_ionconctypes.insert(2 * iontype + i); // unique though inserting for each instance.
}

static bool mech_uses_ionconctype(int mechtype, int iontype, int i) {
if (auto search = mechtype2ionconctype.find(mechtype); search != mechtype2ionconctype.end()) {
auto& set_of_ionconctypes = search->second;
return set_of_ionconctypes.count(2 * iontype + i) == 1;
}
return false;
}

void nrn_check_conc_write(Prop* pmech, Prop* pion, int i) {
// Would be less redundant to generate the "database" at
// mechanism registration time. But NMODL presently gives us this info
// only at each mechanism instance allocation.
add_mechtype2ionconctype(pmech->_type, pion->_type, i);

Prop* p;
int flag, j, k;
Expand All @@ -414,51 +433,32 @@ void nrn_check_conc_write(Prop* p_ok, Prop* pion, int i) {
flag = 0400;
}

/* Create a vector holding std::bitset to track which ions
are being written to the membrane */
if (n_memb_func > size_) {
chk_conc_.resize(2 * n_memb_func);
ion_bit_.resize(n_memb_func);

for (j = size_; j < n_memb_func; ++j) {
chk_conc_[2 * j].reset();
chk_conc_[2 * j + 1].reset();
ion_bit_[j].reset();
}

size_ = n_memb_func;
}
for (k = 0, j = 0; j < n_memb_func; ++j) {
if (nrn_is_ion(j)) {
assert(k < max_ions);
ion_bit_[j].reset();
ion_bit_[j].set(k);
++k;
}
}

chk_conc_[2 * p_ok->_type + i] |= ion_bit_[pion->_type];
if (pion->dparam[iontype_index_dparam].get<int>() & flag) {
/* now comes the hard part. Is the possibility in fact actual.*/
auto ii = pion->dparam[iontype_index_dparam].get<int>();
if (ii & flag) {
// Is the possibility in fact actual. Unfortunately, uninserting the
// mechanism that writes a concentration does not reset the flag bit.
// So search the node property list for another mechanism that also
// writes this ion concentration. (that is needed anyway to
// fill out the warning message.)

// the pion in the node property list is before mechanisms that use the ion
for (p = pion->next; p; p = p->next) {
if (p == p_ok) {
if (p == pmech) {
continue;
}
auto rst = chk_conc_[2 * p->_type + i] & ion_bit_[pion->_type];
if (rst.any()) {
if (mech_uses_ionconctype(p->_type, pion->_type, i)) {
char buf[300];
Sprintf(buf,
"%.*s%c is being written at the same location by %s and %s",
(int) strlen(memb_func[pion->_type].sym->name) - 4,
memb_func[pion->_type].sym->name,
((i == 1) ? 'i' : 'o'),
memb_func[p_ok->_type].sym->name,
memb_func[pmech->_type].sym->name,
memb_func[p->_type].sym->name);
hoc_warning(buf, (char*) 0);
}
}
}
auto ii = pion->dparam[iontype_index_dparam].get<int>();
ii |= flag;
pion->dparam[iontype_index_dparam] = ii;
}
Expand Down

0 comments on commit 3fcec76

Please sign in to comment.