1 #include <../../nrnconf.h>
13 #define nt_t nrn_threads->_t
14 #define nt_dt nrn_threads->_dt
20 std::vector<neuron::container::data_handle<double>>
state;
51 extern "C" void nrn_tree_solve(
double* a,
double* d,
double* b,
double*
rhs,
int* pindex,
int n) {
66 for (
i =
n - 1;
i > 0; --
i) {
76 for (
i = 0;
i <
n; ++
i) {
124 delete std::exchange(*ppld,
nullptr);
129 int i,
n, mi, mpi, pindex;
131 double rall, dxp, dxc;
138 for (
i = 0;
i <
n; ++
i) {
144 ml->
pdata[mi][-sindex - 1].
get<
double*>());
152 mpi = pld->
mindex[pindex];
161 pld->
af[
i] = 2 * rall / dxp / (dxc + dxp);
162 pld->
bf[
i] = 2 / dxc / (dxc + dxp);
171 auto*
const pld =
new LongDifus{
static_cast<std::size_t
>(
n)};
174 pld->pindex = (
int*)
ecalloc(
n,
sizeof(
int));
175 pld->a = (
double*)
ecalloc(
n,
sizeof(
double));
176 pld->b = (
double*)
ecalloc(
n,
sizeof(
double));
177 pld->d = (
double*)
ecalloc(
n,
sizeof(
double));
178 pld->rhs = (
double*)
ecalloc(
n,
sizeof(
double));
179 pld->af = (
double*)
ecalloc(
n,
sizeof(
double));
180 pld->bf = (
double*)
ecalloc(
n,
sizeof(
double));
181 pld->vol = (
double*)
ecalloc(
n,
sizeof(
double));
182 pld->dc = (
double*)
ecalloc(
n,
sizeof(
double));
185 auto const vnodecount = _nt->
end;
186 std::vector<int>
map(vnodecount, -1), omap(
n);
187 for (
int i = 0;
i <
n; ++
i) {
195 for (
int i = 0,
j = 0;
i < vnodecount; ++
i) {
197 pld->mindex[
j] =
map[
i];
221 pld->pindex[
j] = omap[pindex];
267 if (tml->
index == m) {
268 ldtd->
ml[
i] = tml->
ml;
278 return (*ppldtd)->ldifus[tid];
283 return (*ppldtd)->ml[tid];
294 auto*
const _nt = &ntr;
299 auto*
const ml =
v2ml(
v, _nt->id);
300 int const n = ml->nodecount;
302 Datum*
const thread = ml->_thread;
306 for (
int i = 0;
i <
n; ++
i) {
310 pld->
dc[
i] = diffunc(ai, ml, mi,
pdata[mi], pld->
vol +
i, &dfdi, thread, _nt, sorted_token);
314 double const dc = (pld->
dc[
i] + pld->
dc[pin]) / 2.;
315 pld->
a[
i] = -pld->
af[
i] * dc / pld->
vol[pin];
316 pld->
b[
i] = -pld->
bf[
i] * dc / pld->
vol[
i];
320 for (
int i = 0;
i <
n; ++
i) {
325 pld->
d[
i] -= pld->
b[
i];
326 pld->
d[pin] -= pld->
a[
i];
334 for (
int i = 0;
i <
n; ++
i) {
335 *(pld->
state[
i].next_array_element(ai)) = pld->
rhs[
i];
347 auto*
const _nt = &ntr;
352 auto*
const ml =
v2ml(
v, _nt->id);
353 int const n = ml->nodecount;
355 Datum*
const thread = ml->_thread;
358 for (
int i = 0;
i <
n; ++
i) {
362 pld->
dc[
i] = diffunc(ai, ml, mi,
pdata[mi], pld->
vol +
i, &dfdi, thread, _nt, sorted_token);
365 double const dc = (pld->
dc[
i] + pld->
dc[pin]) / 2.;
366 pld->
a[
i] = pld->
af[
i] * dc / pld->
vol[pin];
367 pld->
b[
i] = pld->
bf[
i] * dc / pld->
vol[
i];
371 for (
int i = 0;
i <
n; ++
i) {
376 dif = *(pld->
state[pin].next_array_element(ai)) -
377 *(pld->
state[
i].next_array_element(ai));
378 ml->data(mi, dindex, ai) += dif * pld->
b[
i];
379 ml->data(pld->
mindex[pin], dindex, ai) -= dif * pld->
a[
i];
392 auto*
const _nt = &ntr;
397 auto*
const ml =
v2ml(
v, _nt->id);
398 int const n = ml->nodecount;
400 Datum*
const thread = ml->_thread;
403 for (
int i = 0;
i <
n; ++
i) {
407 pld->
dc[
i] = diffunc(ai, ml, mi,
pdata[mi], pld->
vol +
i, &dfdi, thread, _nt, sorted_token);
410 pld->
d[
i] +=
fabs(dfdi) / pld->
vol[
i] / *(pld->
state[
i].next_array_element(ai));
414 auto const dc = (pld->
dc[
i] + pld->
dc[pin]) / 2.;
415 pld->
a[
i] = -pld->
af[
i] * dc / pld->
vol[pin];
416 pld->
b[
i] = -pld->
bf[
i] * dc / pld->
vol[
i];
420 for (
int i = 0;
i <
n; ++
i) {
424 pld->
rhs[
i] = ml->data(mi, dindex, ai) /
nt_dt;
426 pld->
d[
i] -= pld->
b[
i];
427 pld->
d[pin] -= pld->
a[
i];
431 for (
int i =
n - 1;
i > 0; --
i) {
435 p = pld->
a[
i] / pld->
d[
i];
436 pld->
d[pin] -=
p * pld->
b[
i];
441 for (
int i = 0;
i <
n; ++
i) {
444 pld->
rhs[
i] -= pld->
b[
i] * pld->
rhs[pin];
449 for (
int i = 0;
i <
n; ++
i) {
451 ml->data(mi, dindex, ai) = pld->
rhs[
i];
double section_length(Section *sec)
static void longdifusalloc(LongDifus **ppld, int m, int sindex, Memb_list *ml, NrnThread *_nt)
static ldifusfunc2_t stagger
void nrn_tree_solve(double *a, double *d, double *b, double *rhs, int *pindex, int n)
static Memb_list * v2ml(void **v, int tid)
static void longdifusfree(LongDifus **ppld)
static void longdifus_diamchange(LongDifus *pld, int m, int sindex, Memb_list *ml, NrnThread *_nt)
void long_difus_solve(neuron::model_sorted_token const &sorted_token, int method, NrnThread &nt)
static ldifusfunc2_t matsol
static ldifusfunc2_t overall_setup
void hoc_register_ldifus1(ldifusfunc_t f)
static ldifusfunc_t * ldifusfunc
static LongDifus * v2ld(void **v, int tid)
static double map(void *v)
void * erealloc(void *ptr, size_t size)
void * ecalloc(size_t n, size_t size)
static void * emalloc(size_t size)
int const size_t const size_t n
void(*)(ldifusfunc2_t, neuron::model_sorted_token const &, NrnThread &) ldifusfunc_t
void(int, ldifusfunc3_t, void **, int, int, int, neuron::model_sorted_token const &, NrnThread &) ldifusfunc2_t
double(*)(int, Memb_list *, std::size_t, Datum *, double *, double *, Datum *, NrnThread *, neuron::model_sorted_token const &) ldifusfunc3_t
std::vector< neuron::container::data_handle< double > > state
A view into a set of mechanism instances.
neuron::container::data_handle< double > data_handle(std::size_t instance, neuron::container::field_index field) const
Represent main neuron object computed by single thread.
struct NrnThreadMembList * next
Non-template stable handle to a generic value.
T get() const
Explicit conversion to any T.