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.

