<p><b>xylar@lanl.gov</b> 2010-02-05 16:51:55 -0700 (Fri, 05 Feb 2010)</p><p>* Added global_diagnostics module that computes a few global reductions (more to come!)<br>
* Added Todd's vector reconstruction module that uses radial basis functions<br>
   Note: this module requires LAPACK for matrix inversion<br>
* Made changes from the shallow water branch to handle vertexDegree != 3 <br>
* Fixed a bug in fortprintf.c that occasionally put an &amp; on its own line<br>
<br>
-Xylar<br>
</p><hr noshade><pre><font color="gray">Modified: branches/ocean/Makefile
===================================================================
--- branches/ocean/Makefile        2010-02-02 23:59:45 UTC (rev 113)
+++ branches/ocean/Makefile        2010-02-05 23:51:55 UTC (rev 114)
@@ -33,7 +33,7 @@
 
 CPPINCLUDES = -I../inc -I$(NETCDF)/include
 FCINCLUDES = -I../inc -I$(NETCDF)/include
-LIBS = -L$(NETCDF)/lib -lnetcdf
+LIBS = -L$(NETCDF)/lib -lnetcdf -llapack
 
 RM = rm -f
 CPP = cpp -C -P -traditional

Modified: branches/ocean/Registry/Registry
===================================================================
--- branches/ocean/Registry/Registry        2010-02-02 23:59:45 UTC (rev 113)
+++ branches/ocean/Registry/Registry        2010-02-05 23:51:55 UTC (rev 114)
@@ -7,6 +7,9 @@
 namelist integer   sw_model config_ntimesteps        7500
 namelist integer   sw_model config_output_interval   500
 namelist real      sw_model config_visc              0.0
+namelist character io       config_input_name        grid.nc
+namelist character io       config_output_name       output.nc
+namelist character io       config_restart_name      restart.nc
 namelist integer   restart  config_restart_interval  0
 namelist logical   restart  config_do_restart        false
 namelist real      restart  config_restart_time      172800.0
@@ -20,12 +23,13 @@
 dim maxEdges2 maxEdges2
 dim nVertices nVertices
 dim TWO 2
-dim THREE 3
+dim R3 3
+dim vertexDegree vertexDegree
 dim nVertLevels nVertLevels
 dim nTracers nTracers
 
 #
-# var  type  name_in_file  ( dims )  iro-  name_in_code
+# var  type  name_in_file  ( dims )  iro-  name_in_code super-array array_class
 #
 var real    xtime ( Time ) ro xtime - -
 
@@ -66,13 +70,19 @@
 var integer cellsOnCell ( maxEdges nCells ) iro cellsOnCell - -
 var integer verticesOnCell ( maxEdges nCells ) iro verticesOnCell - -
 var integer verticesOnEdge ( TWO nEdges ) iro verticesOnEdge - -
-var integer edgesOnVertex ( THREE nVertices ) iro edgesOnVertex - -
-var integer cellsOnVertex ( THREE nVertices ) iro cellsOnVertex - -
-var real    kiteAreasOnVertex ( THREE nVertices ) iro kiteAreasOnVertex - -
+var integer edgesOnVertex ( vertexDegree nVertices ) iro edgesOnVertex - -
+var integer cellsOnVertex ( vertexDegree nVertices ) iro cellsOnVertex - -
+var real    kiteAreasOnVertex ( vertexDegree nVertices ) iro kiteAreasOnVertex - -
 var real    fEdge ( nEdges ) iro fEdge - -
 var real    fVertex ( nVertices ) iro fVertex - -
 var real    h_s ( nCells ) iro h_s - -
 
+# Arrays required for reconstruction of velocity field
+var real    matrix_reconstruct ( maxEdges maxEdges nCells ) - matrix_reconstruct - -
+var real    normal ( R3 maxEdges nCells ) - normal - -
+var real    rbf_value ( maxEdges nCells ) - rbf_value - -
+var real    coeffs_reconstruct ( R3 maxEdges nCells ) - coeffs_reconstruct - -
+
 # Boundary conditions: read from input, saved in restart and written to output
 var integer uBC ( nVertLevels nEdges ) iro uBC - -
 var real    u_src ( nVertLevels nEdges ) iro u_src - -
@@ -91,9 +101,27 @@
 var real    ke ( nVertLevels nCells Time ) o ke - -
 var real    pv_vertex ( nVertLevels nVertices Time ) o pv_vertex - -
 var real    pv_cell ( nVertLevels nCells Time ) o pv_cell - -
+var real    uReconstructX ( nVertLevels nCells Time ) o uReconstructX - -
+var real    uReconstructY ( nVertLevels nCells Time ) o uReconstructY - -
+var real    uReconstructZ ( nVertLevels nCells Time ) o uReconstructZ - -
 
 # Other diagnostic variables: neither read nor written to any files
 var real    vh ( nVertLevels nEdges Time ) - vh - -
 var real    circulation ( nVertLevels nVertices Time ) - circulation - -
 var real    gradPVt ( nVertLevels nEdges Time ) - gradPVt - -
 var real    gradPVn ( nVertLevels nEdges Time ) - gradPVn - -
+
+# xsad 10-02-05:
+# Globally reduced diagnostic variables: only written to output
+var real    cellAreaGlobal ( Time ) o cellAreaGlobal - -
+var real    edgeAreaGlobal ( Time ) o edgeAreaGlobal - -
+var real    triangleAreaGlobal ( Time ) o triangleAreaGlobal - -
+
+var real    cellVolumeGlobal ( Time ) o cellVolumeGlobal - -
+var real    keGlobal ( Time ) o keGlobal - -
+var real    averageLayerThicknessGlobal ( Time ) o averageLayerThicknessGlobal - -
+var real    maximumVelocityGlobal ( Time ) o maximumVelocityGlobal - -
+var real    minimumLayerThicknessGlobal ( Time ) o minimumLayerThicknessGlobal - -
+var real    CFLNumberGlobal ( Time ) o CFLNumberGlobal - -
+# xsad 10-02-05 end
+

Modified: branches/ocean/Registry/fortprintf.c
===================================================================
--- branches/ocean/Registry/fortprintf.c        2010-02-02 23:59:45 UTC (rev 113)
+++ branches/ocean/Registry/fortprintf.c        2010-02-05 23:51:55 UTC (rev 114)
@@ -24,7 +24,11 @@
       for(i=0; i&lt;MAX_LINE_LEN-1 &amp;&amp; i&lt;nbuf; i++) {
          if (fbuffer[i] == '\'' &amp;&amp; (fbuffer[i+1] != '\'' || i == nbuf-1)) inquotes = (inquotes + 1) % 2;
          if (fbuffer[i] == '</font>
<font color="gray">') nl = i;
-         if (fbuffer[i] == ' ') sp = i;
+         // xsad 10-02-03:
+         //if (fbuffer[i] == ' ') sp = i;
+         if ((fbuffer[i] == ' ') &amp;&amp; (i != nbuf-1) &amp;&amp; (fbuffer[i+1] != '&amp;'))
+            sp = i;
+         // end xsad 10-02-03
       }
       if (nbuf &lt;= MAX_LINE_LEN) sp = -1;
 

Modified: branches/ocean/src/Makefile
===================================================================
--- branches/ocean/src/Makefile        2010-02-02 23:59:45 UTC (rev 113)
+++ branches/ocean/src/Makefile        2010-02-05 23:51:55 UTC (rev 114)
@@ -13,6 +13,8 @@
        module_dmpar.o \
        module_io_input.o \
        module_io_output.o \
+       module_global_diagnostics.o \
+       module_vector_reconstruction.o \
        module_time_integration.o \
        streams.o
 
@@ -34,10 +36,14 @@
 
 module_sw_solver.o: module_configure.o module_grid_types.o module_io_output.o module_time_integration.o module_dmpar.o module_timer.o
 
-module_time_integration.o: module_grid_types.o module_configure.o module_dmpar.o
+module_time_integration.o: module_grid_types.o module_configure.o module_dmpar.o module_global_diagnostics.o module_vector_reconstruction.o
 
 module_test_cases.o: module_grid_types.o module_configure.o module_constants.o module_dmpar.o
 
+module_vector_reconstruction.o: module_grid_types.o module_configure.o module_constants.o
+
+module_global_diagnostics.o: module_grid_types.o module_configure.o module_dmpar.o 
+
 swmodel: $(OBJS)
         $(FC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
 

Modified: branches/ocean/src/module_dmpar.F
===================================================================
--- branches/ocean/src/module_dmpar.F        2010-02-02 23:59:45 UTC (rev 113)
+++ branches/ocean/src/module_dmpar.F        2010-02-05 23:51:55 UTC (rev 114)
@@ -241,7 +241,102 @@
 
    end subroutine dmpar_sum_int
 
+   !xsad 10-01-22:
+   subroutine dmpar_sum_real(dminfo, r, rsum)
 
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      real(kind=RKIND), intent(in) :: r
+      real(kind=RKIND), intent(out) :: rsum
+
+      integer :: mpi_ierr
+
+#ifdef _MPI
+      call MPI_Allreduce(r, rsum, 1, MPI_REALKIND, MPI_SUM, dminfo % comm, mpi_ierr)
+#else
+      rsum = r
+#endif
+
+   end subroutine dmpar_sum_real
+   !xsad 10-01-22 end
+
+   !xsad 10-02-01:
+   subroutine dmpar_min_int(dminfo, i, imin)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: i
+      integer, intent(out) :: imin
+
+      integer :: mpi_ierr
+
+#ifdef _MPI
+      call MPI_Allreduce(i, imin, 1, MPI_INTEGER, MPI_MIN, dminfo % comm, mpi_ierr)
+#else
+      imin = i
+#endif
+
+   end subroutine dmpar_min_int
+
+   subroutine dmpar_min_real(dminfo, r, rmin)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      real(kind=RKIND), intent(in) :: r
+      real(kind=RKIND), intent(out) :: rmin
+
+      integer :: mpi_ierr
+
+#ifdef _MPI
+      call MPI_Allreduce(r, rmin, 1, MPI_REALKIND, MPI_MIN, dminfo % comm, mpi_ierr)
+#else
+      rmin = r
+#endif
+
+   end subroutine dmpar_min_real
+
+   subroutine dmpar_max_int(dminfo, i, imax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: i
+      integer, intent(out) :: imax
+      
+      integer :: mpi_ierr 
+      
+#ifdef _MPI
+      call MPI_Allreduce(i, imax, 1, MPI_INTEGER, MPI_MAX, dminfo % comm, mpi_ierr)
+#else
+      imax = i
+#endif
+
+   end subroutine dmpar_max_int
+
+   subroutine dmpar_max_real(dminfo, r, rmax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      real(kind=RKIND), intent(in) :: r
+      real(kind=RKIND), intent(out) :: rmax
+
+      integer :: mpi_ierr
+
+#ifdef _MPI
+      call MPI_Allreduce(r, rmax, 1, MPI_REALKIND, MPI_MAX, dminfo % comm, mpi_ierr)
+#else
+      rmax = r
+#endif
+
+   end subroutine dmpar_max_real
+
+   !xsad 10-02-01 end
+
+
    subroutine dmpar_scatter_ints(dminfo, nprocs, noutlist, displs, counts, inlist, outlist)
 
       implicit none

Added: branches/ocean/src/module_global_diagnostics.F
===================================================================
--- branches/ocean/src/module_global_diagnostics.F                                (rev 0)
+++ branches/ocean/src/module_global_diagnostics.F        2010-02-05 23:51:55 UTC (rev 114)
@@ -0,0 +1,180 @@
+module global_diagnostics
+
+   use grid_types
+   use configure
+   use constants
+   use dmpar
+
+   implicit none
+   save
+   public
+
+   contains
+
+   subroutine computeGlobalDiagnostics(dminfo, state, grid, dt)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      type (grid_state), intent(inout) :: state
+      type (grid_meta), intent(in) :: grid
+      real (kind=RKIND), intent(in) :: dt
+
+      type (block_type), pointer :: block
+      integer :: nVertLevels, nCellsSolve, nEdgesSolve, nVerticesSolve
+      real (kind=RKIND) ::  cellAreaGlobal, edgeAreaGlobal, triangleAreaGlobal
+      real (kind=RKIND), dimension(:), pointer ::  areaCell, dcEdge, dvEdge, areaTriangle
+      real (kind=RKIND), dimension(:,:), pointer :: h, ke, u
+      real (kind=RKIND) :: cellVolumeGlobal, keGlobal, averageLayerThicknessGlobal, maximumVelocityGlobal, &amp;
+         minimumLayerThicknessGlobal, CFLNumberGlobal
+      real (kind=RKIND) ::  localCFL, localSum
+      integer :: elementIndex
+      integer :: timeLevel
+
+      nVertLevels = grid % nVertLevels
+      nCellsSolve = grid % nCellsSolve
+      nEdgesSolve = grid % nEdgesSolve
+      nVerticesSolve = grid % nVerticesSolve
+
+      areaCell =&gt; grid % areaCell % array
+      dcEdge =&gt; grid % dcEdge % array
+      dvEdge =&gt; grid % dvEdge % array
+      areaTriangle =&gt; grid % areaTriangle % array
+
+      h =&gt; state % h % array
+      ke =&gt; state % ke % array
+      u =&gt; state % u % array
+
+      localSum = sum(areaCell(1:nCellsSolve))
+      call dmpar_sum_real(dminfo, localSum, cellAreaGlobal)
+
+      localSum = sum(dcEdge(1:nEdgesSolve)*dvEdge(1:nEdgesSolve))
+      call dmpar_sum_real(dminfo, localSum, edgeAreaGlobal)
+
+      localSum = sum(areaTriangle(1:nVerticesSolve))
+      call dmpar_sum_real(dminfo, localSum, triangleAreaGlobal)
+
+      call computeAreaWeightedGlobalSum(dminfo, nVertLevels, nCellsSolve, &amp;
+         areaCell(1:nCellsSolve), h(:,1:nCellsSolve), cellVolumeGlobal)
+
+      averageLayerThicknessGlobal = cellVolumeGlobal/(cellAreaGlobal*nVertLevels)
+
+      call computeVolumeWeightedGlobalSum(dminfo, nVertLevels, nCellsSolve, &amp;
+         areaCell(1:nCellsSolve), h(:,1:nCellsSolve), ke(:,1:nCellsSolve), keGlobal)
+
+      call computeGlobalMax(dminfo, nVertLevels, nEdgesSolve, &amp;
+         u(:,1:nEdgesSolve), maximumVelocityGlobal)
+
+      call computeGlobalMin(dminfo, nVertLevels, nCellsSolve, &amp;
+         h(:,1:nEdgesSolve), minimumLayerThicknessGlobal)
+
+      localCFL = 0.0
+      do elementIndex = 1,nEdgesSolve
+         localCFL = max(localCFL, maxval(dt*u(:,elementIndex)/dcEdge(elementIndex)))
+      end do
+      call dmpar_max_real(dminfo, localCFL, CFLNumberGlobal)
+
+
+      state % cellAreaGlobal % scalar = cellVolumeGlobal
+      state % edgeAreaGlobal % scalar = edgeAreaGlobal
+      state % triangleAreaGlobal % scalar = triangleAreaGlobal
+
+      state % cellVolumeGlobal % scalar = cellVolumeGlobal
+      state % keGlobal % scalar = keGlobal
+      state % averageLayerThicknessGlobal % scalar = averageLayerThicknessGlobal
+      state % maximumVelocityGlobal % scalar = maximumVelocityGlobal
+      state % minimumLayerThicknessGlobal % scalar = minimumLayerThicknessGlobal
+      state % CFLNumberGlobal % scalar = CFLNumberGlobal
+
+   end subroutine computeGlobalDiagnostics
+
+   subroutine computeGlobalSum(dminfo, nVertLevels, nElements, field, globalSum)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalSum
+
+      real (kind=RKIND) :: localSum
+
+      localSum = sum(field)
+      call dmpar_sum_real(dminfo, localSum, globalSum)
+
+   end subroutine computeGlobalSum
+
+   subroutine computeAreaWeightedGlobalSum(dminfo, nVertLevels, nElements, areas, field, globalSum)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nElements), intent(in) :: areas
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalSum
+      
+      integer :: elementIndex
+      real (kind=RKIND) :: localSum
+
+      localSum = 0.
+      do elementIndex = 1, nElements
+        localSum = localSum + areas(elementIndex) * sum(field(:,elementIndex))
+      end do
+   
+      call dmpar_sum_real(dminfo, localSum, globalSum)
+       
+   end subroutine computeAreaWeightedGlobalSum
+
+   subroutine computeVolumeWeightedGlobalSum(dminfo, nVertLevels, nElements, areas, h, field, globalSum)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nElements), intent(in) :: areas
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: h
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalSum
+
+      real (kind=RKIND), dimension(nVertLevels, nElements) :: hTimesField
+
+      hTimesField = h*field
+
+      call computeAreaWeightedGlobalSum(dminfo, nVertLevels, nElements, areas, hTimesField, globalSum)
+
+   end subroutine computeVolumeWeightedGlobalSum
+
+   subroutine computeGlobalMin(dminfo, nVertLevels, nElements, field, globalMin)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalMin
+
+      real (kind=RKIND) :: localMin
+
+      localMin = minval(field)
+      call dmpar_min_real(dminfo, localMin, globalMin)
+
+   end subroutine computeGlobalMin
+
+   subroutine computeGlobalMax(dminfo, nVertLevels, nElements, field, globalMax)
+
+      implicit none
+
+      type (dm_info), intent(in) :: dminfo
+      integer, intent(in) :: nVertLevels, nElements
+      real (kind=RKIND), dimension(nVertLevels, nElements), intent(in) :: field
+      real (kind=RKIND), intent(out) :: globalMax
+
+      real (kind=RKIND) :: localMax
+
+      localMax = maxval(field)
+      call dmpar_max_real(dminfo, localMax, globalMax)
+
+   end subroutine computeGlobalMax
+
+end module global_diagnostics

Modified: branches/ocean/src/module_io_input.F
===================================================================
--- branches/ocean/src/module_io_input.F        2010-02-02 23:59:45 UTC (rev 113)
+++ branches/ocean/src/module_io_input.F        2010-02-05 23:51:55 UTC (rev 114)
@@ -91,9 +91,9 @@
       integer :: idxTdiff
 
       if (config_do_restart) then
-         input_obj % filename = 'restart.nc'
+         input_obj % filename = trim(config_restart_name)
       else
-         input_obj % filename = 'grid.nc'
+         input_obj % filename = trim(config_input_name)
       end if
       call io_input_init(input_obj, domain % dminfo)
    
@@ -207,9 +207,9 @@
       cellsOnVertexField % ioinfo % fieldName = 'cellsOnVertex'
       cellsOnVertexField % ioinfo % start(1) = 1
       cellsOnVertexField % ioinfo % start(2) = readVertexStart
-      cellsOnVertexField % ioinfo % count(1) = 3
+      cellsOnVertexField % ioinfo % count(1) = vertexDegree
       cellsOnVertexField % ioinfo % count(2) = nReadVertices
-      allocate(cellsOnVertexField % array(3,nReadVertices))
+      allocate(cellsOnVertexField % array(vertexDegree,nReadVertices))
       call io_input_field(input_obj, cellsOnVertexField)
    
    
@@ -397,14 +397,14 @@
       ! Work out which edges and vertices are owned by this process, and which are ghost
       ! 
       allocate(cellsOnEdge_2Halo(2,nlocal_edges))
-      allocate(cellsOnVertex_2Halo(3,nlocal_vertices))
+      allocate(cellsOnVertex_2Halo(vertexDegree,nlocal_vertices))
    
       call dmpar_alltoall_field(domain % dminfo, cellsOnEdgeField % array, cellsOnEdge_2Halo, &amp;
                                 2, size(cellsOnEdgeField % array, 2), nlocal_edges, &amp;
                                 sendEdgeList, recvEdgeList)
    
       call dmpar_alltoall_field(domain % dminfo, cellsOnVertexField % array, cellsOnVertex_2Halo, &amp;
-                                3, size(cellsOnVertexField % array, 2), nlocal_vertices, &amp;
+                                vertexDegree, size(cellsOnVertexField % array, 2), nlocal_vertices, &amp;
                                 sendVertexList, recvVertexList)
    
    
@@ -413,7 +413,7 @@
                                               2, nlocal_edges, cellsOnEdge_2Halo, local_edge_list, ghostEdgeStart)
       call block_decomp_partitioned_edge_list(block_graph_2Halo % nVertices, &amp;
                                               block_graph_2Halo % vertexID(1:block_graph_2Halo % nVertices), &amp;
-                                              3, nlocal_vertices, cellsOnVertex_2Halo, local_vertex_list, ghostVertexStart)
+                                              vertexDegree, nlocal_vertices, cellsOnVertex_2Halo, local_vertex_list, ghostVertexStart)
 
 
       ! At this point, local_edge_list(1;ghostEdgeStart-1) contains all of the owned edges for this block
@@ -501,7 +501,7 @@
 
          !
          ! If doing a restart, we need to decide which time slice to read from the 
-         !   restart.nc file
+         !   restart file
          !
          if (input_obj % rdLocalTime &lt;= 0) then
             write(0,*) 'Error: Couldn''t find any times in restart file.'
@@ -649,7 +649,7 @@
       end do
 
       do i=1,domain % blocklist % mesh % nVertices
-         do j=1,3
+         do j=1,vertexDegree
 
             k = binary_search(cellIDSorted, 2, 1, domain % blocklist % mesh % nCells, &amp;
                               domain % blocklist % mesh % cellsOnVertex % array(j,i))

Modified: branches/ocean/src/module_io_output.F
===================================================================
--- branches/ocean/src/module_io_output.F        2010-02-02 23:59:45 UTC (rev 113)
+++ branches/ocean/src/module_io_output.F        2010-02-05 23:51:55 UTC (rev 114)
@@ -3,6 +3,7 @@
    use grid_types
    use dmpar
    use sort
+   use configure
 
    integer, parameter :: OUTPUT = 1
    integer, parameter :: RESTART = 2
@@ -74,10 +75,10 @@
       nVertLevelsGlobal = block_ptr % mesh % nVertLevels
 
       if (trim(stream) == 'OUTPUT') then
-         output_obj % filename = 'output.nc'
+         output_obj % filename = trim(config_output_name)
          output_obj % stream = OUTPUT
       else if (trim(stream) == 'RESTART') then
-         output_obj % filename = 'restart.nc'
+         output_obj % filename = trim(config_restart_name)
          output_obj % stream = RESTART
       end if
 
@@ -149,8 +150,8 @@
       allocate(cellsOnEdge(2, domain % blocklist % mesh % nEdgesSolve))
       allocate(verticesOnEdge(2, domain % blocklist % mesh % nEdgesSolve))
       allocate(edgesOnEdge(2 * domain % blocklist % mesh % maxEdges, domain % blocklist % mesh % nEdgesSolve))
-      allocate(cellsOnVertex(3, domain % blocklist % mesh % nVerticesSolve))
-      allocate(edgesOnVertex(3, domain % blocklist % mesh % nVerticesSolve))
+      allocate(cellsOnVertex(domain % blocklist % mesh % vertexDegree, domain % blocklist % mesh % nVerticesSolve))
+      allocate(edgesOnVertex(domain % blocklist % mesh % vertexDegree, domain % blocklist % mesh % nVerticesSolve))
 
 
       !
@@ -191,7 +192,7 @@
          end do
       end do
       do i=1,domain % blocklist % mesh % nVerticesSolve
-         do j=1,3
+         do j=1,domain % blocklist % mesh % vertexDegree
             cellsOnVertex(j,i) = domain % blocklist % mesh % indexToCellID % array( &amp;
                                                                            domain % blocklist % mesh % cellsOnVertex % array(j,i))
             edgesOnVertex(j,i) = domain % blocklist % mesh % indexToEdgeID % array( &amp;

Modified: branches/ocean/src/module_time_integration.F
===================================================================
--- branches/ocean/src/module_time_integration.F        2010-02-02 23:59:45 UTC (rev 113)
+++ branches/ocean/src/module_time_integration.F        2010-02-05 23:51:55 UTC (rev 114)
@@ -4,6 +4,10 @@
    use configure
    use constants
    use dmpar
+   ! xsad 10-02-05:
+   use global_diagnostics
+   use vector_reconstruction
+   ! xsad 10-02-05 end
 
 
    contains
@@ -213,6 +217,12 @@
 
          call compute_solve_diagnostics(dt, block % time_levs(2) % state, block % mesh)
 
+         call reconstruct(block % time_levs(2) % state, block % mesh)
+
+         ! xsad 10-02-05:
+         call computeGlobalDiagnostics(domain % dminfo, block % time_levs(2) % state, block % mesh, dt)
+         ! xsad 10-02-05 end
+
          block =&gt; block % next
       end do
 
@@ -620,22 +630,20 @@
       ! Compute height at vertices, pv at vertices, and average pv to edge locations
       !  ( this computes pv_vertex at all vertices bounding real cells and distance-1 ghost cells )
       !
-      do iVertex = 1,nVertices
-         if (cellsOnVertex(1,iVertex) &gt; 0 .and. &amp;
-             cellsOnVertex(2,iVertex) &gt; 0 .and. &amp;
-             cellsOnVertex(3,iVertex) &gt; 0       &amp;
-            ) then
-            do k=1,nVertLevels
-               h_vertex = 0.0
-               do i=1,3
-                  h_vertex = h_vertex + h(k,cellsOnVertex(i,iVertex)) * kiteAreasOnVertex(i,iVertex)
-               end do
-               h_vertex = h_vertex / areaTriangle(iVertex)
-
-               pv_vertex(k,iVertex) = (fVertex(iVertex) + vorticity(k,iVertex)) / h_vertex
+      VTX_LOOP: do iVertex = 1,nVertices
+         do i=1,grid % vertexDegree
+            if (cellsOnVertex(i,iVertex) &lt;= 0) cycle VTX_LOOP
+         end do
+         do k=1,nVertLevels
+            h_vertex = 0.0
+            do i=1,grid % vertexDegree
+               h_vertex = h_vertex + h(k,cellsOnVertex(i,iVertex)) * kiteAreasOnVertex(i,iVertex)
             end do
-         end if
-      end do
+            h_vertex = h_vertex / areaTriangle(iVertex)
+   
+            pv_vertex(k,iVertex) = (fVertex(iVertex) + vorticity(k,iVertex)) / h_vertex
+         end do
+      end do VTX_LOOP
       ! tdr
 
 
@@ -658,7 +666,7 @@
       !
       pv_edge(:,:) = 0.0
       do iVertex = 1,nVertices
-        do i=1,3
+        do i=1,grid % vertexDegree
           iEdge = edgesOnVertex(i,iVertex)
           if(iEdge &gt; 0) then
             do k=1,nVertLevels
@@ -687,7 +695,7 @@
       !
       pv_cell(:,:) = 0.0
       do iVertex = 1, nVertices
-       do i=1,3
+       do i=1,grid % vertexDegree
          iCell = cellsOnVertex(i,iVertex)
          if( iCell &gt; 0) then
            do k = 1,nVertLevels
@@ -786,5 +794,4 @@
 
    end subroutine enforce_uBC
 
-
 end module time_integration

Added: branches/ocean/src/module_vector_reconstruction.F
===================================================================
--- branches/ocean/src/module_vector_reconstruction.F                                (rev 0)
+++ branches/ocean/src/module_vector_reconstruction.F        2010-02-05 23:51:55 UTC (rev 114)
@@ -0,0 +1,384 @@
+   module vector_reconstruction
+
+   use grid_types
+   use configure
+   use constants
+
+   implicit none
+
+   public :: init_reconstruct, reconstruct
+
+   contains
+
+   subroutine init_reconstruct(grid)
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
+   ! Purpose: reconstruct vector field at cell centers based on radial basis functions 
+   !
+   ! Input: grid meta data and vector component data residing at cell edges
+   !
+   ! Output: reconstructed vector field (measured in X,Y,Z) located at cell centers
+   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
+
+      implicit none
+
+      type (grid_meta), intent(inout) :: grid 
+
+      ! temporary arrays needed in the (to be constructed) init procedure
+      integer :: nCells, nEdges, nVertLevels, nCellsSolve
+      integer, dimension(:,:), pointer :: cellsOnCell, edgesOnCell, cellsOnEdge
+      integer, dimension(:), pointer :: nEdgesOnCell
+      integer :: iEdge, iCell, k, cell1, cell2, EdgeMax, j, i, npoints
+      integer :: lwork, info
+      integer, allocatable, dimension(:) :: ipvt
+      real (kind=RKIND), allocatable, dimension(:) :: work
+      real (kind=RKIND), dimension(:), pointer :: dcEdge, xCell, yCell, zCell
+      real (kind=RKIND) :: r, t, v, X1(3), X2(3), alpha
+      real (kind=RKIND), allocatable, dimension(:,:,:) :: xLoc
+
+      real (kind=RKIND), dimension(:,:,:), pointer :: matrix_reconstruct
+      real (kind=RKIND), dimension(:,:,:), pointer :: normal
+      real (kind=RKIND), dimension(:,:), pointer :: rbf_value
+      real (kind=RKIND), dimension(:,:,:), pointer :: coeffs_reconstruct
+      real (kind=RKIND), allocatable, dimension(:,:) :: mwork
+
+      !========================================================
+      ! arrays filled and saved during init procedure
+      !========================================================
+      matrix_reconstruct =&gt; grid % matrix_reconstruct % array
+      normal =&gt; grid % normal % array
+      rbf_value =&gt; grid % rbf_value % array
+      coeffs_reconstruct =&gt; grid % coeffs_reconstruct % array
+
+      !========================================================
+      ! temporary variables needed for init procedure
+      !========================================================
+      xCell       =&gt; grid % xCell % array
+      yCell       =&gt; grid % yCell % array
+      zCell       =&gt; grid % zCell % array
+      cellsOnCell =&gt; grid % cellsOnCell % array
+      cellsOnEdge =&gt; grid % cellsOnEdge % array
+      edgesOnCell =&gt; grid % edgesOnCell % array
+      nEdgesOnCell=&gt; grid % nEdgesOnCell % array
+      dcEdge      =&gt; grid % dcEdge % array
+      nCells      = grid % nCells
+      nCellsSolve = grid % nCellsSolve
+      nEdges      = grid % nEdges
+      nVertLevels = grid % nVertLevels
+
+      ! allocate arrays
+      EdgeMax = maxval(nEdgesOnCell)
+      allocate(xLoc(3,EdgeMax,nCells))
+      allocate(work(EdgeMax*EdgeMax))
+      allocate(ipvt(EdgeMax))
+       
+       ! init arrays
+       matrix_reconstruct = 0.0
+       normal = 0.0
+       rbf_value = 0.0
+
+       ! loop over all cells to be solved on this block
+       do iCell=1,nCellsSolve
+
+         npoints = nEdgesOnCell(iCell)   ! only loop over the number of edges for this cell
+
+         ! fill normal vector and xLoc arrays
+         ! X1 is the location of the reconstruction, X2 are the neighboring centers, xLoc is the edge positions
+         cell1 = iCell
+         X1(1) = xCell(cell1)
+         X1(2) = yCell(cell1)
+         X1(3) = zCell(cell1)
+         do j=1,npoints
+           cell2 = cellsOnCell(j,iCell)
+           iEdge = edgesOnCell(j,iCell)
+           X2(1) = xCell(cell2)
+           X2(2) = yCell(cell2)
+           X2(3) = zCell(cell2)
+           if(cell2.gt.cell1) then
+               normal(:,j,iCell) = X2(:) - X1(:)
+           else
+               normal(:,j,iCell) = X1(:) - X2(:)
+           endif
+           call unit_vector_in_R3(normal(:,j,iCell))
+           xLoc(:,j,iCell) = 0.5*(X2(:) + X1(:))
+         enddo
+
+         alpha = 0.0
+         do i=1,npoints
+           call get_distance(xLoc(:,i,iCell),X1(:),r)
+           alpha = alpha + r
+         enddo
+         alpha = 4*alpha / npoints
+         do j=1,npoints
+           do i=1,npoints
+              call get_distance(xLoc(:,i,iCell),xLoc(:,j,iCell),r)
+              r = r / alpha
+              call evaluate_rbf(r,t)
+              call get_dotproduct(normal(:,i,iCell),normal(:,j,iCell),v)
+              matrix_reconstruct(i,j,iCell) = v*t
+           enddo
+         enddo

+         ! save value of RBF when evaluated between reconstruction location and edge locations
+         do j=1,npoints
+           call get_distance(xLoc(:,j,iCell), X1(:), r)
+           r = r / alpha
+           call evaluate_rbf(r,t)
+           rbf_value(j,iCell) = t
+         enddo
+
+         ! invert matrix_reconstruct using lapack routines
+         allocate(mwork(npoints,npoints))
+         lwork = npoints*npoints
+         mwork(:,:) = matrix_reconstruct(1:npoints,1:npoints,iCell)
+         call dgetrf(npoints, npoints, mwork, npoints, ipvt, info)
+         if(info.ne.0) then
+          write(6,*) info, 'dgetrf'
+          stop
+         endif
+         call dgetri(npoints, mwork, npoints, ipvt, work, lwork, info)
+         matrix_reconstruct(1:npoints,1:npoints,iCell) = mwork(:,:)
+         if(info.ne.0) then
+          write(6,*) info, 'dgetri'
+          stop
+         endif
+          deallocate(mwork)
+
+         ! compute the coefficients for reconstructing uX, uY, uZ at cell centers from u_i normal to edges
+         ! uX = sum_j(coeffs(1,j) * u_j) (similarly for Y,Z)
+         ! coeffs(:,j) = sum_i(rbf_values(i) * normal(:,i) * matrix(i,j))
+         do j=1,npoints
+           coeffs_reconstruct(:,j,iCell) = 0.0
+           do i=1,npoints
+              coeffs_reconstruct(:,j,iCell) = coeffs_reconstruct(:,j,iCell) + rbf_value(i,iCell) * normal(:,i,iCell) &amp;
+                * matrix_reconstruct(i,j,iCell)
+           enddo
+         enddo
+
+      enddo   ! iCell
+
+      deallocate(ipvt)
+      deallocate(work)
+      deallocate(xLoc)
+
+      end subroutine init_reconstruct
+
+
+      subroutine reconstruct(s, grid)
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+      ! Purpose: reconstruct vector field at cell centers based on radial basis functions
+      !
+      ! Input: grid meta data and vector component data residing at cell edges
+      !
+      ! Output: reconstructed vector field (measured in X,Y,Z) located at cell centers
+      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+      implicit none
+
+      type (grid_state), intent(inout) :: s 
+      type (grid_meta), intent(in) :: grid
+
+      !   temporary arrays needed in the compute procedure
+      integer :: nCells, nEdges, nVertLevels, nCellsSolve
+      integer, dimension(:,:), pointer :: edgesOnCell
+      integer, dimension(:), pointer :: nEdgesOnCell
+      real (kind=RKIND), dimension(:), pointer :: xCell, yCell, zCell
+      integer :: iCell,iEdge, i, j, k, npoints, EdgeMax
+      real (kind=RKIND) :: r, t, p!, t1(3), t2(3), t3(3), east(3)
+      real (kind=RKIND), dimension(:,:), pointer :: u
+      real (kind=RKIND), dimension(:,:), pointer :: uReconstructX, uReconstructY, uReconstructZ
+      real (kind=RKIND), allocatable, dimension(:,:) :: rhs, c
+
+      real (kind=RKIND), dimension(:,:,:), pointer :: matrix_reconstruct
+      real (kind=RKIND), dimension(:,:,:), pointer :: normal
+      real (kind=RKIND), dimension(:,:), pointer :: rbf_value
+      real (kind=RKIND), dimension(:,:,:), pointer :: coeffs_reconstruct
+
+      ! stored arrays used during compute procedure
+      matrix_reconstruct =&gt; grid % matrix_reconstruct % array
+      normal =&gt; grid % normal % array
+      rbf_value =&gt; grid % rbf_value % array
+      coeffs_reconstruct =&gt; grid % coeffs_reconstruct % array
+
+      ! temporary variables
+      edgesOnCell =&gt; grid % edgesOnCell % array
+      nEdgesOnCell=&gt; grid % nEdgesOnCell % array
+      nCells      = grid % nCells
+      nCellsSolve = grid % nCellsSolve
+      nEdges      = grid % nEdges
+      nVertLevels = grid % nVertLevels
+      xCell =&gt; grid % xCell % array
+      yCell =&gt; grid % yCell % array
+      zCell =&gt; grid % zCell % array
+
+      u =&gt; s % u % array
+      uReconstructX =&gt; s % uReconstructX % array
+      uReconstructY =&gt; s % uReconstructY % array
+      uReconstructZ =&gt; s % uReconstructZ % array
+
+      ! allocate space for temporary arrays
+      EdgeMax = maxval(nEdgesOnCell)
+      allocate(c(nVertLevels,EdgeMax))
+      allocate(rhs(nVertLevels,EdgeMax))
+
+      ! init the intent(out)
+      uReconstructX = 0.0
+      uReconstructY = 0.0
+      uReconstructZ = 0.0
+
+      ! loop over cell centers
+      do iCell=1,nCellsSolve
+
+!        t2(1) = xCell(iCell)
+!        t2(2) = yCell(iCell)
+!        t2(3) = zCell(iCell)
+!        t3(1) = 0
+!        t3(2) = 0
+!        t3(3) = 1.0
+!        call cross_product_in_R3(t3(:), t2(:), east(:))
+!        call unit_vector_in_R3(east(:))
+
+        npoints = nEdgesOnCell(iCell)
+
+        ! fill the RHS of the matrix equation
+        ! for testing purposes, fill rhs with test function
+        ! test function assumes uniform flow to the east
+        rhs = 0.0
+        do j=1,npoints
+          iEdge = edgesOnCell(j,iCell)
+          do k=1,nVertLevels
+            rhs(k,j) = u(k,iEdge)
+            ! call get_dotproduct(normal(:,j,iCell),east(:),rhs(k,j))
+          enddo
+        enddo
+  
+        ! compute c by multiplying matrix_reconstruct * rhs  (Eq 8 in Tex document)
+        c = 0.0
+        do i=1,npoints
+         do j=1,npoints
+           do k=1,nVertLevels
+             c(k,i) = c(k,i) + matrix_reconstruct(i,j,iCell)*rhs(k,j)
+           enddo
+         enddo
+        enddo
+  
+        ! reconstruct the velocity field at point X1 (Eq 6 in Tex document)
+!        do i=1,npoints
+!          do k=1,nVertLevels
+!            uReconstructX(k,iCell) = uReconstructX(k,iCell) + c(k,i)*rbf_value(i,iCell)*normal(1,i,iCell)
+!            uReconstructY(k,iCell) = uReconstructY(k,iCell) + c(k,i)*rbf_value(i,iCell)*normal(2,i,iCell)
+!            uReconstructZ(k,iCell) = uReconstructZ(k,iCell) + c(k,i)*rbf_value(i,iCell)*normal(3,i,iCell)
+!          enddo
+!        enddo
+!
+!        t1(1) = uReconstructX(1,iCell)
+!        t1(2) = uReconstructY(1,iCell)
+!        t1(3) = uReconstructZ(1,iCell)
+!        call get_dotproduct(east, t1, p)
+!        write(6,10) iCell, p
+!        write(6,10) iCell, t1(:)
+!        write(6,10) iCell, east(:)
+!        write(6,*)
+! 10     format(i6, 3e15.5)
+
+        ! reconstruct the velocity field at point X1 (Eq 6 in Tex document)
+!        uReconstructX(:,iCell) = 0.0
+!        uReconstructY(:,iCell) = 0.0
+!        uReconstructZ(:,iCell) = 0.0
+        do i=1,npoints
+          uReconstructX(:,iCell) = uReconstructX(:,iCell) + coeffs_reconstruct(1,i,iCell) * rhs(:,i)
+          uReconstructY(:,iCell) = uReconstructY(:,iCell) + coeffs_reconstruct(2,i,iCell) * rhs(:,i)
+          uReconstructZ(:,iCell) = uReconstructZ(:,iCell) + coeffs_reconstruct(3,i,iCell) * rhs(:,i)
+        enddo
+
+!        t1(1) = uReconstructX(1,iCell)
+!        t1(2) = uReconstructY(1,iCell)
+!        t1(3) = uReconstructZ(1,iCell)
+!        call get_dotproduct(east, t1, p)
+!        write(6,10) iCell, p
+!        write(6,10) iCell, t1(:)
+!        write(6,10) iCell, east(:)
+!        write(6,*)
+
+        
+      enddo   ! iCell
+
+      ! deallocate
+      deallocate(rhs)
+      deallocate(c)

+!      stop
+
+   end subroutine reconstruct
+
+   subroutine get_distance(x1,x2,xout)
+     implicit none
+     real(kind=RKIND), intent(in) :: x1(3), x2(3)
+     real(kind=RKIND), intent(out) :: xout
+     xout = sqrt( (x1(1)-x2(1))**2 + (x1(2)-x2(2))**2 + (x1(3)-x2(3))**2 )
+   end subroutine get_distance

+   subroutine get_dotproduct(x1,x2,xout)
+     implicit none
+     real(kind=RKIND), intent(in) :: x1(3), x2(3)
+     real(kind=RKIND), intent(out) :: xout
+     xout = x1(1)*x2(1) + x1(2)*x2(2) + x1(3)*x2(3)
+   end subroutine get_dotproduct


+   subroutine unit_vector_in_R3(xin)
+     implicit none
+     real (kind=RKIND), intent(inout) :: xin(3)
+     real (kind=RKIND) :: mag
+     mag = sqrt(xin(1)**2+xin(2)**2+xin(3)**2)
+     xin(:) = xin(:) / mag
+   end subroutine unit_vector_in_R3
+
+
+   subroutine evaluate_rbf(r,xout)
+     real(kind=RKIND), intent(in) ::  r
+     real(kind=RKIND), intent(out) :: xout
+
+     ! Gaussian
+       xout = exp(-r**2)
+
+     ! multiquadrics
+     ! xout = 1.0 / sqrt(1.0**2 + r**2)
+
+     ! other
+     ! xout = 1.0 / (1.0**2 + r**2)
+
+   end subroutine evaluate_rbf
+
+!======================================================================
+! BEGINNING OF CROSS_PRODUCT_IN_R3
+!======================================================================
+        subroutine cross_product_in_R3(p_1,p_2,p_out)
+
+!-----------------------------------------------------------------------
+! PURPOSE: compute p_1 cross p_2 and place in p_out
+!-----------------------------------------------------------------------
+
+!-----------------------------------------------------------------------
+! intent(in)
+!-----------------------------------------------------------------------
+        real (kind=RKIND), intent(in) ::                            &amp;
+                        p_1 (3),                                      &amp;
+                        p_2 (3)
+
+!-----------------------------------------------------------------------
+! intent(out)
+!-----------------------------------------------------------------------
+        real (kind=RKIND), intent(out) ::                           &amp;
+                        p_out (3)
+
+        p_out(1) = p_1(2)*p_2(3)-p_1(3)*p_2(2)
+        p_out(2) = p_1(3)*p_2(1)-p_1(1)*p_2(3)
+        p_out(3) = p_1(1)*p_2(2)-p_1(2)*p_2(1)
+
+        end subroutine cross_product_in_R3
+!======================================================================
+! END OF CROSS_PRODUCT_IN_R3
+!======================================================================
+
+
+end module vector_reconstruction

</font>
</pre>