static void nrn_cur(_NrnThread* _nt, _Memb_list* _ml, int _type) { double* _p; Datum* _ppvar; Datum* _thread; Node *_nd; int* _ni; double _rhs, _v; int _iml, _cntml; #if CACHEVEC _ni = _ml->_nodeindices; #endif _cntml = _ml->_nodecount; _thread = _ml->_thread; for (_iml = 0; _iml < _cntml; ++_iml) { _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml]; #if CACHEVEC if (use_cachevec) { _v = VEC_V(_ni[_iml]); }else #endif { _nd = _ml->_nodelist[_iml]; _v = NODEV(_nd); } ena = _ion_ena; _g = _nrn_current(_p, _ppvar, _thread, _nt, _v + .001); { double _dina; _dina = ina; _rhs = _nrn_current(_p, _ppvar, _thread, _nt, _v); _ion_dinadv += (_dina - ina)/.001 ; } _g = (_g - _rhs)/.001; _ion_ina += ina ; #if CACHEVEC if (use_cachevec) { VEC_RHS(_ni[_iml]) -= _rhs; }else #endif { NODERHS(_nd) -= _rhs; } }}
static void nrn_cur(_NrnThread* _nt, _Memb_list* _ml, int _type){ Node *_nd; int* _ni; double _rhs, _v; int _iml, _cntml; #if CACHEVEC _ni = _ml->_nodeindices; #endif _cntml = _ml->_nodecount; for (_iml = 0; _iml < _cntml; ++_iml) { _p = _ml->_data[_iml]; _ppvar = _ml->_pdata[_iml]; #if CACHEVEC if (use_cachevec) { _v = VEC_V(_ni[_iml]); }else #endif { _nd = _ml->_nodelist[_iml]; _v = NODEV(_nd); } ek = _ion_ek; cai = _ion_cai; _g = _nrn_current(_v + .001); { double _dik; _dik = ik; _rhs = _nrn_current(_v); _ion_dikdv += (_dik - ik)/.001 ; } _g = (_g - _rhs)/.001; _ion_ik += ik ; #if CACHEVEC if (use_cachevec) { VEC_RHS(_ni[_iml]) -= _rhs; }else #endif { NODERHS(_nd) -= _rhs; } }}
void NonLinImpRep::didv() { int i, j, ip; Node* nd; NrnThread* _nt = nrn_threads; // d2v/dv2 terms for (i=_nt->ncell; i < n_v_; ++i) { nd = _nt->_v_node[i]; ip = _nt->_v_parent[i]->v_node_index; double* a = cmplx_spGetElement(m_, v_index_[ip], v_index_[i]); double* b = cmplx_spGetElement(m_, v_index_[i], v_index_[ip]); *a += NODEA(nd); *b += NODEB(nd); *diag_[i] -= NODEB(nd); *diag_[ip] -= NODEA(nd); } // jwC term Memb_list* mlc = _nt->tml->ml; int n = mlc->nodecount; for (i=0; i < n; ++i) { double* cd = mlc->data[i]; j = mlc->nodelist[i]->v_node_index; diag_[v_index_[j]-1][1] += .001 * cd[0] * omega_; } // di/dv terms // because there may be several point processes of the same type // at the same location, we have to be careful to neither increment that // nd->v multiple times nor count the rhs multiple times. // So we can't take advantage of vectorized point processes. // To avoid this we do each mechanism item separately. // We assume there is no interaction between // separate locations. Note that interactions such as gap junctions // would not be handled in any case without computing a full jacobian. // i.e. calling nrn_rhs varying every state one at a time (that would // give the d2v/dv2 terms as well), but the expense is unwarranted. for (NrnThreadMembList* tml = _nt->tml; tml; tml = tml->next) { i = tml->index; if (i == CAP) { continue; } if (!memb_func[i].current) { continue; } Memb_list* ml = tml->ml; double* x1 = rv_; // use as temporary storage double* x2 = jv_; for (j = 0; j < ml->nodecount; ++j) { Node* nd = ml->nodelist[j]; // zero rhs // save v NODERHS(nd) = 0; x1[j] = NODEV(nd); // v+dv NODEV(nd) += delta_; current(i, ml, j); // save rhs // zero rhs // restore v x2[j] = NODERHS(nd); NODERHS(nd) = 0; NODEV(nd) = x1[j]; current(i, ml, j); // conductance // add to matrix *diag_[v_index_[nd->v_node_index]-1] -= (x2[j] - NODERHS(nd))/delta_; } } }
void Cvode::init_eqn(){ double vtol; NrnThread* _nt; CvMembList* cml; Memb_list* ml; Memb_func* mf; int i, j, zneq, zneq_v, zneq_cap_v; //printf("Cvode::init_eqn\n"); if (nthsizes_) { delete [] nthsizes_; nthsizes_ = 0; } neq_ = 0; for (int id = 0; id < nctd_; ++id) { CvodeThreadData& z = ctd_[id]; z.cmlcap_ = nil; z.cmlext_ = nil; for (cml = z.cv_memb_list_; cml; cml = cml->next) { if (cml->index == CAP) { z.cmlcap_ = cml; } if (cml->index == EXTRACELL) { z.cmlext_ = cml; } } } if (use_daspk_) { daspk_init_eqn(); return; } FOR_THREADS(_nt) { // for lvardt, this body done only once and for ctd_[0] CvodeThreadData& z = ctd_[_nt->id]; // how many ode's are there? First ones are non-zero capacitance // nodes with non-zero capacitance zneq_cap_v = z.cmlcap_ ? z.cmlcap_->ml->nodecount : 0; zneq = zneq_cap_v; // now add the membrane mechanism ode's to the count for (cml = z.cv_memb_list_; cml; cml = cml->next) { Pfridot s = (Pfridot)memb_func[cml->index].ode_count; if (s) { zneq += cml->ml->nodecount * (*s)(cml->index); } } //printf("%d Cvode::init_eqn neq_v=%d zneq_=%d\n", nrnmpi_myid, neq_v, zneq_); if (z.pv_) { delete [] z.pv_; delete [] z.pvdot_; z.pv_ = 0; z.pvdot_ = 0; } if (zneq) { z.pv_ = new double*[zneq]; z.pvdot_ = new double*[zneq]; } z.nvoffset_ = neq_; z.nvsize_ = zneq; neq_ += zneq; if (nth_) { break; } //lvardt } #if PARANEURON if (use_partrans_) { global_neq_ = nrnmpi_int_sum_reduce(neq_, mpicomm_); //printf("%d global_neq_=%d neq=%d\n", nrnmpi_myid, global_neq_, neq_); } #endif atolvec_alloc(neq_); for (int id = 0; id < nctd_; ++id) { CvodeThreadData& z = ctd_[id]; double* atv = n_vector_data(atolnvec_, id); zneq_cap_v = z.cmlcap_ ? z.cmlcap_->ml->nodecount : 0; zneq = z.nvsize_; zneq_v = zneq_cap_v; for (i=0; i < zneq; ++i) { atv[i] = ncv_->atol(); } vtol = 1.; if (!vsym) { vsym = hoc_table_lookup("v", hoc_built_in_symlist); } if (vsym->extra) { double x; x = vsym->extra->tolerance; if (x != 0 && x < vtol) { vtol = x; } } for (i=0; i < zneq_cap_v; ++i) { atv[i] *= vtol; } // deal with voltage nodes // only cap nodes for cvode for (i=0; i < z.v_node_count_; ++i) { //sentinal values for determining no_cap NODERHS(z.v_node_[i]) = 1.; } for (i=0; i < zneq_cap_v; ++i) { ml = z.cmlcap_->ml; z.pv_[i] = &NODEV(ml->nodelist[i]); z.pvdot_[i] = &(NODERHS(ml->nodelist[i])); *z.pvdot_[i] = 0.; // only ones = 1 are no_cap } // the remainder are no_cap nodes if (z.no_cap_node_) { delete [] z.no_cap_node_; delete [] z.no_cap_child_; } z.no_cap_node_ = new Node*[z.v_node_count_ - zneq_cap_v]; z.no_cap_child_ = new Node*[z.v_node_count_ - zneq_cap_v]; z.no_cap_count_ = 0; j = 0; for (i=0; i < z.v_node_count_; ++i) { if (NODERHS(z.v_node_[i]) > .5) { z.no_cap_node_[z.no_cap_count_++] = z.v_node_[i]; } if (z.v_parent_[i] && NODERHS(z.v_parent_[i]) > .5) { z.no_cap_child_[j++] = z.v_node_[i]; } } z.no_cap_child_count_ = j; // use the sentinal values in NODERHS to construct a new no cap membrane list new_no_cap_memb(z, _nt); // map the membrane mechanism ode state and dstate pointers int ieq = zneq_v; for (cml = z.cv_memb_list_; cml; cml = cml->next) { int n; ml = cml->ml; mf = memb_func + cml->index; Pfridot sc = (Pfridot)mf->ode_count; if (sc && ( (n = (*sc)(cml->index)) > 0)) { Pfridot s = (Pfridot)mf->ode_map; if (mf->hoc_mech) { for (j=0; j < ml->nodecount; ++j) { (*s)(ieq, z.pv_ + ieq, z.pvdot_ + ieq, ml->prop[j], atv + ieq); ieq += n; } }else{ for (j=0; j < ml->nodecount; ++j) { (*s)(ieq, z.pv_ + ieq, z.pvdot_ + ieq, ml->data[j], ml->pdata[j], atv + ieq, cml->index); ieq += n; } } } } } structure_change_ = false; }
method3_setup_tree_matrix() /* construct diagonal elements */ { int i; if (diam_changed) { recalc_diam(); } #if _CRAY #pragma _CRI ivdep #endif for (i = 0; i < v_node_count; ++i) { Node* nd = v_node[i]; NODED(nd) = 0.; NODERHS(nd) = 0.; nd->thisnode.GC = 0.; nd->thisnode.EC = 0.; } for (i=0; i < n_memb_func; ++i) if (memb_func[i].current && memb_list[i].nodecount) { if (memb_func[i].vectorized) { memb_func[i].current( memb_list[i].nodecount, memb_list[i].nodelist, memb_list[i].data, memb_list[i].pdata ); }else{ int j, count; Pfrd s = memb_func[i].current; Memb_list* m = memb_list + i; count = m->nodecount; if (memb_func[i].is_point) { for (j = 0; j < count; ++j) { Node* nd = m->nodelist[j]; NODERHS(nd) -= (*s)(m->data[j], m->pdata[j], &NODED(nd),nd->v); }; }else{ for (j = 0; j < count; ++j) { Node* nd = m->nodelist[j]; nd->thisnode.EC -= (*s)(m->data[j], m->pdata[j], &nd->thisnode.GC,nd->v); }; } } if (errno) { if (nrn_errno_check(i)) { hoc_warning("errno set during calculation of currents", (char*)0); } } } #if 0 && _CRAY #pragma _CRI ivdep #endif for (i=rootnodecount; i < v_node_count; ++i) { Node* nd2; Node* nd = v_node[i]; Node* pnd = v_parent[nd->v_node_index]; double dg, de, dgp, dep, fac; #if 0 if (i == rootnodecount) { printf("v0 %g vn %g jstim %g jleft %g jright %g\n", nd->v, pnd->v, nd->fromparent.current, nd->toparent.current, nd[1].fromparent.current); } #endif /* dg and de must be second order when used */ if ((nd2 = nd->toparent.nd2) != (Node*)0) { dgp = -(3*(pnd->thisnode.GC - pnd->thisnode.Cdt) - 4*(nd->thisnode.GC - nd->thisnode.Cdt) +(nd2->thisnode.GC - nd2->thisnode.Cdt))/2 ; dep = -(3*(pnd->thisnode.EC - pnd->thisnode.Cdt * pnd->v) - 4*(nd->thisnode.EC - nd->thisnode.Cdt * nd->v) +(nd2->thisnode.EC - nd2->thisnode.Cdt * nd2->v))/2 ; }else{ dgp = 0.; dep = 0.; } if ((nd2 = pnd->fromparent.nd2) != (Node*)0) { dg = -(3*(nd->thisnode.GC - nd->thisnode.Cdt) - 4*(pnd->thisnode.GC - pnd->thisnode.Cdt) +(nd2->thisnode.GC - nd2->thisnode.Cdt))/2 ; de = -(3*(nd->thisnode.EC - nd->thisnode.Cdt * nd->v) - 4*(pnd->thisnode.EC - pnd->thisnode.Cdt * pnd->v) +(nd2->thisnode.EC - nd2->thisnode.Cdt * nd2->v))/2 ; }else{ dg = 0.; de = 0.; } fac = 1. + nd->toparent.coefjdot * nd->thisnode.GC; nd->toparent.djdv0 = ( nd->toparent.coefj + nd->toparent.coef0 * nd->thisnode.GC + nd->toparent.coefdg * dg )/fac; NODED(nd) += nd->toparent.djdv0; nd->toparent.current = ( - nd->toparent.coef0 * nd->thisnode.EC - nd->toparent.coefn * pnd->thisnode.EC + nd->toparent.coefjdot * nd->thisnode.Cdt * nd->toparent.current - nd->toparent.coefdg * de )/fac; NODERHS(nd) -= nd->toparent.current; NODEB(nd) = ( - nd->toparent.coefj + nd->toparent.coefn * pnd->thisnode.GC )/fac; /* this can break cray vectors */ fac = 1. + nd->fromparent.coefjdot * pnd->thisnode.GC; nd->fromparent.djdv0 = ( nd->fromparent.coefj + nd->fromparent.coef0 * pnd->thisnode.GC + nd->fromparent.coefdg * dgp )/fac; pNODED(nd) += nd->fromparent.djdv0; nd->fromparent.current = ( - nd->fromparent.coef0 * pnd->thisnode.EC - nd->fromparent.coefn * nd->thisnode.EC + nd->fromparent.coefjdot * nd->thisnode.Cdt * nd->fromparent.current - nd->fromparent.coefdg * dep )/fac; pNODERHS(nd) -= nd->fromparent.current; NODEA(nd) = ( - nd->fromparent.coefj + nd->fromparent.coefn * nd->thisnode.GC )/fac; } activstim(); activsynapse(); #if SEJNOWSKI activconnect(); #endif activclamp(); }