<p><b>mpetersen@lanl.gov</b> 2011-03-24 15:42:29 -0600 (Thu, 24 Mar 2011)</p><p>BRANCH COMMIT Update to implicit vertical mix branch.  Code works for double-gyre with inverse stratification.  This commit includes print lines for debugging.<br>
</p><hr noshade><pre><font color="gray">Modified: branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/Registry
===================================================================
--- branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/Registry        2011-03-24 18:27:00 UTC (rev 767)
+++ branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/Registry        2011-03-24 21:42:29 UTC (rev 768)
@@ -199,9 +199,9 @@
 var persistent real    CFLNumberGlobal ( Time ) 2 o CFLNumberGlobal state - -
 
 # Diagnostics fields, only one time level required
-var persistent real    RiTopOfCell ( nVertLevelsP1 nCells ) 0 o RiTopOfCell diagnostics - -
-var persistent real    RiTopOfEdge ( nVertLevelsP1 nEdges ) 0 o RiTopOfEdge diagnostics - -
-var persistent real    vertViscTopOfEdge ( nVertLevelsP1 nEdges ) 0 o vertViscTopOfEdge diagnostics - -
-var persistent real    vertDiffTopOfCell ( nVertLevelsP1 nCells ) 0 o vertDiffTopOfCell diagnostics - -
+var persistent real    RiTopOfCell ( nVertLevelsP1 nCells Time ) 1 o RiTopOfCell diagnostics - -
+var persistent real    RiTopOfEdge ( nVertLevelsP1 nEdges Time ) 1 o RiTopOfEdge diagnostics - -
+var persistent real    vertViscTopOfEdge ( nVertLevelsP1 nEdges Time ) 1 o vertViscTopOfEdge diagnostics - -
+var persistent real    vertDiffTopOfCell ( nVertLevelsP1 nCells Time ) 1 o vertDiffTopOfCell diagnostics - -
 
 

Modified: branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/module_mpas_core.F
===================================================================
--- branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/module_mpas_core.F        2011-03-24 18:27:00 UTC (rev 767)
+++ branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/module_mpas_core.F        2011-03-24 21:42:29 UTC (rev 768)
@@ -81,10 +81,38 @@
    
       call compute_solve_diagnostics(dt, block % state % time_levs(1) % state, mesh)
  
+! mrp causes error Subscript #1 of the array INDX has value 7 which is greater than the upper bound of 6
       call rbfInterp_initialize(mesh)
       call init_reconstruct(mesh)
       call reconstruct(block % state % time_levs(1) % state, mesh)
 
+      ! mrp 110131 testing only
+      block % mesh % u_src % array(:,:) = &amp;
+        block % mesh % u_src % array(:,:) *100
+     print *, 'min,maxval(u_src) ',minval( block % mesh % u_src % array(:,:)),maxval( block % mesh % u_src % array(:,:))
+
+      do iCell=1,block % mesh % nCells
+         do k=1,mesh % nVertLevels
+            !block % state % time_levs(1) % state % tracers % array( &amp;
+            !   1, k ,iCell) =  31-k/1000.0  !31-k
+            !block % state % time_levs(1) % state % tracers % array( &amp;
+            !   2, k ,iCell) =  32 !+ k*0.32
+            !block % state % time_levs(1) % state % tracers % array( &amp;
+            !   3, k ,iCell) =  k
+         enddo
+            block % state % time_levs(1) % state % tracers % array( &amp;
+               3, :,iCell) =  1.
+            block % state % time_levs(1) % state % tracers % array( &amp;
+               4, :,iCell) =  1.
+
+         do k=1,mesh % nVertLevels,2
+            block % state % time_levs(1) % state % tracers % array( &amp;
+               4, k ,iCell) =  0.
+         enddo
+
+      end do
+      ! mrp 110131 testing only end
+
       ! initialize velocities and tracers on land to be -1e34
       ! The reconstructed velocity on land will have values not exactly
       ! -1e34 due to the interpolation of reconstruction.

Modified: branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/module_time_integration.F
===================================================================
--- branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/module_time_integration.F        2011-03-24 18:27:00 UTC (rev 767)
+++ branches/ocean_projects/imp_vert_mix_mrp/src/core_ocean/module_time_integration.F        2011-03-24 21:42:29 UTC (rev 768)
@@ -72,11 +72,20 @@
       type (block_type), pointer :: block
       type (state_type) :: provis
 
-      integer :: rk_step, iEdge
+      integer :: rk_step, iEdge, cell1, cell2
 
       real (kind=RKIND), dimension(4) :: rk_weights, rk_substep_weights
-      real (kind=RKIND), dimension(:), allocatable:: A,C,R,X
 
+      integer :: nCells, nEdges, nVertLevels, num_tracers
+      real (kind=RKIND), dimension(:,:), pointer :: &amp;
+        u, h, h_edge, vertViscTopOfEdge, vertDiffTopOfCell
+      real (kind=RKIND), dimension(:,:,:), pointer :: tracers
+      integer, dimension(:), pointer :: &amp; 
+        maxLevelCell, maxLevelEdgeTop
+      real (kind=RKIND), dimension(:), allocatable:: A,C,uTemp
+      real (kind=RKIND), dimension(:,:), allocatable:: tracersTemp
+
+
       block =&gt; domain % blocklist
       call allocate_state(provis, &amp;
                           block % mesh % nCells, block % mesh % nEdges, block % mesh % maxEdges, block % mesh % maxEdges2, &amp;
@@ -231,45 +240,116 @@
       block =&gt; domain % blocklist
       do while (associated(block))
 
+         u           =&gt; block % state % time_levs(2) % state % u % array
+         tracers     =&gt; block % state % time_levs(2) % state % tracers % array
+         h           =&gt; block % state % time_levs(2) % state % h % array
+         h_edge      =&gt; block % state % time_levs(2) % state % h_edge % array
+         num_tracers = block % state % time_levs(2) % state % num_tracers
+         vertViscTopOfEdge =&gt; block % diagnostics % vertViscTopOfEdge % array
+         vertDiffTopOfCell =&gt; block % diagnostics % vertDiffTopOfCell % array
+         maxLevelCell    =&gt; block % mesh % maxLevelCell % array
+         maxLevelEdgeTop =&gt; block % mesh % maxLevelEdgeTop % array
+                  
+         nCells      = block % mesh % nCells
+         nEdges      = block % mesh % nEdges
+         nVertLevels = block % mesh % nVertLevels
+
+         do iCell=1,nCells
+            do k=1,maxLevelCell(iCell)
+               tracers(:,k,iCell) = tracers(:,k,iCell) / h(k,iCell)
+            end do
+         end do
+
          if (config_implicit_vertical_mix) then
-            allocate(A(block % mesh % nVertLevels),C(block % mesh % nVertLevels),R(block % mesh % nVertLevels),X(block % mesh % nVertLevels))
+            allocate(A(nVertLevels),C(nVertLevels),uTemp(nVertLevels), &amp;
+               tracersTemp(num_tracers,nVertLevels))
 
-            call compute_vertical_mix_coefficients(block % state % time_levs(2) % state, block % diagnostics, block % mesh)
+            call compute_vertical_mix_coefficients(provis, block % diagnostics, block % mesh)
 
-            do iCell=1,block % mesh % nCells
+!print '(a,10es12.4)', 'u1', minval(u(:,1:nEdges)),maxval(u(:,1:nEdges))
+! should I use nEdges or nEdgesSolve here?
+            do iEdge=1,nEdges
+              if (maxLevelEdgeTop(iEdge).gt.0) then
 
- C=-2
- do k=1,10
-    A(k) = 9.0 + k/10.0
-    R(k)=k
- enddo
+               ! Compute A(k), C(k) for momentum
+               ! mrp 110315 efficiency note: for z-level, could precompute
+               ! -2.0*dt/(h(k)_h(k+1))/h(k) in setup
+               ! h_edge is computed in compute_solve_diag, and is not available yet.
+               ! This could be removed if hZLevel used instead.
+               cell1 = block % mesh % cellsOnEdge % array(1,iEdge)
+               cell2 = block % mesh % cellsOnEdge % array(2,iEdge)
+               do k=1,maxLevelEdgeTop(iEdge)
+                  h_edge(k,iEdge) = 0.5 * (h(k,cell1) + h(k,cell2))
+               end do
 
- call tridiagonal_solve(A,C,A,R,X,10)
-print '(a,10f10.4)', 'A', A(1:10)
-print '(a,10f10.4)', 'C', C(1:10)
-print '(a,10f10.4)', 'R', R(1:10)
-print '(a,10f10.4)', 'X', X(1:10)
-stop
+               do k=1,maxLevelEdgeTop(iEdge)-1
+                  A(k) = -2.0*dt*vertViscTopOfEdge(k+1,iEdge) &amp;
+                     / (h_edge(k,iEdge) + h_edge(k+1,iEdge)) &amp;
+                     / h_edge(k,iEdge)
+               enddo
+               A(maxLevelEdgeTop(iEdge)) = 0.0
 
-            !   do k=1,maxLevelCell(iCell)
-               ! Compute A(k), C(k), R(k) for momentum
-             !  enddo
-               !call tridiagonal_solve(u(:,iCell),A(2:N),C(1:N),A(1:N-1),R)
+               C(1) = 1 - A(1)
+               do k=2,maxLevelEdgeTop(iEdge)
+                  C(k) = 1 - A(k) - A(k-1)
+               enddo
 
-              ! do k=1,maxLevelCell(iCell)
-               ! Compute A(k), C(k), R(iTracer,k) for tracers
-               !enddo
-               !call tridiagonal_solve_mult(tracers(:,:,iCell),A(2:N),C(1:N),A(1:N-1),R)
+               call tridiagonal_solve(A,C,A,u(:,iEdge),uTemp,maxLevelEdgeTop(iEdge))
+
+!print '(a,2i4)', 'iEdge, maxLevelEdgeTop(iEdge))', iEdge,maxLevelEdgeTop(iEdge)
+!print '(a,100es12.4)', 'vertViscTopOfEdge(:,iEdge)', vertViscTopOfEdge(:,iEdge)
+!print '(a,100es12.4)', 'h_edge', h_edge(:,iEdge)
+!print '(a,100es12.4)', 'dt', dt
+!print '(a,100es12.4)', 'A', A
+!print '(a,100es12.4)', 'C', C
+!print '(a,100es12.4)', 'u(:,iEdge)', u(:,iEdge)
+!print '(a,100es12.4)', 'uTemp     ', uTemp
+!stop
+
+! mrp temp, turn off implicit on u:
+               u(1:maxLevelEdgeTop(iEdge),iEdge) = uTemp(1:maxLevelEdgeTop(iEdge))
+               u(maxLevelEdgeTop(iEdge)+1:nVertLevels,iEdge) = 0.0
+
+              end if
             end do
-            deallocate(A,C,R,X)
-         else
-            do iCell=1,block % mesh % nCells
-               do k=1,block % mesh % maxLevelCell % array(iCell)
-                  block % state % time_levs(2) % state % tracers % array(:,k,iCell) = &amp;
-                        block % state % time_levs(2) % state % tracers % array(:,k,iCell)  &amp;
-                       / block % state % time_levs(2) % state % h % array(k,iCell)
-               end do
+!print '(a,10es12.4)', 'u2', minval(u(:,1:nEdges)),maxval(u(:,1:nEdges))
+
+
+            do iCell=1,nCells
+               ! Compute A(k), C(k) for tracers
+               ! mrp 110315 efficiency note: for z-level, could precompute
+               ! -2.0*dt/(h(k)_h(k+1))/h(k) in setup
+               do k=1,maxLevelCell(iCell)-1
+                  A(k) = -2.0*dt*vertDiffTopOfCell(k+1,iCell) &amp;
+                     / (h(k,iCell) + h(k+1,iCell)) &amp;
+                     / h(k,iCell)
+               enddo
+
+               A(maxLevelCell(iCell)) = 0.0
+
+               C(1) = 1 - A(1)
+               do k=2,maxLevelCell(iCell)
+                  C(k) = 1 - A(k) - A(k-1)
+               enddo
+
+               call tridiagonal_solve_mult(A,C,A,tracers(:,:,iCell), &amp;
+                  tracersTemp, maxLevelCell(iCell), &amp;
+                  nVertLevels,num_tracers)
+
+!mrp temp
+               tracers(:,1:maxLevelCell(iCell),iCell) = tracersTemp(:,1:maxLevelCell(iCell))
+! mrp temp remove soon:
+!               do k=1,maxLevelCell(iCell)
+!                  tracers(:,k,iCell) = tracers(:,k,iCell) / h(k,iCell)
+!               end do
+! mrp temp end
+! mrp set as follows
+!               tracers(:,maxLevelCell(iCell)+1:nVertLevels,iCell) = -1e34
+               tracers(:,maxLevelCell(iCell)+1:nVertLevels,iCell) = 0
+
             end do
+!print '(a,10es12.4)', 'tracer', minval(tracers(:,:,1:nCells)),maxval(tracers(:,:,1:nCells))
+            deallocate(A,C,uTemp,tracersTemp)
          end if
 
          if (config_test_case == 1) then    ! For case 1, wind field should be fixed
@@ -278,6 +358,7 @@
 
          call compute_solve_diagnostics(dt, block % state % time_levs(2) % state, block % mesh)
 
+! mrp causes error Subscript #1 of the array INDX has value 7 which is greater than the upper bound of 6
          call reconstruct(block % state % time_levs(2) % state, block % mesh)
 
          block =&gt; block % next
@@ -681,6 +762,8 @@
       !
       ! velocity tendency: vertical mixing d/dz( nu_v du/dz))
       !
+!mrp indent later
+      if (.not.config_implicit_vertical_mix) then
       allocate(fluxVertTop(nVertLevels+1))
       fluxVertTop(1) = 0.0
       do iEdge=1,grid % nEdgesSolve
@@ -700,7 +783,7 @@
 
       end do
       deallocate(fluxVertTop)
-
+      endif
    end subroutine compute_tend
 
 
@@ -1207,6 +1290,8 @@
       !
       ! tracer tendency: vertical diffusion h d/dz( \kappa_v d\phi/dz)
       !
+!mrp indent later
+      if (.not.config_implicit_vertical_mix) then
       allocate(fluxVertTop(num_tracers,nVertLevels+1))
       fluxVertTop(:,1) = 0.0
       do iCell=1,nCellsSolve 
@@ -1232,6 +1317,7 @@
 
       enddo ! iCell loop
       deallocate(fluxVertTop)
+      endif
 
           ! print some diagnostics - for debugging
 !         print *, 'after vertical mixing',&amp;
@@ -1638,6 +1724,11 @@
       ! For an isopycnal model, density should remain constant.
       if (config_vert_grid_type.eq.'zlevel') then
          call equation_of_state(s,grid,-1)
+
+! mrp temp, just to visualize rhoDisplaced
+      call equation_of_state(s, grid, 1)
+! mrp temp, just to visualize rhoDisplaced end
+
       endif
 
       !
@@ -1794,17 +1885,25 @@
       real (kind=RKIND) :: r, h1, h2
 
       rhoDisplaced =&gt; s % rhoDisplaced % array
+      u           =&gt; s % u % array
+      h           =&gt; s % h % array
+      h_edge      =&gt; s % h_edge % array
 
       vertViscTopOfEdge =&gt; d % vertViscTopOfEdge % array
       vertDiffTopOfCell =&gt; d % vertDiffTopOfCell % array
       RiTopOfEdge =&gt; d % RiTopOfEdge % array
       RiTopOfCell =&gt; d % RiTopOfCell % array
 
-      h           =&gt; s % h % array
-      u           =&gt; s % u % array
+
+!
+!
+! mmmmmmmmmmmmmmmmmmmmmmm mrp delete variables later
+!
+!
+
+
       v           =&gt; s % v % array
       wTop        =&gt; s % wTop % array
-      h_edge      =&gt; s % h_edge % array
       circulation =&gt; s % circulation % array
       vorticity   =&gt; s % vorticity % array
       divergence  =&gt; s % divergence % array
@@ -1846,6 +1945,7 @@
       maxLevelVertexBot =&gt; grid % maxLevelVertexBot % array
       maxLevelVertexTop =&gt; grid % maxLevelVertexTop % array
                   
+
       nCells      = grid % nCells
       nEdges      = grid % nEdges
       nVertices   = grid % nVertices
@@ -1867,6 +1967,11 @@
       ! compute density of parcel displaced to surface, $\rho^*$,
       ! in state % rhoDisplaced
       call equation_of_state(s, grid, 1)
+! mrp delete:
+!print '(a,10es12.4)', 'temperature', minval(tracers(1,2:10,1:nCells)),maxval(tracers(1,2:10,1:nCells))
+!print '(a,10es12.4)', 'salinity', minval(tracers(2,2:10,1:nCells)),maxval(tracers(2,2:10,1:nCells))
+!print '(a,10es12.4)', 'rhoDisplaced', minval(rhoDisplaced(2:10,1:nCells)),maxval(rhoDisplaced(2:10,1:nCells))
+!print '(a,10es12.4)', 'h_edge', minval(h_edge(2:10,1:nEdges)),maxval(h_edge(2:10,1:nEdges))
 
       ! drhoTopOfCell(k) = $\rho^*_{k-1}-\rho^*_k$
       drhoTopOfCell = 0.0
@@ -1915,6 +2020,8 @@
 
 !test this interp
 
+! are there issues with updating proc boundaries here?
+
       ! compute RiTopOfEdge using drhoTopOfEdge and du2TopOfEdge
       ! coef = -g/rho_0/2
       RiTopOfEdge = 0.0
@@ -1939,6 +2046,13 @@
          end do
       end do
 
+!print '(a,10es12.4)', 'RiTopOfCell', minval(RiTopOfCell(2:10,1:nCells)),maxval(RiTopOfCell(2:10,1:nCells))
+!print '(a,10es12.4)', 'RiTopOfEdge', minval(RiTopOfEdge(2:10,1:nEdges)),maxval(RiTopOfEdge(2:10,1:nEdges))
+!print *, 'gravity',gravity
+!print '(a,10es12.4)', 'drhoTopOfCell', minval(drhoTopOfCell(2:10,1:nCells)),maxval(drhoTopOfCell(2:10,1:nCells))
+!print '(a,10es12.4)', 'du2TopOfCell', minval(du2TopOfCell(2:10,1:nCells)),maxval(du2TopOfCell(2:10,1:nCells))
+!print '(a,10es12.4)', 'h', minval(h(2:10,1:nCells)),maxval(h(2:10,1:nCells))
+
       
 ! what about boundary update?
 
@@ -1947,6 +2061,9 @@
         du2TopOfCell, du2TopOfEdge)
    endif
 
+   !
+   !  Compute vertical viscosity
+   !
    if (config_vert_visc_type.eq.'const') then
 
       vertViscTopOfEdge = config_vert_viscosity
@@ -1971,8 +2088,18 @@
       vertViscTopOfEdge = 0.0
       do iEdge = 1,nEdges
          do k = 2,maxLevelEdgeTop(iEdge)
-            vertViscTopOfEdge(k,iEdge) = config_bkrd_vert_visc &amp;
-               + config_rich_mix / (1.0 + 5.0*RiTopOfEdge(k,iEdge))**2
+            ! mrp 110324 efficiency note: this if is inside iCell and k loops.
+            ! Perhaps there is a more efficient way to do this.
+            if (RiTopOfCell(k,iCell)&gt;0.0) then
+               vertViscTopOfEdge(k,iEdge) = config_bkrd_vert_visc &amp;
+                  + config_rich_mix / (1.0 + 5.0*RiTopOfEdge(k,iEdge))**2
+            else
+               ! for Ri&lt;0, use maximum diffusion allowed by CFL criterion
+               ! mrp 110324 efficiency note: for z-level, could use fixed
+               ! grid array hMeanTopZLevel and compute maxdiff on startup.
+               vertViscTopOfEdge(k,iEdge) = &amp;
+                   (h_edge(k-1,iEdge)+h_edge(k,iEdge))**2/config_dt/4.0
+            endif
          end do
       end do
 
@@ -1983,6 +2110,9 @@
 
    endif
 
+   !
+   !  Compute vertical tracer diffusion
+   !
    if (config_vert_diff_type.eq.'const') then
 
       vertDiffTopOfCell = config_vert_diffusion
@@ -2008,10 +2138,20 @@
       coef = -gravity/1000.0/2.0
       do iCell = 1,nCells
          do k = 2,maxLevelCell(iCell)
-            vertDiffTopOfCell(k,iCell) = config_bkrd_vert_diff &amp;
-               + (config_bkrd_vert_visc &amp; 
-                  + config_rich_mix / (1.0 + 5.0*RiTopOfCell(k,iCell))**2) &amp;
-               / (1.0 + 5.0*RiTopOfCell(k,iCell))**2
+            ! mrp 110324 efficiency note: this if is inside iCell and k loops.
+            ! Perhaps there is a more efficient way to do this.
+            if (RiTopOfCell(k,iCell)&gt;0.0) then
+               vertDiffTopOfCell(k,iCell) = config_bkrd_vert_diff &amp;
+                  + (config_bkrd_vert_visc &amp; 
+                     + config_rich_mix / (1.0 + 5.0*RiTopOfCell(k,iCell))**2) &amp;
+                  / (1.0 + 5.0*RiTopOfCell(k,iCell))
+             else
+                ! for Ri&lt;0, use maximum diffusion allowed by CFL criterion
+                ! mrp 110324 efficiency note: for z-level, could use fixed
+                ! grid array hMeanTopZLevel and compute maxdiff on startup.
+                vertDiffTopOfCell(k,iCell) = &amp;
+                   (h(k-1,iCell)+h(k,iCell))**2/config_dt/4.0
+             end if
          end do
       end do
 
@@ -2022,6 +2162,8 @@
 
    endif
 
+!print '(a,10es12.4)', 'vertDiffTopOfCell', minval(vertDiffTopOfCell(2:10,1:nCells)),maxval(vertDiffTopOfCell(2:10,1:nCells))
+!print '(a,10es12.4)', 'vertViscTopOfEdge', minval(vertViscTopOfEdge(2:10,1:nEdges)),maxval(vertViscTopOfEdge(2:10,1:nEdges))
 
    end subroutine compute_vertical_mix_coefficients
 
@@ -2349,21 +2491,36 @@
       DENOMK = 1.0/(BULK_MOD - p(k))
 
       rhoPointer(k,iCell) = (unt0 + RHO_S)*BULK_MOD*DENOMK
+!mrp 
+!   if (k_displaced.gt.0) then
+!print '(a,2i5,10es22.14)', 'eos icell,k,T,S,rho', icell,k,TQ,SQ,rhoPointer(k,iCell)
+!   endif
+!mrp 
 
     end do
   end do
 
+!mrp 
+!   if (k_displaced.gt.0) then
+!print '(a,10es22.14)', 'eos temperature', minval(tracers(1,2:10,1:nCells)),maxval(tracers(1,2:10,1:nCells))
+!print '(a,10es22.14)', 'eos salinity', minval(tracers(2,2:10,1:nCells)),maxval(tracers(2,2:10,1:nCells))
+!print '(a,10es22.14)', 'eos rhoDisplaced', minval(rhoPointer(2:10,1:nCells)),maxval(rhoPointer(2:10,1:nCells))
+!   stop
+!   endif
+!mrp 
+
       deallocate(pRefEOS,p,p2)
 
    end subroutine equation_of_state_jm
 
+
 subroutine tridiagonal_solve(a,b,c,r,x,n)
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 ! Solve the matrix equation Ax=r for x, where A is tridiagonal.
 ! A is an nxn matrix, with:
-!   a sub-diagonal, filled from 2:n
+!   a sub-diagonal, filled from 1:n-1 (a(1) appears on row 2)
 !   b diagonal, filled from 1:n
-!   c sup-diagonal, filled from 1:n-1
+!   c sup-diagonal, filled from 1:n-1  (c(1) apears on row 1)
 !
 ! Input: a,b,c,r,n
 !
@@ -2385,12 +2542,10 @@
  
    ! First pass: set the coefficients
    do i = 2,n
-      m = a(i)/bTemp(i-1)
+      m = a(i-1)/bTemp(i-1)
       bTemp(i) = b(i) - m*c(i-1)
       rTemp(i) = r(i) - m*rTemp(i-1)
    end do 
-print '(a,10f8.2)', 'bTemp', bTemp(1:n)
-print '(a,10f8.2)', 'rTemp', rTemp(1:n)
  
    x(n) = rTemp(n)/bTemp(n)
    ! Second pass: back-substition
@@ -2401,4 +2556,56 @@
 end subroutine tridiagonal_solve
 
 
+subroutine tridiagonal_solve_mult(a,b,c,r,x,n,nDim,nSystems)
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Solve the matrix equation Ax=r for x, where A is tridiagonal.
+! A is an nxn matrix, with:
+!   a sub-diagonal, filled from 1:n-1 (a(1) appears on row 2)
+!   b diagonal, filled from 1:n
+!   c sup-diagonal, filled from 1:n-1  (c(1) apears on row 1)
+!
+! Input: a,b,c,r,n
+!
+! Output: x
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

+   implicit none
+
+   integer,intent(in) :: n, nDim, nSystems
+   real (KIND=RKIND), dimension(n), intent(in) :: a,b,c
+   real (KIND=RKIND), dimension(nSystems,nDim), intent(in) :: r
+   real (KIND=RKIND), dimension(nSystems,nDim), intent(out) :: x
+   real (KIND=RKIND), dimension(n) :: bTemp
+   real (KIND=RKIND), dimension(nSystems,n) :: rTemp
+   real (KIND=RKIND) :: m
+   integer i,j

+   ! Use work variables for b and r
+   bTemp(1) = b(1)
+   do j = 1,nSystems
+      rTemp(j,1) = r(j,1)
+   end do

+   ! First pass: set the coefficients
+   do i = 2,n
+      m = a(i-1)/bTemp(i-1)
+      bTemp(i) = b(i) - m*c(i-1)
+      do j = 1,nSystems
+         rTemp(j,i) = r(j,i) - m*rTemp(j,i-1)
+      end do 
+   end do 

+   do j = 1,nSystems
+      x(j,n) = rTemp(j,n)/bTemp(n)
+   end do
+   ! Second pass: back-substition
+   do i = n-1, 1, -1
+      do j = 1,nSystems
+         x(j,i) = (rTemp(j,i) - c(i)*x(j,i+1))/bTemp(i)
+      end do
+   end do

+end subroutine tridiagonal_solve_mult
+
+
 end module time_integration

</font>
</pre>