static double use_long_double(void* v) { NetCvode* d = (NetCvode*)v; hoc_return_type_code = 2; // boolean if (ifarg(1)) { int i = (int)chkarg(1,0,1); d->use_long_double_ = i; recalc_diam(); } return (double)d->use_long_double_; }
static double use_mxb(void* v) { NetCvode* d = (NetCvode*)v; hoc_return_type_code = 2; // boolean if (ifarg(1)) { int i = (int)chkarg(1,0,1); if (use_sparse13 != i) { use_sparse13 = i; recalc_diam(); } } return (double) use_sparse13; }
void Cvode::rhs(NrnThread* _nt) { int i; CvodeThreadData& z = CTD(_nt->id); if (diam_changed) { recalc_diam(); } if (z.v_node_count_ == 0) { return; } for (i = 0; i < z.v_node_count_; ++i) { NODERHS(z.v_node_[i]) = 0.; } if (_nt->_nrn_fast_imem) { double* p = _nt->_nrn_fast_imem->_nrn_sav_rhs; for (i = 0; i < z.v_node_count_; ++i) { Node* nd = z.v_node_[i]; p[nd->v_node_index] = 0; } } rhs_memb(z.cv_memb_list_, _nt); nrn_nonvint_block_current(_nt->end, _nt->_actual_rhs, _nt->id); if (_nt->_nrn_fast_imem) { double* p = _nt->_nrn_fast_imem->_nrn_sav_rhs; for (i = 0; i < z.v_node_count_; ++i) { Node* nd = z.v_node_[i]; p[nd->v_node_index] -= NODERHS(nd); } } /* at this point d contains all the membrane conductances */ /* now the internal axial currents. rhs += ai_j*(vi_j - vi) */ for (i = z.rootnodecount_; i < z.v_node_count_; ++i) { Node* nd = z.v_node_[i]; Node* pnd = z.v_parent_[i]; double dv = NODEV(pnd) - NODEV(nd); /* our connection coefficients are negative so */ NODERHS(nd) -= NODEB(nd)*dv; NODERHS(pnd) += NODEA(nd)*dv; } }
fcurrent() { int i; if (tree_changed) { setup_topology(); } if (v_structure_change) { v_setup_vectors(); } if (diam_changed) { recalc_diam(); } dt2thread(-1.); nrn_thread_table_check(); state_discon_allowed_ = 0; nrn_multithread_job(setup_tree_matrix); state_discon_allowed_ = 1; ret(1.); }
fadvance() { tstopunset; #if CVODE if (cvode_active_) { cvode_fadvance(-1.); tstopunset; ret(1.); return; } #endif if (tree_changed) { setup_topology(); } if (v_structure_change) { v_setup_vectors(); } if (diam_changed) { recalc_diam(); } nrn_fixed_step(); tstopunset; ret(1.); }
void Cvode::daspk_init_eqn(){ // DASPK equation order is exactly the same order as the // fixed step method for current balance (including // extracellular nodes) and linear mechanism. Remaining ode // equations are same order as for Cvode. Thus, daspk differs from // cvode order primarily in that cap and no-cap nodes are not // distinguished. // note that only one thread is allowed for sparse right now. NrnThread* _nt = nrn_threads; CvodeThreadData&z = ctd_[0]; double vtol; //printf("Cvode::daspk_init_eqn\n"); int i, j, in, ie, k, neq_v; // how many equations are there? Memb_func* mf; CvMembList* cml; //start with all the equations for the fixed step method. if (use_sparse13 == 0 || diam_changed != 0) { recalc_diam(); } z.neq_v_ = spGetSize(_nt->_sp13mat, 0); z.nvsize_ = z.neq_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) { z.nvsize_ += cml->ml->nodecount * (*s)(cml->index); } } neq_ = z.nvsize_; //printf("Cvode::daspk_init_eqn: neq_v_=%d neq_=%d\n", neq_v_, neq_); if (z.pv_) { delete [] z.pv_; delete [] z.pvdot_; } z.pv_ = new double*[z.nvsize_]; z.pvdot_ = new double*[z.nvsize_]; atolvec_alloc(neq_); double* atv = n_vector_data(atolnvec_, 0); for (i=0; i < neq_; ++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; } } // deal with voltage and extracellular and linear circuit nodes // for daspk the order is the same assert(use_sparse13); if (use_sparse13) { for (in = 0; in < _nt->end; ++in) { Node* nd; Extnode* nde; nd = _nt->_v_node[in]; nde = nd->extnode; i = nd->eqn_index_ - 1; // the sparse matrix index starts at 1 z.pv_[i] = &NODEV(nd); z.pvdot_[i] = nd->_rhs; if (nde) { for (ie=0; ie < nlayer; ++ie) { k = i + ie + 1; z.pv_[k] = nde->v + ie; z.pvdot_[k] = nde->_rhs[ie]; } } } linmod_dkmap(z.pv_, z.pvdot_); for (i=0; i < z.neq_v_; ++i) { atv[i] *= vtol; } } // map the membrane mechanism ode state and dstate pointers int ieq = z.neq_v_; for (cml = z.cv_memb_list_; cml; cml = cml->next) { int n; mf = memb_func + cml->index; Pfridot sc = (Pfridot)mf->ode_count; if (sc && ( (n = (*sc)(cml->index)) > 0)) { Memb_list* ml = cml->ml; 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(); }