Passive propagation
Source code of the subroutine that updates the membrane potential. The local inputs are the current membrane potential, any current or voltage clamps on the cell, and the effective conductance and reversal potential that the ion channels provide for each compartment.
The other input quantities define the electrical structure of the discretized cell and are fixed throughout the calculation.
Fixed quantities
Declarations of structural quantities: these are fixed throughout the calculation
integer, intent(in) :: ncompartments, nconnections, ncc, nvc integer, dimension(nconnections), intent(in) :: con_from, con_to real, dimension(nconnections), intent(in) :: con_conductance, con_capacitance real, dimension(ncompartments) :: cpt_capacitance real, intent(in) :: dt, ftimediff integer, dimension(ncc), intent(in) :: pos_ccs integer, dimension(nvc), intent(in) :: pos_vcs
Local inputs
The effective conductance and reversal potential arising from combining all the channels on each compartment, and the values ov current clamps and voltage clamps.
real, dimension(ncompartments), intent(in) :: gchan, echan real, dimension(ncc), intent(in) :: ccvals real, dimension(nvc), intent(in) :: vcvals
Work arrays and output
The diag, rhs, and offdiag are internal work arrays. v is the membrane potential: both input and output
real, dimension(ncompartments), intent(inout) :: v real, dimension(ncompartments) :: diag, rhs real, dimension(nconnections) :: offdiag real :: fcn, a, b integer :: i, i_from, i_to, icpt real :: f
Set up
Populate the matrices and rhs vector. The matrix elements are stored in the diag and offdiag arrays. The off-diagonal elements are stored by connection rather than by compartment.
v(pos_vcs) = vcvals; do i = 1, ncompartments a = dt * gchan(i) rhs(i) = a * (echan(i) - v(i)) diag(i) = cpt_capacitance(i) + fcn * a end do do i = 1, ncompartments a = dt * gchan(i) rhs(i) = a * (echan(i) - v(i)) diag(i) = cpt_capacitance(i) + fcn * a end do do i = 1, nconnections a = dt * con_conductance(i) offdiag(i) = -fcn * (con_capacitance(i) + a) end do rhs(pos_ccs) = rhs(pos_ccs) + dt * ccvals; do i = 1, nconnections b = dt * con_conductance(i) * (v(con_from(i)) - v(con_to(i))) rhs(con_to(i)) = rhs(con_to(i)) + b rhs(con_from(i)) = rhs(con_from(i)) - b diag(con_to(i)) = diag(con_to(i)) - offdiag(i) diag(con_from(i)) = diag(con_from(i)) - offdiag(i) end do diag(pos_vcs) = 1. rhs(pos_vcs) = 0;
Forward sweep
Eliminates points to the right of the leading diagonal, working from the bottom up so that no new elemnts are introduced
do i = nconnections, 1, -1 i_from = con_from(i) i_to = con_to(i) f = offdiag(i) / diag(i_to) rhs(i_from) = rhs(i_from) - f * rhs(i_to) diag(i_from) = diag(i_from) - f * offdiag(i) end do diag(pos_vcs) = 1. rhs(pos_vcs) = 0;
Backsubstitute
The only complication here is that because the loop is over connections, not compartments, it is necessary to check for when a complete row has been finished in order to normalize by the diagonal.
icpt = 1 do i = 1, nconnections if (con_to(i) .ne. icpt) then rhs(icpt) = rhs(icpt) / diag(icpt) icpt = con_to(icpt) end if rhs(con_to(i)) = rhs(con_to(i)) - offdiag(i) * rhs(con_from(i)) end do rhs(ncompartments) = rhs(ncompartments) / diag(ncompartments) v = v + rhs
The last step above is to increment v by the deltaV values that are in the rhs array.