def indices(self, r=None): """return the indices corresponding to this species in the given region if r is None, then returns all species indices""" # TODO: beware, may really want self._indices3d or self._indices1d initializer._do_init() return self._indices1d(r) + self._indices3d(r)
def _ode_count(offset): global last_structure_change_cnt global _rxd_offset initializer._do_init() _rxd_offset = offset if _diffusion_matrix is None or last_structure_change_cnt != _structure_change_count.value: _setup_matrices() last_structure_change_cnt = _structure_change_count.value return len(_nonzero_volume_indices)
def nodes(self): """A NodeList of all the nodes corresponding to the species. This can then be further restricted using the callable property of NodeList objects.""" initializer._do_init() # The first part here is for the 1D -- which doesn't keep live node objects -- the second part is for 3D return nodelist.NodeList(list(itertools.chain.from_iterable([s.nodes for s in self._secs])) + self._nodes)
def _fixed_step_solve(raw_dt): initializer._do_init() global pinverse, _fixed_step_count global _last_m, _last_dt, _last_preconditioner if species._species_count == 0: return # allow for skipping certain fixed steps # warning: this risks numerical errors! fixed_step_factor = options.fixed_step_factor _fixed_step_count += 1 if _fixed_step_count % fixed_step_factor: return dt = fixed_step_factor * raw_dt # TODO: this probably shouldn't be here if _diffusion_matrix is None and _euler_matrix is None: _setup_matrices() states = _node_get_states()[:] b = _rxd_reaction(states) - _diffusion_matrix * states if not species._has_3d: # use Hines solver since 1D only states[:] += _reaction_matrix_solve( dt, states, _diffusion_matrix_solve(dt, dt * b)) # clear the zero-volume "nodes" states[_zero_volume_indices] = 0 # TODO: refactor so this isn't in section1d... probably belongs in node _section1d_transfer_to_legacy() _last_preconditioner = None else: # TODO: this looks to be semi-implicit method because it doesn't take into account the reaction contribution to the Jacobian; do we care? # the actual advance via implicit euler n = len(states) if _last_dt != dt or _last_preconditioner is None: _last_m = eye_minus_dt_J(n, dt) _last_preconditioner = _LinearOperator( (n, n), _spilu(csc_matrix(_last_m)).solve) _last_dt = dt # removed diagonal preconditioner since tests showed no improvement in convergence result, info = _scipy_sparse_linalg_bicgstab(_last_m, dt * b, M=_last_preconditioner) assert (info == 0) states[:] += result # clear the zero-volume "nodes" states[_zero_volume_indices] = 0 for sr in _species_get_all_species().values(): s = sr() if s is not None: s._transfer_to_legacy()
def nodes(self): """A NodeList of all the nodes corresponding to the species. This can then be further restricted using the callable property of NodeList objects.""" initializer._do_init() # The first part here is for the 1D -- which doesn't keep live node objects -- the second part is for 3D return nodelist.NodeList( list(itertools.chain.from_iterable([s.nodes for s in self._secs])) + self._nodes)
def _currents(rhs): initializer._do_init() # setup membrane fluxes from our stuff # TODO: cache the memb_cur_ptrs, memb_cur_charges, memb_net_charges, memb_cur_mapped # because won't change very often global _rxd_induced_currents # need this; think it's because of initialization of mod files if _curr_indices is None: return # TODO: change so that this is only called when there are in fact currents _rxd_induced_currents = _numpy_zeros(len(_curr_indices)) rxd_memb_flux = [] memb_cur_ptrs = [] memb_cur_charges = [] memb_net_charges = [] memb_cur_mapped = [] for rptr in _all_reactions: r = rptr() if r and r._membrane_flux: # NOTE: memb_flux contains any scaling we need new_fluxes = r._get_memb_flux(_node_get_states()) rxd_memb_flux += list(new_fluxes) memb_cur_ptrs += r._cur_ptrs memb_cur_mapped += r._cur_mapped memb_cur_charges += [r._cur_charges] * len(new_fluxes) memb_net_charges += [r._net_charges] * len(new_fluxes) # TODO: is this in any way dimension dependent? if rxd_memb_flux: # TODO: remove the asserts when this is verified to work assert (len(rxd_memb_flux) == len(_cur_node_indices)) assert (len(rxd_memb_flux) == len(memb_cur_ptrs)) assert (len(rxd_memb_flux) == len(memb_cur_charges)) assert (len(rxd_memb_flux) == len(memb_net_charges)) for flux, cur_ptrs, cur_charges, net_charge, i, cur_maps in zip( rxd_memb_flux, memb_cur_ptrs, memb_cur_charges, memb_net_charges, _cur_node_indices, memb_cur_mapped): rhs[i] -= net_charge * flux #print net_charge * flux #import sys #sys.exit() # TODO: remove this assert when more thoroughly tested assert (len(cur_ptrs) == len(cur_maps)) for ptr, charge, cur_map_i in zip(cur_ptrs, cur_charges, cur_maps): # this has the opposite sign of the above because positive # currents lower the membrane potential cur = charge * flux ptr[0] += cur for sign, c in zip([-1, 1], cur_maps): if c is not None: _rxd_induced_currents[c] += sign * cur
def _currents(rhs): initializer._do_init() # setup membrane fluxes from our stuff # TODO: cache the memb_cur_ptrs, memb_cur_charges, memb_net_charges, memb_cur_mapped # because won't change very often global _rxd_induced_currents # need this; think it's because of initialization of mod files if _curr_indices is None: return # TODO: change so that this is only called when there are in fact currents _rxd_induced_currents = _numpy_zeros(len(_curr_indices)) rxd_memb_flux = [] memb_cur_ptrs = [] memb_cur_charges = [] memb_net_charges = [] memb_cur_mapped = [] for rptr in _all_reactions: r = rptr() if r and r._membrane_flux: # NOTE: memb_flux contains any scaling we need new_fluxes = r._get_memb_flux(_node_get_states()) rxd_memb_flux += list(new_fluxes) memb_cur_ptrs += r._cur_ptrs memb_cur_mapped += r._cur_mapped memb_cur_charges += [r._cur_charges] * len(new_fluxes) memb_net_charges += [r._net_charges] * len(new_fluxes) # TODO: is this in any way dimension dependent? if rxd_memb_flux: # TODO: remove the asserts when this is verified to work assert(len(rxd_memb_flux) == len(_cur_node_indices)) assert(len(rxd_memb_flux) == len(memb_cur_ptrs)) assert(len(rxd_memb_flux) == len(memb_cur_charges)) assert(len(rxd_memb_flux) == len(memb_net_charges)) for flux, cur_ptrs, cur_charges, net_charge, i, cur_maps in zip(rxd_memb_flux, memb_cur_ptrs, memb_cur_charges, memb_net_charges, _cur_node_indices, memb_cur_mapped): rhs[i] -= net_charge * flux #print net_charge * flux #import sys #sys.exit() # TODO: remove this assert when more thoroughly tested assert(len(cur_ptrs) == len(cur_maps)) for ptr, charge, cur_map_i in zip(cur_ptrs, cur_charges, cur_maps): # this has the opposite sign of the above because positive # currents lower the membrane potential cur = charge * flux ptr[0] += cur for sign, c in zip([-1, 1], cur_maps): if c is not None: _rxd_induced_currents[c] += sign * cur
def _fixed_step_solve(raw_dt): initializer._do_init() global pinverse, _fixed_step_count global _last_m, _last_dt, _last_preconditioner if species._species_count == 0: return # allow for skipping certain fixed steps # warning: this risks numerical errors! fixed_step_factor = options.fixed_step_factor _fixed_step_count += 1 if _fixed_step_count % fixed_step_factor: return dt = fixed_step_factor * raw_dt # TODO: this probably shouldn't be here if _diffusion_matrix is None and _euler_matrix is None: _setup_matrices() states = _node_get_states()[:] b = _rxd_reaction(states) - _diffusion_matrix * states if not species._has_3d: # use Hines solver since 1D only states[:] += _reaction_matrix_solve(dt, states, _diffusion_matrix_solve(dt, dt * b)) # clear the zero-volume "nodes" states[_zero_volume_indices] = 0 # TODO: refactor so this isn't in section1d... probably belongs in node _section1d_transfer_to_legacy() _last_preconditioner = None else: # TODO: this looks to be semi-implicit method because it doesn't take into account the reaction contribution to the Jacobian; do we care? # the actual advance via implicit euler n = len(states) if _last_dt != dt or _last_preconditioner is None: _last_m = _scipy_sparse_eye(n, n) - dt * _euler_matrix _last_preconditioner = _LinearOperator((n, n), _spilu(csc_matrix(_last_m)).solve) _last_dt = dt # removed diagonal preconditioner since tests showed no improvement in convergence result, info = _scipy_sparse_linalg_bicgstab(_last_m, dt * b, M=_last_preconditioner) assert(info == 0) states[:] += result for sr in _species_get_all_species().values(): s = sr() if s is not None: s._transfer_to_legacy()
def _init(): initializer._do_init() # TODO: check about the 0<x<1 problem alluded to in the documentation h.define_shape() if species._has_1d: section1d._purge_cptrs() for sr in _species_get_all_species().values(): s = sr() if s is not None: # TODO: are there issues with hybrid or 3D here? (I don't think so, but here's a bookmark just in case) s._register_cptrs() s._finitialize() _setup_matrices()
def nodes(self): """A NodeList of the Node objects containing concentration data for the given Species and Region. The code node_list = ca[cyt].nodes is more efficient than the otherwise equivalent node_list = ca.nodes(cyt) because the former only creates the Node objects belonging to the restriction ca[cyt] whereas the second option constructs all Node objects belonging to the Species ca and then culls the list to only include those also belonging to the Region cyt. """ initializer._do_init() return nodelist.NodeList(itertools.chain.from_iterable([s.nodes for s in self._species()._secs if s._region == self._region()]))
def nodes(self): """A NodeList of the Node objects containing concentration data for the given Species and Region. The code node_list = ca[cyt].nodes is more efficient than the otherwise equivalent node_list = ca.nodes(cyt) because the former only creates the Node objects belonging to the restriction ca[cyt] whereas the second option constructs all Node objects belonging to the Species ca and then culls the list to only include those also belonging to the Region cyt. """ initializer._do_init() return nodelist.NodeList( itertools.chain.from_iterable([ s.nodes for s in self._species()._secs if s._region == self._region() ]))
def _setup(): initializer._do_init() # TODO: this is when I should resetup matrices (structure changed event) global _last_dt, _external_solver_initialized _last_dt = None _external_solver_initialized = False