<p><b>mhoffman@lanl.gov</b> 2013-02-28 12:12:01 -0700 (Thu, 28 Feb 2013)</p><p>BRANCH COMMIT - land ice<br>
<br>
Created a modified version of the ocean core's tool 'basin' to use on land ice meshes for removing non-ice cells.<br>
<br>
To use, first create a land ice mesh (e.g. with periodic_hex + add_land_ice_variables_to_mpas_grid.py) and then populate it with thickness data (e.g. with copy_CISM_grid_to_MPAS_grid.py).  Then run define_keepCellMask.py which will add a new field call keepCellMask to the file.  There are options in that script to add a buffer around the ice-covered portion of the domain.  Next compile and run crop_landice_grid.  This will return a cropped domain that is an empty grid, so the steps for converting it to a land ice grid and populating it with data will need to be repeated.  You will also want to run pmetis manually on the graph.info file that is generated.<br>
</p><hr noshade><pre><font color="gray">Added: branches/land_ice_projects/grid_tools/crop_landice_grid/Makefile
===================================================================
--- branches/land_ice_projects/grid_tools/crop_landice_grid/Makefile                                (rev 0)
+++ branches/land_ice_projects/grid_tools/crop_landice_grid/Makefile        2013-02-28 19:12:01 UTC (rev 2521)
@@ -0,0 +1,69 @@
+# IBM with Xlf compilers
+#FC = xlf90
+#CC = xlc
+#FFLAGS = -qrealsize=8 -g -C
+#CFLAGS = -g
+#LDFLAGS = -g -C
+
+# pgf90
+#FC = pgf90
+#CC = pgcc
+#FFLAGS = -r8 -O3
+#CFLAGS = -O3
+#LDFLAGS = -O3
+
+# ifort
+#FC = ifort
+#CC = icc
+#FFLAGS = -real-size 64 #-g -traceback -check all
+#CFLAGS = #-g
+#LDFLAGS = #-g -traceback -check all
+
+FC = gfortran
+CC = gcc
+FFLAGS = -O3 -m64 -ffree-line-length-none -fdefault-real-8 -fconvert=big-endian
+CFLAGS = -O3 -m64
+LDFLAGS = -O3 -m64
+
+# absoft
+#FC = f90
+#CC = gcc
+#FFLAGS = -dp -O3
+#CFLAGS = -O3
+#LDFLAGS = -O3
+#NETCDF = /Users/maltrud/local
+
+
+CPP = cpp -C -P -traditional
+CPPFLAGS = 
+CPPINCLUDES = 
+INCLUDES = -I$(NETCDF)/include
+LIBS = -L$(NETCDF)/lib -lnetcdf -lnetcdff
+
+RM = rm -f
+
+##########################
+
+.SUFFIXES: .F .o
+
+OBJS = utilities.o \
+       module_read_netcdf.o \
+       module_cullLoops.o \
+       module_write_netcdf.o \
+       crop_landice_grid.o 
+
+all: crop_landice_grid
+
+crop_landice_grid.o: utilities.o module_write_netcdf.o module_read_netcdf.o module_cullLoops.o
+
+crop_landice_grid: $(OBJS)
+        $(FC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
+
+clean:
+        $(RM) *.o *.mod pop *.f90
+
+.F.o:
+        $(RM) $@ $*.mod
+        $(CPP) $(CPPFLAGS) $(CPPINCLUDES) $&lt; &gt; $*.f90
+        $(FC) $(FFLAGS) -c $*.f90 $(INCLUDES)
+        #$(RM) $*.f90

Added: branches/land_ice_projects/grid_tools/crop_landice_grid/crop_landice_grid.F
===================================================================
--- branches/land_ice_projects/grid_tools/crop_landice_grid/crop_landice_grid.F                                (rev 0)
+++ branches/land_ice_projects/grid_tools/crop_landice_grid/crop_landice_grid.F        2013-02-28 19:12:01 UTC (rev 2521)
@@ -0,0 +1,1133 @@
+program crop_landice_grid
+
+use read_netcdf
+use write_netcdf
+use utilities
+use cullLoops
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! Program: crop_landice_grid.F
+!
+! This program culls cells from a mesh.  Presumably you will use it to remove non-ice cells.
+! You define what cells to keep with a 1 value in an integer field called keepCellMask that you must add to a grid file named land_ice_grid.nc.
+! It generates a culled version called land_ice_grid_culled.nc.
+!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+implicit none
+
+! original grid variables
+integer :: time, nCells, nEdges, nVertices
+integer :: maxEdges, maxEdges2, TWO, vertexDegree, nVertLevels
+integer, allocatable, dimension(:) :: indexToCellID, indexToEdgeID, indexToVertexID
+real, allocatable, dimension(:) :: xCell, yCell, zCell, latCell, lonCell, meshDensity
+real, allocatable, dimension(:) :: xEdge, yEdge, zEdge, latEdge, lonEdge
+real, allocatable, dimension(:) :: xVertex, yVertex, zVertex, latVertex, lonVertex
+integer, allocatable, dimension(:) :: nEdgesOnCell, nEdgesOnEdge
+integer, allocatable, dimension(:,:) :: cellsOnCell, edgesOnCell, verticesOnCell
+integer, allocatable, dimension(:,:) :: cellsOnEdge, verticesOnEdge, edgesOnEdge
+integer, allocatable, dimension(:,:) :: cellsOnVertex, edgesOnVertex
+real, allocatable, dimension(:) :: areaCell, areaTriangle, dcEdge, dvEdge, angleEdge
+real, allocatable, dimension(:,:) :: kiteAreasOnVertex, weightsOnEdge
+
+integer nlon, nlat, ndepth
+real(kind=4), allocatable, dimension(:) :: t_lon, t_lat
+
+real, dimension(40) :: dz
+
+   real (kind=8) :: ymid, ytmp, ymax, xmid, xloc, yloc, pert, ymin, distance, r, c1(3), c2(3)
+   real (kind=8) :: latmid, lattmp, latmax, latmin
+   integer :: cell1, cell2
+
+! new grid variables
+integer :: nCellsNew, nEdgesNew, nVerticesNew
+integer :: maxEdgesNew, maxEdges2New, TWONew, vertexDegreeNew, nVertLevelsNew
+integer, allocatable, dimension(:) :: indexToCellIDNew, indexToEdgeIDNew, indexToVertexIDNew
+real, allocatable, dimension(:) :: xCellNew, yCellNew, zCellNew, latCellNew, lonCellNew, meshDensityNew, meshSpacingNew
+real, allocatable, dimension(:) :: xEdgeNew, yEdgeNew, zEdgeNew, latEdgeNew, lonEdgeNew
+real, allocatable, dimension(:) :: xVertexNew, yVertexNew, zVertexNew, latVertexNew, lonVertexNew
+integer, allocatable, dimension(:) :: nEdgesOnCellNew, nEdgesOnEdgeNew, flipVerticesOnEdgeOrdering
+integer, allocatable, dimension(:,:) :: cellsOnCellNew, edgesOnCellNew, verticesOnCellNew
+integer, allocatable, dimension(:,:) :: cellsOnEdgeNew, verticesOnEdgeNew, edgesOnEdgeNew
+integer, allocatable, dimension(:,:) :: cellsOnVertexNew, edgesOnVertexNew
+integer, allocatable, dimension(:,:) :: boundaryEdgeNew, boundaryVertexNew
+real, allocatable, dimension(:) :: areaCellNew, areaTriangleNew, dcEdgeNew, dvEdgeNew, angleEdgeNew
+real, allocatable, dimension(:,:) :: kiteAreasOnVertexNew, weightsOnEdgeNew, normalsNew
+
+integer, allocatable, dimension(:) :: keepCellMask
+
+! mapping variables
+integer, allocatable, dimension(:) :: kmt
+integer, allocatable, dimension(:) :: cellMap, edgeMap, vertexMap
+
+! work variables
+integer :: i,j,jNew,k,jEdge,jEdgeNew,iVertex1New,iVertex2New,iCell1New,iCell2New
+integer :: iCell, iCell1, iCell2, iCell3, iEdge, iVertex, iVertex1, iVertex2
+integer :: iCellNew, iEdgeNew, iVertexNew, ndata, jCell1, jCell2, jCell, iter
+real :: xin, yin, zin, ulon, ulat, ux, uy, uz, rlon, rlat, temp_t, temp_s
+
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! Namelist variables
+!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+! Variables in namelist file
+character (len=32) :: on_a_sphere, zLevel_thickness,bottom_topography, initial_conditions
+logical :: expand_from_unit_sphere, eliminate_inland_seas, &amp;
+   check_mesh, &amp;
+   cut_domain_from_sphere, solid_boundary_in_y, solid_boundary_in_x
+
+integer :: nVertLevelsMOD
+real (kind=8) :: sphere_radius
+
+!! specify namelist
+!namelist /landicecrop/ on_a_sphere, sphere_radius, &amp;
+!   expand_from_unit_sphere, &amp;
+!   eliminate_inland_seas, check_mesh, &amp;
+!   cut_domain_from_sphere, solid_boundary_in_y, solid_boundary_in_x
+!!   Lx
+
+! Default namelist values.  Default set for realistic global IC.
+on_a_sphere = 'NO'
+sphere_radius = 6.37122e6
+expand_from_unit_sphere = .true.
+
+eliminate_inland_seas=.false.
+solid_boundary_in_y = .false.
+solid_boundary_in_x = .false.
+
+! This needs to be changed for correct periodic boundaries
+! Lx is the TOTAL domain width, and needs to be exact for correct periodic
+! boundaries in x.
+!Lx = 3200.0e3  ! 40x80km=3200km
+
+
+!! Read in namelist
+!   open(20,file='namelist.landicecrop',status='old')
+!   read(20,landicecrop)
+!   close(20)
+
+
+! get to work
+write(6,*) ' starting'
+write(6,*)
+
+! get grid
+write(6,*) ' calling read_grid'
+write(6,*)
+call read_grid
+write(6,*) ' xCell 1: ',minval(xCell), maxval(xCell)
+
+nVertLevelsMOD = nVertLevels
+
+! copy dimensions
+write(6,*) ' copy dimensions'
+write(6,*)
+call copy_dimensions
+write(6,*) ' xCell 1: ',minval(xCell), maxval(xCell)
+
+! define the kmt array
+write(6,*) ' calling define_kmt'
+write(6,*)
+call define_kmt
+
+! define the mapping between original and new cells, edges and vertices
+write(6,*) ' calling define_mapping'
+write(6,*)
+call define_mapping
+
+! copy the vector arrays form the original to new arrays
+write(6,*) ' calling map_vectors'
+write(6,*)
+call map_vectors
+
+! define the new connectivity variables
+write(6,*) ' calling map_connectivity'
+write(6,*)
+call map_connectivity
+
+! check the mesh
+if (check_mesh) then
+   call error_checking
+endif
+
+! dump new grid to netCDF
+write(6,*) ' calling write_grid'
+write(6,*)
+call write_grid
+
+! dump graph for partioning
+write(6,*) ' call write_graph'
+write(6,*)
+call write_graph
+
+!! write OpenDx file
+!if (write_OpenDX_flag) then
+!   write(6,*) ' calling write_OpenDX'
+!   write(6,*)
+!   call write_OpenDX(        on_a_sphere, &amp;
+!                             nCellsNew, &amp;
+!                             nVerticesNew, &amp;
+!                             nEdgesNew, &amp;
+!                             vertexDegreeNew, &amp;
+!                             maxEdgesNew, &amp;
+!                             xCellNew, &amp;
+!                             yCellNew, &amp;
+!                             zCellNew, &amp;
+!                             xVertexNew, &amp;
+!                             yVertexNew, &amp;
+!                             zVertexNew, &amp;
+!                             xEdgeNew, &amp;
+!                             yEdgeNew, &amp;
+!                             zEdgeNew, &amp;
+!                             nEdgesOnCellNew, &amp;
+!                             verticesOnCellNew, &amp;
+!                             verticesOnEdgeNew, &amp;
+!                             cellsOnVertexNew, &amp;
+!                             edgesOnCellNew, &amp;
+!                             areaCellNew, &amp;
+!                             maxLevelCellNew, &amp;
+!                             meshDensityNew, &amp;
+!                             bottomDepthNew, &amp;
+!                             temperatureNew(1,1,:), &amp;
+!                             kiteAreasOnVertexNew )
+!endif
+
+!!do iCell=1,nCellsNew
+!  !ulon = 1.0; ulat = 0.0
+!  !xin = xCellNew(iCell); yin = yCellNew(iCell); zin = zCellNew(iCell)
+!  !call transform_from_lonlat_to_xyz(xin, yin, zin, ulon, ulat, ux, uy, uz)
+!  !if(abs(ux).lt.1.0e-10) ux=0.0
+!  !if(abs(uy).lt.1.0e-10) uy=0.0
+!  !if(abs(uz).lt.1.0e-10) uz=0.0
+!  !write(20,10) ux, uy, uz
+!  !10 format(3e25.10)
+!!enddo
+  
+write(6,*) ' finished'
+
+contains
+
+subroutine write_graph
+implicit none
+integer :: m,itmp(maxEdgesNew),k
+
+      m=nEdgesNew
+      do i=1,nCellsNew
+      do j=1,nEdgesOnCellNew(i)
+         if(cellsOnCellNew(j,i).eq.0) m=m-1
+      enddo
+      enddo
+
+      open(42,file='graph.info',form='formatted')
+      write(42,*) nCellsNew, m
+      do i=1,nCellsNew
+         itmp = 0; k = 0;
+         do j=1,nEdgesOnCellNew(i)
+            if(cellsOnCellNew(j,i).gt.0) then
+              k=k+1; itmp(k)=cellsOnCellNew(j,i)
+            endif
+         enddo
+         write(42,'(1x,12i8)',advance='no') (itmp(m),m=1,k)
+         write(42,'(1x)')
+      end do
+      close(42)
+end subroutine write_graph
+
+
+subroutine error_checking
+real :: p(3), q(3), r(3), angle, s(3), t(3), dot, mindot, maxdot, b(vertexDegree)
+real :: work(nCellsNew)
+
+
+! write
+write(6,*)
+write(6,*) ' error checking '
+write(6,*)
+
+! check to see if every edge is normal to associated cells
+mindot =  2
+maxdot = -2
+do iEdge=1,nEdgesNew
+  if(boundaryEdgeNew(1,iEdge).eq.1) cycle
+  iCell1 = cellsOnEdgeNew(1,iEdge)
+  iCell2 = cellsOnEdgeNew(2,iEdge)
+  p(1)=xCellNew(iCell1); p(2)=yCellNew(iCell1); p(3)=zCellNew(iCell1)
+  q(1)=xCellNew(iCell2); q(2)=yCellNew(iCell2); q(3)=zCellNew(iCell2)
+  r(1)=xEdgeNew(iEdge);  r(2)=yEdgeNew(iEdge);  r(3)=zEdgeNew(iEdge)
+  call unit_vector_in_3space(p)
+  call unit_vector_in_3space(q)
+  call unit_vector_in_3space(r)
+  t = q - p
+  s = r - p
+  call unit_vector_in_3space(t)
+  call unit_vector_in_3space(s)
+  dot = s(1)*t(1)+s(2)*t(2)+s(3)*t(3)
+  if(dot.lt.mindot) mindot=dot
+  if(dot.gt.maxdot) maxdot=dot
+enddo
+write(6,10) 'alignment of edges and cells (should be ones)', mindot, maxdot
+10 format(a60,5x,2e15.5)
+
+! check to see if every segments connecting cells and vertices are orothogonal'
+mindot =  2
+maxdot = -2
+do iEdge=1,nEdgesNew
+  if(boundaryEdgeNew(1,iEdge).eq.1) cycle
+  iCell1 = cellsOnEdgeNew(1,iEdge)
+  iCell2 = cellsOnEdgeNew(2,iEdge)
+  iVertex1 = verticesOnEdgeNew(1,iEdge)
+  iVertex2 = verticesOnEdgeNew(2,iEdge)
+  p(1)=xCellNew(iCell1); p(2)=yCellNew(iCell1); p(3)=zCellNew(iCell1)
+  q(1)=xCellNew(iCell2); q(2)=yCellNew(iCell2); q(3)=zCellNew(iCell2)
+  r(1)=xVertexNew(iVertex1); r(2)=yVertexNew(iVertex1); r(3)=zVertexNew(iVertex1)
+  s(1)=xVertexNew(iVertex2); s(2)=yVertexNew(iVertex2); s(3)=zVertexNew(iVertex2)
+  call unit_vector_in_3space(p)
+  call unit_vector_in_3space(q)
+  call unit_vector_in_3space(r)
+  call unit_vector_in_3space(s)
+  t = q - p
+  s = s - r
+  call unit_vector_in_3space(t)
+  call unit_vector_in_3space(s)
+  dot = s(1)*t(1)+s(2)*t(2)+s(3)*t(3)
+  if(dot.lt.mindot) mindot=dot
+  if(dot.gt.maxdot) maxdot=dot
+enddo
+write(6,10) 'orthogonality of cell and vertex edges (should be zeros)', mindot, maxdot
+
+! check that the kiteareas sum to the areatriangle
+mindot =  2
+maxdot = -2
+do iVertex=1,nVerticesNew
+  b = 0
+  do i=1,vertexDegree
+    b(i) = kiteAreasOnVertexNew(i,iVertex)
+  enddo
+  angle = sum(b)
+  if(angle - areaTriangleNew(iVertex).lt.mindot) mindot = angle - areaTriangleNew(iVertex)
+  if(angle - areaTriangleNew(iVertex).gt.maxdot) maxdot = angle - areaTriangleNew(iVertex)
+enddo
+write(6,10) ' error in sum of kites and triangles (should be zeroes)', mindot, maxdot
+
+! check that the kiteareas sum to the areaCell
+mindot =  2
+maxdot = -2
+work = 0
+do iVertex=1,nVerticesNew
+  iCell1 = cellsOnVertexNew(1,iVertex)
+  iCell2 = cellsOnVertexNew(2,iVertex)
+  iCell3 = cellsOnVertexNew(3,iVertex)
+  if(iCell1.ne.0) work(iCell1) = work(iCell1) + kiteAreasOnVertexNew(1,iVertex)
+  if(iCell2.ne.0) work(iCell2) = work(iCell2) + kiteAreasOnVertexNew(2,iVertex)
+  if(iCell3.ne.0) work(iCell3) = work(iCell3) + kiteAreasOnVertexNew(3,iVertex)
+enddo
+mindot = minval(areaCellNew - work)
+maxdot = maxval(areaCellNew - work)
+write(6,10) ' error in sum of kites and cells (should be zeroes)', mindot, maxdot
+
+!check for connectivity inverses for cells/edges
+do iCell=1,nCellsNew
+  do i=1,nEdgesOnCellNew(iCell)
+    iEdge=edgesOnCellNew(i,iCell)
+    if(iEdge.le.0) stop ' iEdge le 0'
+    iCell1 = cellsOnEdgeNew(1,iEdge)
+    iCell2 = cellsOnEdgeNew(2,iEdge)
+    if(iCell1.ne.iCell.and.iCell2.ne.iCell) stop ' cells/edges inverse failed'
+  enddo
+enddo
+write(6,*) ' cellsOnEdge and edgesOnCell are duals for every cell/edge combination'
+
+!check for connectivity inverses for cells/vertices
+do iCell=1,nCellsNew
+  do i=1,nEdgesOnCellNew(iCell)
+    iVertex = verticesOnCellNew(i,iCell)
+    if(iVertex.le.0) stop ' iVertex le 0'
+    iCell1 = cellsOnVertexNew(1,iVertex)
+    iCell2 = cellsOnVertexNew(2,iVertex)
+    iCell3 = cellsOnVertexNew(3,iVertex)
+    if(iCell1.ne.iCell.and.iCell2.ne.iCell.and.iCell3.ne.iCell) stop ' cells/vertices inverse failed'
+  enddo
+enddo
+write(6,*) ' cellsOnVertex and verticesOnCell are duals for every cell/vertex combination'
+
+!check edgesOnEdge
+do iEdge=1,nEdgesNew
+  iCell1 = cellsOnEdgeNew(1,iEdge)
+  iCell2 = cellsOnEdgeNew(2,iEdge)
+  if(nEdgesOnEdgeNew(iEdge).eq.0) then
+    if(boundaryEdgeNew(1,iEdge).ne.1) stop ' stopping boundaryEdgeNew'
+  endif
+  do i=1,nEdgesOnEdgeNew(iEdge)
+    jEdge = edgesOnEdgeNew(i,iEdge)
+    jCell1 = cellsOnEdgeNew(1,jEdge)
+    jCell2 = cellsOnEdgeNew(2,jEdge)
+    if(jCell1.ne.iCell1.and.jCell1.ne.iCell2) then
+    if(jCell2.ne.iCell1.and.jCell2.ne.iCell2) then
+          write(6,*) 'error in edgesOnEdge'
+          write(6,*) iCell1, iCell2, jCell1, jCell2
+          stop
+    endif
+    endif
+  enddo
+enddo
+write(6,*) ' edgesOnEdge is consistent with cellsOnEdge'
+
+end subroutine error_checking
+
+
+subroutine copy_dimensions
+
+maxEdgesNew = maxEdges
+maxEdges2New = maxEdges2
+TWONew = TWO
+vertexDegreeNew = vertexDegree
+nVertLevelsNew = nVertLevelsMod
+
+write(6,*)
+write(6,*) ' new dimensions '
+write(6,*) ' maxEdgesNew     : ', maxEdgesNew
+write(6,*) ' maxEdges2New    : ', maxEdges2New
+write(6,*) ' TWONew          : ', TWONew
+write(6,*) ' vertexDegreeNew : ', vertexDegreeNew
+write(6,*) ' nVertLevelsNew  : ', nVertLevelsNew
+
+end subroutine copy_dimensions
+
+
+
+subroutine read_grid
+implicit none
+
+call read_netcdf_init(nCells, nEdges, nVertices, maxEdges,maxEdges2,&amp;
+                       nVertLevels,TWO,vertexDegree)
+
+write(6,*) ' init from grid '
+write(6,*) 'nCells        :', nCells
+write(6,*) 'nEdges        :', nEdges
+write(6,*) 'nVertices     :', nVertices
+write(6,*) 'maxEdges      :', maxEdges
+write(6,*) 'maxEdges2     :', maxEdges2
+write(6,*) 'nVertLevels   :', nVertLevels
+write(6,*) 'vertexDegree  :', vertexDegree
+write(6,*) 'TWO           :', TWO
+
+allocate(xCell(nCells))
+allocate(yCell(nCells))
+allocate(zCell(nCells))
+allocate(latCell(nCells))
+allocate(lonCell(nCells))
+allocate(meshDensity(nCells))
+allocate(xEdge(nEdges))
+allocate(yEdge(nEdges))
+allocate(zEdge(nEdges))
+allocate(latEdge(nEdges))
+allocate(lonEdge(nEdges))
+allocate(xVertex(nVertices))
+allocate(yVertex(nVertices))
+allocate(zVertex(nVertices))
+allocate(latVertex(nVertices))
+allocate(lonVertex(nVertices))
+allocate(dcEdge(nEdges))
+allocate(dvEdge(nEdges))
+
+allocate(indexToCellID(nCells))
+allocate(indexToEdgeID(nEdges))
+allocate(indexToVertexID(nVertices))
+
+allocate(cellsOnEdge(TWO,nEdges))
+allocate(nEdgesOnCell(nCells))
+allocate(nEdgesOnEdge(nEdges))
+allocate(edgesOnCell(maxEdges,nCells))
+allocate(edgesOnEdge(maxEdges2,nEdges))
+allocate(weightsOnEdge(maxEdges2,nEdges))
+
+allocate(angleEdge(nEdges))
+allocate(areaCell(nCells))
+allocate(areaTriangle(nVertices))
+allocate(cellsOnCell(maxEdges,nCells))
+allocate(verticesOnCell(maxEdges,nCells))
+allocate(verticesOnEdge(TWO,nEdges))
+allocate(edgesOnVertex(vertexDegree,nVertices))
+allocate(cellsOnVertex(vertexDegree,nVertices))
+allocate(kiteAreasOnVertex(vertexDegree,nVertices))
+
+allocate(keepCellMask(nCells))
+
+
+xCell=0; yCell=0; zCell=0; latCell=0; lonCell=0; meshDensity=1.0
+xEdge=0; yEdge=0; zEdge=0; latEdge=0; lonEdge=0
+xVertex=0; yVertex=0; zVertex=0; latVertex=0; lonVertex=0
+
+indexToCellID=0; indexToEdgeID=0; indexToVertexID=0
+cellsOnEdge=0; nEdgesOnCell=0; edgesOnCell=0
+edgesOnEdge=0; weightsOnEdge=0
+angleEdge=0; areaCell=0; areaTriangle=0
+cellsOnCell=0; verticesOnCell=0; verticesOnEdge=0
+edgesOnVertex=0; cellsOnVertex=0; kiteAreasOnVertex=0
+
+
+call  read_netcdf_fields( &amp;
+                    time, &amp;
+                    latCell, &amp;
+                    lonCell, &amp;
+                    meshDensity, &amp;
+                    xCell, &amp;
+                    yCell, &amp;
+                    zCell, &amp;
+                    indexToCellID, &amp;
+                    latEdge, &amp;
+                    lonEdge, &amp;
+                    xEdge, &amp;
+                    yEdge, &amp;
+                    zEdge, &amp;
+                    indexToEdgeID, &amp;
+                    latVertex, &amp;
+                    lonVertex, &amp;
+                    xVertex, &amp;
+                    yVertex, &amp;
+                    zVertex, &amp;
+                    indexToVertexID, &amp;
+                    cellsOnEdge, &amp;
+                    nEdgesOnCell, &amp;
+                    nEdgesOnEdge, &amp;
+                    edgesOnCell, &amp;
+                    edgesOnEdge, &amp;
+                    weightsOnEdge, &amp;
+                    dvEdge, &amp;
+                    dcEdge, &amp;
+                    angleEdge, &amp;
+                    areaCell, &amp;
+                    areaTriangle, &amp;
+                    cellsOnCell, &amp;
+                    verticesOnCell, &amp;
+                    verticesOnEdge, &amp;
+                    edgesOnVertex, &amp;
+                    cellsOnVertex, &amp;
+                    kiteAreasOnVertex, &amp;
+                    keepCellMask &amp;
+                   )
+
+write(6,*) ' values from read grid, min/max'
+write(6,*) ' latCell : ', minval(latCell), maxval(latCell)
+write(6,*) ' lonCell : ', minval(lonCell), maxval(lonCell)
+write(6,*) ' meshDensity : ', minval(meshDensity),maxval(meshDensity)
+write(6,*) ' xCell : ', minval(xCell), maxval(xCell)
+write(6,*) ' yCell : ', minval(yCell), maxval(yCell)
+write(6,*) ' zCell : ', minval(zCell), maxval(zCell)
+write(6,*) ' indexToCellID : ', minval(indexToCellID), maxval(indexToCellID)
+write(6,*) ' latEdge : ', minval(latEdge), maxval(latEdge)
+write(6,*) ' lonEdge : ', minval(lonEdge), maxval(lonEdge)
+write(6,*) ' xEdge : ', minval(xEdge), maxval(xEdge)
+write(6,*) ' yEdge : ', minval(yEdge), maxval(yEdge)
+write(6,*) ' zEdge : ', minval(zEdge), maxval(zEdge)
+write(6,*) ' indexToEdgeID : ', minval(indexToEdgeID), maxval(indexToEdgeID)
+write(6,*) ' latVertex : ', minval(latVertex), maxval(latVertex)
+write(6,*) ' lonVertex : ', minval(lonVertex), maxval(lonVertex)
+write(6,*) ' xVertex : ', minval(xVertex), maxval(xVertex)
+write(6,*) ' yVertex : ', minval(yVertex), maxval(yVertex)
+write(6,*) ' zVertex : ', minval(zVertex), maxval(zVertex)
+write(6,*) ' indexToVertexID : ', minval(indexToVertexID), maxval(indexToVertexID)
+write(6,*) ' cellsOnEdge : ', minval(cellsOnEdge), maxval(cellsOnEdge)
+write(6,*) ' nEdgesOnCell : ', minval(nEdgesOnCell), maxval(nEdgesOnCell)
+write(6,*) ' nEdgesOnEdge : ', minval(nEdgesOnEdge), maxval(nEdgesOnEdge)
+write(6,*) ' edgesOnCell : ', minval(edgesOnCell), maxval(edgesOnCell)
+write(6,*) ' edgesOnEdge : ', minval(edgesOnEdge), maxval(edgesOnEdge)
+write(6,*) ' weightsOnEdge : ', minval(weightsOnEdge), maxval(weightsOnEdge)
+write(6,*) ' dvEdge : ', minval(dvEdge), maxval(dvEdge)
+write(6,*) ' dcEdge : ', minval(dcEdge), maxval(dcEdge)
+write(6,*) ' angleEdge : ', minval(angleEdge), maxval(angleEdge)
+write(6,*) ' areaCell : ', minval(areaCell), maxval(areaCell)
+write(6,*) ' areaTriangle : ', minval(areaTriangle), maxval(areaTriangle)
+write(6,*) ' cellsOnCell : ', minval(cellsOnCell), maxval(cellsOnCell)
+write(6,*) ' verticesOnCell : ', minval(verticesOnCell), maxval(verticesOnCell)
+write(6,*) ' verticesOnEdge : ', minval(verticesOnEdge), maxval(verticesOnEdge)
+write(6,*) ' edgesOnVertex : ', minval(edgesOnVertex), maxval(edgesOnVertex)
+write(6,*) ' cellsOnVertex : ', minval(cellsOnVertex), maxval(cellsOnVertex)
+write(6,*) ' kiteAreasOnVertex : ', minval(kiteAreasOnVertex), maxval(kiteAreasOnVertex)
+write(6,*) ' keepCellMask : sum (should be number of 1 values) ', sum(keepCellMask)
+
+
+end subroutine read_grid
+
+
+subroutine write_grid
+implicit none
+
+if (expand_from_unit_sphere) then
+   xCellNew = xCellNew * sphere_radius
+   yCellNew = yCellNew * sphere_radius
+   zCellNew = zCellNew * sphere_radius
+   xEdgeNew = xEdgeNew * sphere_radius
+   yEdgeNew = yEdgeNew * sphere_radius
+   zEdgeNew = zEdgeNew * sphere_radius
+   xVertexNew = xVertexNew * sphere_radius
+   yVertexNew = yVertexNew * sphere_radius
+   zVertexNew = zVertexNew * sphere_radius
+   dcEdgeNew = dcEdgeNew * sphere_radius
+   dvEdgeNew = dvEdgeNew * sphere_radius
+   areaCellNew = areaCellNew * (sphere_radius)**2
+   areaTriangleNew = areaTriangleNew * (sphere_radius)**2
+   kiteAreasOnVertexNew = kiteAreasOnVertexNew * (sphere_radius)**2
+endif
+
+call write_netcdf_init( &amp;
+                nCellsNew, &amp;
+                nEdgesNew, &amp;
+                nVerticesNew, &amp;
+                maxEdgesNew, &amp;
+                nVertLevelsNew, &amp;
+                vertexDegreeNew, &amp;
+                sphere_radius, &amp;
+                on_a_sphere &amp;
+                )
+
+call write_netcdf_fields( &amp;
+                    1, &amp;
+                    latCellNew, &amp;
+                    lonCellNew, &amp;
+                    meshDensityNew, &amp;
+                    xCellNew, &amp;
+                    yCellNew, &amp;
+                    zCellNew, &amp;
+                    indexToCellIDNew, &amp;
+                    latEdgeNew, &amp;
+                    lonEdgeNew, &amp;
+                    xEdgeNew, &amp;
+                    yEdgeNew, &amp;
+                    zEdgeNew, &amp;
+                    indexToEdgeIDNew, &amp;
+                    latVertexNew, &amp;
+                    lonVertexNew, &amp;
+                    xVertexNew, &amp;
+                    yVertexNew, &amp;
+                    zVertexNew, &amp;
+                    indexToVertexIDNew, &amp;
+                    cellsOnEdgeNew, &amp;
+                    nEdgesOnCellNew, &amp;
+                    nEdgesOnEdgeNew, &amp;
+                    edgesOnCellNew, &amp;
+                    edgesOnEdgeNew, &amp;
+                    weightsOnEdgeNew, &amp;
+                    dvEdgeNew, &amp;
+                    dcEdgeNew, &amp;
+                    angleEdgeNew, &amp;
+                    areaCellNew, &amp;
+                    areaTriangleNew, &amp;
+                    cellsOnCellNew, &amp;
+                    verticesOnCellNew, &amp;
+                    verticesOnEdgeNew, &amp;
+                    edgesOnVertexNew, &amp;
+                    cellsOnVertexNew, &amp;
+                    kiteAreasOnVertexNew &amp;
+                   )
+
+call write_netcdf_finalize
+
+if (expand_from_unit_sphere) then
+   xCellNew = xCellNew / sphere_radius
+   yCellNew = yCellNew / sphere_radius
+   zCellNew = zCellNew / sphere_radius
+   xEdgeNew = xEdgeNew / sphere_radius
+   yEdgeNew = yEdgeNew / sphere_radius
+   zEdgeNew = zEdgeNew / sphere_radius
+   xVertexNew = xVertexNew / sphere_radius
+   yVertexNew = yVertexNew / sphere_radius
+   zVertexNew = zVertexNew / sphere_radius
+   dcEdgeNew = dcEdgeNew / sphere_radius
+   dvEdgeNew = dvEdgeNew / sphere_radius
+   areaCellNew = areaCellNew / (sphere_radius)**2
+   areaTriangleNew = areaTriangleNew / (sphere_radius)**2
+   kiteAreasOnVertexNew = kiteAreasOnVertexNew / (sphere_radius)**2
+endif
+
+end subroutine write_grid
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+!  Step 4: Check define_kmt routine for bottomDepth and kmt (maxLevelCell) variables
+!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+subroutine define_kmt
+implicit none
+real (kind=4), allocatable, dimension(:) :: x,y, work_kmt
+real (kind=4), allocatable, dimension(:,:) :: ztopo
+integer :: nx, ny, inx, iny, ix, iy, kmt_neighbor_max
+real :: pi, dtr, zdata, rlon, rlat, r, ymin, ymax, xmin, xmax
+real :: latmin, latmax, lonmin, lonmax, ridgeDepth, maxdc
+logical :: flag, kmt_flag
+
+!pi = 4.0*atan(1.0)
+!dtr = pi / 180.0
+
+allocate(kmt(nCells))
+kmt = 0
+
+
+do iCell=1,nCells
+   if (keepCellMask(iCell) &gt; 0) then
+     kmt(iCell) = 1  ! any positive value will keep the cell, 0 cells will be culled
+   endif
+enddo
+
+
+!if (cut_domain_from_sphere) then
+!   latmin = -30*dtr
+!   latmax = +30*dtr
+!   lonmin = +10*dtr
+!   lonmax = +70*dtr
+!   write(6,*) ' lat min ', latmin
+!   write(6,*) ' lat max ', latmax
+!   where(latCell.lt.latmin) kmt = 0
+!   where(latCell.gt.latmax) kmt = 0
+!   where(lonCell.lt.lonmin) kmt = 0
+!   where(lonCell.gt.lonmax) kmt = 0
+!endif
+
+!if (solid_boundary_in_y) then
+!   ymin = minval(yCell)
+!   write(6,*) ' minimum yCell ', ymin
+!   ymax = maxval(yCell)
+!   write(6,*) ' maximum yCell ', ymax
+!   where(yCell.lt.1.001*ymin) kmt = 0
+!   where(yCell.gt.0.999*ymax) kmt = 0
+!endif
+
+!if (solid_boundary_in_x) then
+!   maxdc = maxval(dcEdge)
+!   xmin = minval(xCell)
+!   write(6,*) ' minimum xCell ', xmin
+!   xmax = maxval(xCell)
+!   write(6,*) ' maximum xCell ', xmax
+!   where(xCell.lt.xmin+maxdc/1.5) kmt = 0
+!   where(xCell.gt.xmax-maxdc/1.5) kmt = 0
+!endif
+
+    
+allocate(work_kmt(nCells))
+work_kmt = 0.0
+where(kmt.eq.0) work_kmt=1.0
+write(6,*) 'number of cells culled ',sum(work_kmt)
+deallocate(work_kmt)
+
+
+!! Eliminate isolated ocean cells, and make these isolated deep cells
+!! flush with the deepest neighbor.
+!do iCell=1,nCells
+!   kmt_neighbor_max = 0
+!   do j=1,nEdgesOnCell(iCell)
+!      iCell1 = cellsOnCell(j,iCell)
+!      kmt_neighbor_max = max(kmt_neighbor_max,kmt(iCell1))
+!   enddo
+!   if (kmt(iCell).gt.kmt_neighbor_max) then
+!      kmt(iCell) = kmt_neighbor_max
+!      bottomDepth(iCell) = refBottomDepth(kmt(iCell))
+!   endif
+!enddo
+
+!if(eliminate_inland_seas) then
+!call eliminateLoops(nCells,nEdges,nVertices,maxEdges,vertexDegree, &amp;
+!                    nEdgesOnCell, cellsOnCell, verticesOnEdge, cellsOnVertex, edgesOnCell, lonCell, latCell, &amp;
+!                    xCell, yCell, zCell, xEdge, yEdge, zEdge, xVertex, yVertex, zVertex, &amp;
+!                    KMT)
+!endif
+
+!! do not allow land or PBCs in top layers
+!k = min(top_layers_without_land,nVertLevelsMOD)
+!where(kmt.gt.0.and.kmt.le.k) 
+!   bottomDepth = refBottomDepth(k)
+!   kmt=k
+!endwhere
+
+end subroutine define_kmt
+
+
+
+subroutine define_mapping
+implicit none
+
+allocate(cellMap(nCells))
+allocate(edgeMap(nEdges))
+allocate(vertexMap(nVertices))
+cellMap = 0; edgeMap = 0; vertexMap = 0
+
+j=1
+do i=1,nCells
+if(kmt(i).ne.0) then
+    cellMap(i) = j
+    j=j+1
+endif
+write(10,*) i, cellMap(i)
+enddo
+
+j=1
+do i=1,nEdges
+iCell1 = cellsOnEdge(1,i)
+iCell2 = cellsOnEdge(2,i)
+if(kmt(iCell1).ne.0.or.kmt(iCell2).ne.0) then
+    edgeMap(i)=j
+    j=j+1
+endif
+write(11,*) i,edgeMap(i)
+enddo
+
+j=1
+do i=1,nVertices
+iCell1 = cellsOnVertex(1,i)
+iCell2 = cellsOnVertex(2,i)
+iCell3 = cellsOnVertex(3,i)
+if(kmt(iCell1).ne.0.or.kmt(iCell2).ne.0.or.kmt(iCell3).ne.0) then
+    vertexMap(i)=j
+    j=j+1
+endif
+write(12,*) i,vertexMap(i)
+enddo
+
+nCellsNew = 0
+do i=1,nCells
+if(cellMap(i).ne.0) nCellsNew = nCellsNew + 1
+enddo
+
+nEdgesNew = 0
+do i=1,nEdges
+if(edgeMap(i).ne.0) nEdgesNew = nEdgesNew + 1
+enddo
+
+nVerticesNew = 0
+do i=1,nVertices
+if(vertexMap(i).ne.0) nVerticesNew = nVerticesNew + 1
+enddo
+
+write(6,*) ' mesh mapping found '
+write(6,*)  nCells, nCellsNew
+write(6,*)  nEdges, nEdgesNew
+write(6,*)  nVertices, nVerticesNew
+
+allocate(indexToCellIDNew(nCellsNew))
+allocate(indexToEdgeIDNew(nEdgesNew))
+allocate(indexToVertexIDNew(nVerticesNew))
+indextoCellIDNew = 0; indexToEdgeIDNew = 0; indexToVertexIDNew = 0
+
+do i=1,nCellsNew
+indexToCellIDNew(i)=i
+enddo
+
+do i=1,nEdgesNew
+indexToEdgeIDNew(i)=i
+enddo
+
+do i=1,nVerticesNew
+indexToVertexIDNew(i)=i
+enddo
+
+end subroutine define_mapping
+
+
+subroutine map_vectors
+implicit none
+
+allocate(xCellNew(nCellsNew))
+allocate(yCellNew(nCellsNew))
+allocate(zCellNew(nCellsNew))
+allocate(normalsNew(3,nEdgesNew))
+allocate(latCellNew(nCellsNew))
+allocate(lonCellNew(nCellsNew))
+allocate(meshDensityNew(nCellsNew))
+allocate(meshSpacingNew(nCellsNew))
+allocate(xEdgeNew(nEdgesNew))
+allocate(yEdgeNew(nEdgesNew))
+allocate(zEdgeNew(nEdgesNew))
+allocate(latEdgeNew(nEdgesNew))
+allocate(lonEdgeNew(nEdgesNew))
+allocate(xVertexNew(nVerticesNew))
+allocate(yVertexNew(nVerticesNew))
+allocate(zVertexNew(nVerticesNew))
+allocate(latVertexNew(nVerticesNew))
+allocate(lonVertexNew(nVerticesNew))
+allocate(dcEdgeNew(nEdgesNew))
+allocate(dvEdgeNew(nEdgesNew))
+allocate(angleEdgeNew(nEdgesNew))
+allocate(areaCellNew(nCellsNew))
+allocate(areaTriangleNew(nVerticesNew))
+
+
+
+
+xCellNew=0; yCellNew=0; zCellNew=0; latCellNew=0; lonCellNew=0; meshDensityNew=1.0; meshSpacingNew=0.0
+xEdgeNew=0; yEdgeNew=0; zEdgeNew=0; latEdgeNew=0; lonEdgeNew=0
+xVertexNew=0; yVertexNew=0; zVertexNew=0; latVertexNew=0; lonVertexNew=0
+
+
+do i=1,nCells
+jNew = cellMap(i)
+if(jNew.ne.0) then
+    xCellNew(jNew)=xCell(i)
+    yCellNew(jNew)=yCell(i)
+    zCellNew(jNew)=zCell(i)
+    latCellNew(jNew)=latCell(i)
+    lonCellNew(jNew)=lonCell(i)
+    meshDensityNew(jNew)=meshDensity(i)
+    areaCellNew(jNew)=areaCell(i)
+endif
+enddo
+
+do i=1,nEdges
+jNew = edgeMap(i)
+if(jNew.ne.0) then
+    xEdgeNew(jNew)=xEdge(i)
+    yEdgeNew(jNew)=yEdge(i)
+    zEdgeNew(jNew)=zEdge(i)
+    latEdgeNew(jNew)=latEdge(i)
+    lonEdgeNew(jNew)=lonEdge(i)
+    dcEdgeNew(jNew) = dcEdge(i)
+    dvEdgeNew(jNew) = dvEdge(i)
+    angleEdgeNew(jNew) = angleEdge(i)
+endif
+enddo
+
+do i=1,nVertices
+jNew = vertexMap(i)
+if(jNew.ne.0) then
+    xVertexNew(jNew)=xVertex(i)
+    yVertexNew(jNew)=yVertex(i)
+    zVertexNew(jNew)=zVertex(i)
+    latVertexNew(jNew)=latVertex(i)
+    lonVertexNew(jNew)=lonVertex(i)
+    areaTriangleNew(jNew)=areaTriangle(i)
+endif
+enddo
+
+deallocate(xCell)
+deallocate(yCell)
+deallocate(zCell)
+deallocate(latCell)
+deallocate(lonCell)
+deallocate(meshDensity)
+deallocate(xEdge)
+deallocate(yEdge)
+deallocate(zEdge)
+deallocate(latEdge)
+deallocate(lonEdge)
+deallocate(xVertex)
+deallocate(yVertex)
+deallocate(zVertex)
+deallocate(latVertex)
+deallocate(lonVertex)
+deallocate(dcEdge)
+deallocate(dvEdge)
+
+end subroutine map_vectors
+
+
+
+subroutine map_connectivity
+implicit none
+
+allocate(cellsOnEdgeNew(TWONew,nEdgesNew))
+allocate(boundaryEdgeNew(nVertLevelsNew,nEdgesNew))
+allocate(flipVerticesOnEdgeOrdering(nEdgesNew))
+cellsOnEdgeNew(:,:) = 0
+boundaryEdgeNew(:,:) = 0
+flipVerticesOnEdgeOrdering(:) = 0
+do iEdge=1,nEdges
+if(edgeMap(iEdge).eq.0) cycle
+iEdgeNew = edgeMap(iEdge)
+iCell1 = cellsOnEdge(1,iEdge)
+iCell2 = cellsOnEdge(2,iEdge)
+iCell1New = cellMap(iCell1)
+iCell2New = cellMap(iCell2)
+cellsOnEdgeNew(1,iEdgeNew) = iCell1New
+cellsOnEdgeNew(2,iEdgeNew) = iCell2New
+if(iCell1New.eq.0.or.iCell2New.eq.0) boundaryEdgeNew(:,iEdgeNew) = 1
+if(iCell1New.eq.0.and.iCell2New.eq.0) stop &quot;cellsOnEdge&quot;
+if(iCell1New.eq.0) then
+    cellsOnEdgeNew(1,iEdgeNew) = iCell2New
+    cellsOnEdgeNew(2,iEdgeNew) = iCell1New
+    flipVerticesOnEdgeOrdering(iEdgeNew) = 1
+endif
+enddo
+deallocate(cellsOnEdge)
+
+allocate(verticesOnEdgeNew(TWONew,nEdgesNew))
+allocate(boundaryVertexNew(nVertLevelsNew,nVerticesNew))
+verticesOnEdgeNew(:,:) = 0
+boundaryVertexNew(:,:) = 0
+do iEdge=1,nEdges
+if(edgeMap(iEdge).eq.0) cycle
+iEdgeNew = edgeMap(iEdge)
+iVertex1 = VerticesOnEdge(1,iEdge)
+iVertex2 = VerticesOnEdge(2,iEdge)
+iVertex1New = vertexMap(iVertex1)
+iVertex2New = vertexMap(iVertex2)
+if(iVertex1New.eq.0.or.iVertex2New.eq.0) stop &quot;verticesOnEdge&quot;
+if(flipVerticesOnEdgeOrdering(iEdgeNew).eq.0) then
+  verticesOnEdgeNew(1,iEdgeNew) = iVertex1New
+  verticesOnEdgeNew(2,iEdgeNew) = iVertex2New
+else
+  verticesOnEdgeNew(1,iEdgeNew) = iVertex2New
+  verticesOnEdgeNew(2,iEdgeNew) = iVertex1New
+endif
+if(boundaryEdgeNew(1,iEdgeNew).eq.1) then
+    boundaryVertexNew(:,iVertex1New)=1
+    boundaryVertexNew(:,iVertex2New)=1
+endif
+enddo
+deallocate(verticesOnEdge)
+
+allocate(nEdgesOnEdgeNew(nEdgesNew))
+allocate(edgesOnEdgeNew(maxEdges2,nEdgesNew))
+allocate(weightsOnEdgeNew(maxEdges2,nEdgesNew))
+nEdgesOnEdgeNew(:) = 0
+edgesOnEdgeNew(:,:) = 0
+weightsOnEdgeNew(:,:) = 0.0
+do iEdge=1,nEdges
+if(edgeMap(iEdge).eq.0) cycle
+iEdgeNew = edgeMap(iEdge)
+if(boundaryEdgeNew(1,iEdgeNew).eq.1) then
+    nEdgesOnEdgeNew(iEdgeNew) = 0
+    edgesOnEdgeNew(:,iEdgeNew) = 0
+    weightsOnEdgeNew(:,iEdgeNew) = 0.0
+else
+    nEdgesOnEdgeNew(iEdgeNew) = nEdgesOnEdge(iEdge)
+    do i=1,nEdgesOnEdgeNew(iEdgeNew)
+    jEdge = edgesOnEdge(i,iEdge)
+    jEdgeNew = edgeMap(jEdge)
+    if(jEdgeNew.eq.0) stop &quot;jEdgeNew&quot;
+    edgesOnEdgeNew(i,iEdgeNew)=jEdgeNew
+    weightsOnEdgeNew(i,iEdgeNew) = weightsOnEdge(i,iEdge)
+    enddo
+endif
+enddo
+deallocate(nEdgesOnEdge)
+deallocate(edgesOnEdge)
+deallocate(weightsOnEdge)
+
+allocate(cellsOnCellNew(maxEdges,nCellsNew))
+allocate(nEdgesOnCellNew(nCellsNew))
+cellsOnCellNew = 0
+nEdgesOnCellNew = 0
+do iCell=1,nCells
+if(cellMap(iCell).eq.0) cycle
+iCellNew = cellMap(iCell)
+nEdgesOnCellNew(iCellNew)=nEdgesOnCell(iCell)
+do i=1,nEdgesOnCellNew(iCellNew)
+j = cellsOnCell(i,iCell)
+jNew = cellMap(j)
+cellsOnCellNew(i,iCellNew) = jNew
+enddo
+enddo
+deallocate(cellsOnCell)
+deallocate(nEdgesOnCell)
+
+allocate(edgesOnCellNew(maxEdgesNew,nCellsNew))
+edgesOnCellNew(:,:) = 0
+meshSpacingNew(:) = 0.0
+do iCell=1,nCells
+if(cellMap(iCell).eq.0) cycle
+iCellNew = cellMap(iCell)
+do i=1,nEdgesOnCellNew(iCellNew)
+j = edgesOnCell(i,iCell)
+jNew = edgeMap(j)
+if(jNew.eq.0) stop &quot;edgesOnCell&quot;
+edgesOnCellNew(i,iCellNew) = jNew
+meshSpacingNew(iCellNew) = meshSpacingNew(iCellNew) + dcEdgeNew(jNew)/nEdgesOnCellNew(iCellNew)
+enddo
+enddo
+deallocate(edgesOnCell)
+
+allocate(verticesOnCellNew(maxEdgesNew,nCellsNew))
+verticesOnCellNew(:,:)=0
+do iCell=1,nCells
+if(cellMap(iCell).eq.0) cycle
+iCellNew = cellMap(iCell)
+do i=1,nEdgesOnCellNew(iCellNew)
+j=verticesOnCell(i,iCell)
+jNew = vertexMap(j)
+if(jNew.eq.0) stop &quot;verticesOnCell&quot;
+verticesOnCellNew(i,iCellNew) = jNew
+enddo
+enddo
+deallocate(verticesOnCell)
+
+allocate(cellsOnVertexNew(vertexDegreeNew,nVerticesNew))
+allocate(kiteAreasOnVertexNew(vertexDegreeNew,nVerticesNew))
+cellsOnVertexNew = 0
+kiteAreasOnVertexNew = 0
+do iVertex=1,nVertices
+if(vertexMap(iVertex).eq.0) cycle
+iVertexNew = vertexMap(iVertex)
+do i=1,vertexDegree
+j=cellsOnVertex(i,iVertex)
+jNew=cellMap(j)
+if(jNew.eq.0) then
+    kiteAreasOnVertexNew(i,iVertexNew)=0
+else
+    kiteAreasOnVertexNew(i,iVertexNew)=kiteAreasOnVertex(i,iVertex)
+endif
+cellsOnVertexNew(i,iVertexNew)=jNew
+enddo
+enddo
+deallocate(cellsOnVertex)
+deallocate(kiteAreasOnVertex)
+
+areaTriangleNew = 0
+do iVertex=1,nVerticesNew
+do i=1,vertexDegree
+areaTriangleNew(iVertex) = areaTriangleNew(iVertex) + kiteAreasOnVertexNew(i,iVertex)
+enddo
+enddo
+
+allocate(edgesOnVertexNew(vertexDegreeNew, nVerticesNew))
+edgesOnVertexNew = 0
+do iVertex=1,nVertices
+if(vertexMap(iVertex).eq.0) cycle
+iVertexNew = vertexMap(iVertex)
+do i=1,vertexDegree
+j=edgesOnVertex(i,iVertex)
+jNew=edgeMap(j)
+edgesOnVertexNew(i,iVertexNew)=jNew
+enddo
+enddo
+deallocate(edgesOnVertex)
+
+! find normals
+normalsNew = 0.0
+do iEdge=1,nEdgesNew
+cell1 = cellsOnEdgeNew(1,iEdge)
+cell2 = cellsOnEdgeNew(2,iEdge)
+if(cell1.eq.0.or.cell2.eq.0) cycle
+c1(1) = xCellNew(cell1); c1(2) = yCellNew(cell1); c1(3) = zCellNew(cell1)
+c2(1) = xCellNew(cell2); c2(2) = yCellNew(cell2); c2(3) = zCellNew(cell2)
+distance = sqrt( (c1(1)-c2(1))**2 + (c1(2)-c2(2))**2 + (c1(3)-c2(3))**2 )
+
+if(on_a_sphere.eq.'YES') then
+    normalsNew(1,iEdge) = c2(1) - c1(1)
+    normalsNew(2,iEdge) = c2(2) - c1(2)
+    normalsNew(3,iEdge) = c2(3) - c1(3)
+    distance = sqrt( (c1(1)-c2(1))**2 + (c1(2)-c2(2))**2 + (c1(3)-c2(3))**2 )
+    normalsNew(:,iEdge) = normalsNew(:,iEdge) / distance
+else
+!    if(distance.gt.0.5*Lx) then
+!        write(6,*) ' periodic edge ', iEdge, distance
+!        write(6,10) '          c1   ', c1(:)
+!        write(6,10) '          c2   ', c2(:)
+!        r = c2(1) - c1(1)
+!        if(r.gt.0) c2(1) = c2(1) - Lx
+!        if(r.lt.0) c2(1) = c2(1) + Lx
+!        distance = sqrt( (c1(1)-c2(1))**2 + (c1(2)-c2(2))**2 + (c1(3)-c2(3))**2 )
+!        write(6,*) ' periodic edge fix ', iEdge, r, distance
+!    endif
+    normalsNew(1,iEdge) = c2(1) - c1(1)
+    normalsNew(2,iEdge) = c2(2) - c1(2)
+    normalsNew(3,iEdge) = c2(3) - c1(3)
+    distance = sqrt( (c1(1)-c2(1))**2 + (c1(2)-c2(2))**2 + (c1(3)-c2(3))**2 )
+    normalsNew(:,iEdge) = normalsNew(:,iEdge) / distance
+endif
+enddo
+10 format(a20,3e15.5)
+
+end subroutine map_connectivity
+
+
+end program crop_landice_grid

Added: branches/land_ice_projects/grid_tools/crop_landice_grid/define_keepCellMask.py
===================================================================
--- branches/land_ice_projects/grid_tools/crop_landice_grid/define_keepCellMask.py                                (rev 0)
+++ branches/land_ice_projects/grid_tools/crop_landice_grid/define_keepCellMask.py        2013-02-28 19:12:01 UTC (rev 2521)
@@ -0,0 +1,91 @@
+#!/usr/bin/python
+# Script for adding a field named cullMask to an MPAS land ice grid for use with the crop_landice_grid.F tool that actually culls the unwanted cells.
+# Matt Hoffman, February 28, 2013
+
+import sys
+import numpy as np
+from optparse import OptionParser
+import matplotlib.pyplot as plt
+try:
+  from Scientific.IO.NetCDF import NetCDFFile
+  netCDF_module = 'Scientific.IO.NetCDF'
+except ImportError:
+  try:
+    from netCDF4 import Dataset as NetCDFFile
+    netCDF_module = 'netCDF4'
+  except ImportError:
+      print 'Unable to import any of the following python modules:'
+      print '  Scientific.IO.NetCDF </font>
<font color="gray">  netcdf4 '
+      print 'One of them must be installed.'
+      raise ImportError('No netCDF module found')
+
+
+print &quot;** Gathering information.&quot;
+parser = OptionParser()
+parser.add_option(&quot;-f&quot;, &quot;--file&quot;, dest=&quot;file&quot;, help=&quot;grid file to modify; default: land_ice_grid.nc&quot;, metavar=&quot;FILE&quot;)
+
+
+options, args = parser.parse_args()
+
+if not options.file:
+        print &quot;No grid filename provided. Using land_ice_grid.nc.&quot;
+        options.file = &quot;land_ice_grid.nc&quot;
+
+try: 
+  f = NetCDFFile(options.file,'r+')
+except:
+  sys.exit('Error loading grid file.')
+  
+
+# get the right representation of the datatype
+if netCDF_module == 'Scientific.IO.NetCDF':
+    datatype = 'i'
+else:
+    datatype = f.variables['indexToCellID'].dtype  # Get the datatype for double precision float
+
+# Try to add the new variable
+if 'keepCellMask' not in f.variables:
+  f.createVariable('keepCellMask', datatype, ('nCells',))
+
+keepCellMask = f.variables['keepCellMask'][:]
+thickness = f.variables['thickness'][:]
+
+keepCellMask[:] = 0
+
+# =====  Various methods for defining the mask ====
+maskmeth = 2
+
+# 1. only keep cells with ice
+if maskmeth == 1:
+  keepCellMask[thickness[0,:] &gt; 0.0] = 1
+
+# 2. add a buffer of X cells around the ice 
+elif maskmeth == 2:
+
+  buffersize=4  # number of cells to expand
+
+  keepCellMask[thickness[0,:] &gt; 0.0] = 1  # start with the mask being where ice is
+  print 'Num of cells to keep:', sum(keepCellMask)
+  cellsOnCell = f.variables['cellsOnCell']
+  for i in range(buffersize):
+    print 'Starting buffer loop ', i+1
+    keepCellMaskNew = keepCellMask[:]+0 # make a copy to edit  --- the +0 makes an actual copy rather than pointing to the memory
+    for iCell in range(len(keepCellMask)):
+      for neighbor in cellsOnCell[iCell,:]-1:  # the -1 converts from the fortran indexing in the variable to python indexing
+        if keepCellMask[neighbor] == 1:  # if any neighbors are already being kept on the old mask then keep this cell too.  This will get all (or almost all) of the ice cells, but they have already been assigned so they don't matter.  What we care about is getting cells that are not ice that have on or more ice neighbors.
+           keepCellMaskNew[iCell] = 1
+    keepCellMask = keepCellMaskNew[:]+0  # after we've looped over all cells assign the new mask to the variable we need (either for another loop around the domain or to write out)
+    print 'Num of cells to keep:', sum(keepCellMask)
+fig = plt.figure(1, facecolor='w')
+ax = fig.add_subplot(111, aspect='equal')
+plt.scatter(f.variables['xCell'][:], f.variables['yCell'][:], 50, keepCellMask, edgecolors='none') #, vmin=minval, vmax=maxval)
+plt.colorbar()
+plt.draw()
+plt.show()
+
+f.variables['keepCellMask'][:] = keepCellMask
+
+#f.close()
+
+
+

Added: branches/land_ice_projects/grid_tools/crop_landice_grid/module_cullLoops.F
===================================================================
--- branches/land_ice_projects/grid_tools/crop_landice_grid/module_cullLoops.F                                (rev 0)
+++ branches/land_ice_projects/grid_tools/crop_landice_grid/module_cullLoops.F        2013-02-28 19:12:01 UTC (rev 2521)
@@ -0,0 +1,84 @@
+module cullLoops
+
+   public :: eliminateLoops
+
+   contains
+
+   subroutine eliminateLoops(nCells,nEdges,nVertices,maxEdges,vertexDegree, &amp;
+                nEdgesOnCell, cellsOnCell, verticesOnEdge, cellsOnVertex, edgesOnCell, lonCell, latCell, &amp;
+                xCell, yCell, zCell, xEdge, yEdge, zEdge, xVertex, yVertex, zVertex, &amp;
+                KMT)
+
+       implicit none
+
+       ! intent (in)
+       integer :: nCells, nEdges, nVertices, maxEdges, vertexDegree
+       integer :: nEdgesOnCell(nCells), cellsOnCell(maxEdges,nCells), verticesOnEdge(2,nEdges)
+       integer :: cellsOnVertex(vertexDegree,nVertices), edgesOnCell(maxEdges,nCells)
+       real :: lonCell(nCells), latCell(nCells)
+       real :: xCell(nCells), yCell(nCells), zCell(nCells)
+       real :: xEdge(nEdges), yEdge(nEdges), zEdge(nEdges)
+       real :: xVertex(nVertices), yVertex(nVertices), zVertex(nVertices)
+       integer :: edgeList(nEdges), iCellMask(nCells)
+
+       ! intent(inout)
+       integer, intent(inout) :: KMT(ncells)
+
+       ! local workspace
+       integer :: iCell, jCell, oCell, lCell, iEdge, i, kCell, iSharedEdge, iStartEdge, iSave, iSweep
+       integer :: iEdgeCounter, nEdgesInLoop(nCells), iCellAhead, LeftTurns, RightTurns
+       logical :: connected, atBoundary, moveSouth, moveEast, atGrenwich
+       real :: lat, rlat, rlon, rCenter(3), s(3), t(3), q(3), rCross, mylon, mylat, pi
+
+       integer, dimension(:), pointer :: cellStack
+       integer, dimension(:), pointer :: oceanMask
+       integer :: iCellStart, nStack, addedCells
+       real :: latStart, lonStart
+
+       write(6,*) 'Culling inland seas.....'
+
+       allocate(cellStack(nCells/2))
+       allocate(oceanMask(nCells))
+
+       oceanMask = 0
+       addedCells = 0
+
+       iCellStart = maxloc(kmt, dim=1)
+
+       write(6,*) 'Starting index. ', iCellStart
+       write(6,*) 'lat, lon: ', latCell(iCellStart), lonCell(iCellStart)
+       write(6,*) 'Starting kmt: ', kmt(iCellStart)
+
+       nStack = 1
+       cellStack(nStack) = iCellStart
+       oceanMask(iCellStart) = 1
+       addedCells = 1
+
+       do while(nStack &gt; 0)
+         oCell = cellStack(nStack)
+         nStack = nStack - 1
+         !write(6,*) '   Working on cell ', oCell, addedCells, nStack
+
+         do i = 1, nEdgesOnCell(oCell)
+            iCell = cellsOnCell(i, oCell) 
+
+            if(kmt(iCell) &gt; 0 .and. oceanMask(iCell) == 0) then
+              nStack = nStack + 1
+              cellStack(nStack) = iCell
+              oceanMask(iCell) = 1
+              addedCells = addedCells + 1
+            end if
+         end do
+       end do
+
+       where(oceanMask == 0) kmt(:) = 0
+
+       write(6,*) addedCells, ' total cells have been in the stack.'
+       write(6,*) 'Done culling inland seas.....'
+
+       deallocate(cellStack)
+       deallocate(oceanMask)
+
+   end subroutine eliminateLoops
+
+end module cullLoops

Added: branches/land_ice_projects/grid_tools/crop_landice_grid/module_read_netcdf.F
===================================================================
--- branches/land_ice_projects/grid_tools/crop_landice_grid/module_read_netcdf.F                                (rev 0)
+++ branches/land_ice_projects/grid_tools/crop_landice_grid/module_read_netcdf.F        2013-02-28 19:12:01 UTC (rev 2521)
@@ -0,0 +1,476 @@
+module read_netcdf

+   integer :: rd_ncid
+   integer :: rdDimIDTime
+   integer :: rdDimIDnCells
+   integer :: rdDimIDnEdges
+   integer :: rdDimIDnVertices
+   integer :: rdDimIDmaxEdges
+   integer :: rdDimIDmaxEdges2
+   integer :: rdDimIDnVertLevels
+   integer :: rdDimIDTWO
+   integer :: rdDimIDvertexDegree
+   integer :: rdVarIDlatCell
+   integer :: rdVarIDlonCell
+   integer :: rdVarIDmeshDensity
+   integer :: rdVarIDxCell
+   integer :: rdVarIDyCell
+   integer :: rdVarIDzCell
+   integer :: rdVarIDindexToCellID
+   integer :: rdVarIDlatEdge
+   integer :: rdVarIDlonEdge
+   integer :: rdVarIDxEdge
+   integer :: rdVarIDyEdge
+   integer :: rdVarIDzEdge
+   integer :: rdVarIDindexToEdgeID
+   integer :: rdVarIDlatVertex
+   integer :: rdVarIDlonVertex
+   integer :: rdVarIDxVertex
+   integer :: rdVarIDyVertex
+   integer :: rdVarIDzVertex
+   integer :: rdVarIDindexToVertexID
+   integer :: rdVarIDcellsOnEdge
+   integer :: rdVarIDnEdgesOnCell
+   integer :: rdVarIDnEdgesOnEdge
+   integer :: rdVarIDedgesOnCell
+   integer :: rdVarIDedgesOnEdge
+   integer :: rdVarIDweightsOnEdge
+   integer :: rdVarIDdvEdge
+   integer :: rdVarIDdcEdge
+   integer :: rdVarIDangleEdge
+   integer :: rdVarIDareaCell
+   integer :: rdVarIDareaTriangle
+   integer :: rdVarIDcellsOnCell
+   integer :: rdVarIDverticesOnCell
+   integer :: rdVarIDverticesOnEdge
+   integer :: rdVarIDedgesOnVertex
+   integer :: rdVarIDcellsOnVertex
+   integer :: rdVarIDkiteAreasOnVertex
+   integer :: rdVarIDkeepCellMask
+

+   integer :: rdLocalnCells
+   integer :: rdLocalnEdges
+   integer :: rdLocalnVertices
+   integer :: rdLocalmaxEdges
+   integer :: rdLocalmaxEdges2
+   integer :: rdLocalnVertLevels
+   integer :: rdLocalTWO
+   integer :: rdLocalvertexDegree

+   contains

+   subroutine read_netcdf_init( &amp;
+                               nCells, &amp;
+                               nEdges, &amp;
+                               nVertices, &amp;
+                               maxEdges, &amp;
+                               maxEdges2, &amp;
+                               nVertLevels, &amp;
+                               TWO, &amp;
+                               vertexDegree &amp;
+                               )

+      implicit none

+      include 'netcdf.inc'

+      integer, intent(out) :: nCells
+      integer, intent(out) :: nEdges
+      integer, intent(out) :: nVertices
+      integer, intent(out) :: maxEdges
+      integer, intent(out) :: maxEdges2
+      integer, intent(out) :: nVertLevels
+      integer, intent(out) :: TWO
+      integer, intent(out) :: vertexDegree

+      integer :: nferr


+      nferr = nf_open('land_ice_grid.nc', NF_SHARE, rd_ncid)

+      !
+      ! Get IDs for variable dimensions
+      !
+      nferr = nf_inq_unlimdim(rd_ncid, rdDimIDTime)
+      nferr = nf_inq_dimid(rd_ncid, 'nCells', rdDimIDnCells)
+      nferr = nf_inq_dimlen(rd_ncid, rdDimIDnCells, rdLocalnCells)
+      nferr = nf_inq_dimid(rd_ncid, 'nEdges', rdDimIDnEdges)
+      nferr = nf_inq_dimlen(rd_ncid, rdDimIDnEdges, rdLocalnEdges)
+      nferr = nf_inq_dimid(rd_ncid, 'nVertices', rdDimIDnVertices)
+      nferr = nf_inq_dimlen(rd_ncid, rdDimIDnVertices, rdLocalnVertices)
+      nferr = nf_inq_dimid(rd_ncid, 'maxEdges', rdDimIDmaxEdges)
+      nferr = nf_inq_dimlen(rd_ncid, rdDimIDmaxEdges, rdLocalmaxEdges)
+      nferr = nf_inq_dimid(rd_ncid, 'maxEdges2', rdDimIDmaxEdges2)
+      nferr = nf_inq_dimlen(rd_ncid, rdDimIDmaxEdges2, rdLocalmaxEdges2)
+      nferr = nf_inq_dimid(rd_ncid, 'nVertLevels', rdDimIDnVertLevels)
+      nferr = nf_inq_dimlen(rd_ncid, rdDimIDnVertLevels, rdLocalnVertLevels)
+      nferr = nf_inq_dimid(rd_ncid, 'vertexDegree', rdDimIDvertexDegree)
+      nferr = nf_inq_dimlen(rd_ncid, rdDimIDvertexDegree, rdLocalvertexDegree)
+      nferr = nf_inq_dimid(rd_ncid, 'TWO', rdDimIDTWO)
+      nferr = nf_inq_dimlen(rd_ncid, rdDimIDTWO, rdLocalTWO)
+
+
+      nCells = rdLocalnCells
+      nEdges = rdLocalnEdges
+      nVertices = rdLocalnVertices
+      maxEdges = rdLocalmaxEdges
+      maxEdges2 = rdLocalmaxEdges2
+      nVertLevels = rdLocalnVertLevels
+      vertexDegree = rdLocalvertexDegree
+      TWO = rdLocalTWO

+      !
+      ! Get IDs for variables
+      !
+      nferr = nf_inq_varid(rd_ncid, 'latCell', rdVarIDlatCell)
+      nferr = nf_inq_varid(rd_ncid, 'lonCell', rdVarIDlonCell)
+      nferr = nf_inq_varid(rd_ncid, 'meshDensity', rdVarIDmeshDensity)
+      nferr = nf_inq_varid(rd_ncid, 'xCell', rdVarIDxCell)
+      nferr = nf_inq_varid(rd_ncid, 'yCell', rdVarIDyCell)
+      nferr = nf_inq_varid(rd_ncid, 'zCell', rdVarIDzCell)
+      nferr = nf_inq_varid(rd_ncid, 'indexToCellID', rdVarIDindexToCellID)
+      nferr = nf_inq_varid(rd_ncid, 'latEdge', rdVarIDlatEdge)
+      nferr = nf_inq_varid(rd_ncid, 'lonEdge', rdVarIDlonEdge)
+      nferr = nf_inq_varid(rd_ncid, 'xEdge', rdVarIDxEdge)
+      nferr = nf_inq_varid(rd_ncid, 'yEdge', rdVarIDyEdge)
+      nferr = nf_inq_varid(rd_ncid, 'zEdge', rdVarIDzEdge)
+      nferr = nf_inq_varid(rd_ncid, 'indexToEdgeID', rdVarIDindexToEdgeID)
+      nferr = nf_inq_varid(rd_ncid, 'latVertex', rdVarIDlatVertex)
+      nferr = nf_inq_varid(rd_ncid, 'lonVertex', rdVarIDlonVertex)
+      nferr = nf_inq_varid(rd_ncid, 'xVertex', rdVarIDxVertex)
+      nferr = nf_inq_varid(rd_ncid, 'yVertex', rdVarIDyVertex)
+      nferr = nf_inq_varid(rd_ncid, 'zVertex', rdVarIDzVertex)
+      nferr = nf_inq_varid(rd_ncid, 'indexToVertexID', rdVarIDindexToVertexID)
+      nferr = nf_inq_varid(rd_ncid, 'cellsOnEdge', rdVarIDcellsOnEdge)
+      nferr = nf_inq_varid(rd_ncid, 'nEdgesOnCell', rdVarIDnEdgesOnCell)
+      nferr = nf_inq_varid(rd_ncid, 'nEdgesOnEdge', rdVarIDnEdgesOnEdge)
+      nferr = nf_inq_varid(rd_ncid, 'edgesOnCell', rdVarIDedgesOnCell)
+      nferr = nf_inq_varid(rd_ncid, 'edgesOnEdge', rdVarIDedgesOnEdge)
+      nferr = nf_inq_varid(rd_ncid, 'weightsOnEdge', rdVarIDweightsOnEdge)
+      nferr = nf_inq_varid(rd_ncid, 'dvEdge', rdVarIDdvEdge)
+      nferr = nf_inq_varid(rd_ncid, 'dcEdge', rdVarIDdcEdge)
+      nferr = nf_inq_varid(rd_ncid, 'angleEdge', rdVarIDangleEdge)
+      nferr = nf_inq_varid(rd_ncid, 'areaCell', rdVarIDareaCell)
+      nferr = nf_inq_varid(rd_ncid, 'areaTriangle', rdVarIDareaTriangle)
+      nferr = nf_inq_varid(rd_ncid, 'cellsOnCell', rdVarIDcellsOnCell)
+      nferr = nf_inq_varid(rd_ncid, 'verticesOnCell', rdVarIDverticesOnCell)
+      nferr = nf_inq_varid(rd_ncid, 'verticesOnEdge', rdVarIDverticesOnEdge)
+      nferr = nf_inq_varid(rd_ncid, 'edgesOnVertex', rdVarIDedgesOnVertex)
+      nferr = nf_inq_varid(rd_ncid, 'cellsOnVertex', rdVarIDcellsOnVertex)
+      nferr = nf_inq_varid(rd_ncid, 'kiteAreasOnVertex', rdVarIDkiteAreasOnVertex)
+      nferr = nf_inq_varid(rd_ncid, 'keepCellMask', rdVarIDkeepCellMask)
+   end subroutine read_netcdf_init


+   subroutine read_netcdf_fields( &amp;
+                                  time, &amp;
+                                  latCell, &amp;
+                                  lonCell, &amp;
+                                  meshDensity, &amp;
+                                  xCell, &amp;
+                                  yCell, &amp;
+                                  zCell, &amp;
+                                  indexToCellID, &amp;
+                                  latEdge, &amp;
+                                  lonEdge, &amp;
+                                  xEdge, &amp;
+                                  yEdge, &amp;
+                                  zEdge, &amp;
+                                  indexToEdgeID, &amp;
+                                  latVertex, &amp;
+                                  lonVertex, &amp;
+                                  xVertex, &amp;
+                                  yVertex, &amp;
+                                  zVertex, &amp;
+                                  indexToVertexID, &amp;
+                                  cellsOnEdge, &amp;
+                                  nEdgesOnCell, &amp;
+                                  nEdgesOnEdge, &amp;
+                                  edgesOnCell, &amp;
+                                  edgesOnEdge, &amp;
+                                  weightsOnEdge, &amp;
+                                  dvEdge, &amp;
+                                  dcEdge, &amp;
+                                  angleEdge, &amp;
+                                  areaCell, &amp;
+                                  areaTriangle, &amp;
+                                  cellsOnCell, &amp;
+                                  verticesOnCell, &amp;
+                                  verticesOnEdge, &amp;
+                                  edgesOnVertex, &amp;
+                                  cellsOnVertex, &amp;
+                                  kiteAreasOnVertex, &amp;
+                                  keepCellMask &amp;
+                                 )

+      implicit none

+      include 'netcdf.inc'

+      integer, intent(in) :: time
+      real (kind=8), dimension(:), intent(out) :: latCell
+      real (kind=8), dimension(:), intent(out) :: lonCell
+      real (kind=8), dimension(:), intent(out) :: meshDensity
+      real (kind=8), dimension(:), intent(out) :: xCell
+      real (kind=8), dimension(:), intent(out) :: yCell
+      real (kind=8), dimension(:), intent(out) :: zCell
+      integer, dimension(:), intent(out) :: indexToCellID
+      real (kind=8), dimension(:), intent(out) :: latEdge
+      real (kind=8), dimension(:), intent(out) :: lonEdge
+      real (kind=8), dimension(:), intent(out) :: xEdge
+      real (kind=8), dimension(:), intent(out) :: yEdge
+      real (kind=8), dimension(:), intent(out) :: zEdge
+      integer, dimension(:), intent(out) :: indexToEdgeID
+      real (kind=8), dimension(:), intent(out) :: latVertex
+      real (kind=8), dimension(:), intent(out) :: lonVertex
+      real (kind=8), dimension(:), intent(out) :: xVertex
+      real (kind=8), dimension(:), intent(out) :: yVertex
+      real (kind=8), dimension(:), intent(out) :: zVertex
+      integer, dimension(:), intent(out) :: indexToVertexID
+      integer, dimension(:,:), intent(out) :: cellsOnEdge
+      integer, dimension(:), intent(out) :: nEdgesOnCell
+      integer, dimension(:), intent(out) :: nEdgesOnEdge
+      integer, dimension(:,:), intent(out) :: edgesOnCell
+      integer, dimension(:,:), intent(out) :: edgesOnEdge
+      real (kind=8), dimension(:,:), intent(out) :: weightsOnEdge
+      real (kind=8), dimension(:), intent(out) :: dvEdge
+      real (kind=8), dimension(:), intent(out) :: dcEdge
+      real (kind=8), dimension(:), intent(out) :: angleEdge
+      real (kind=8), dimension(:), intent(out) :: areaCell
+      real (kind=8), dimension(:), intent(out) :: areaTriangle
+      integer, dimension(:,:), intent(out) :: cellsOnCell
+      integer, dimension(:,:), intent(out) :: verticesOnCell
+      integer, dimension(:,:), intent(out) :: verticesOnEdge
+      integer, dimension(:,:), intent(out) :: edgesOnVertex
+      integer, dimension(:,:), intent(out) :: cellsOnVertex
+      real (kind=8), dimension(:,:), intent(out) :: kiteAreasOnVertex
+      integer, dimension(:), intent(out) :: keepCellMask
+
+      logical :: meshDensityPresent

+      integer :: nferr
+      integer, dimension(1) :: start1, count1
+      integer, dimension(2) :: start2, count2
+      integer, dimension(3) :: start3, count3
+      integer, dimension(4) :: start4, count4
+
+      meshDensityPresent = .false.

+      start1(1) = 1

+      start2(1) = 1
+      start2(2) = 1

+      start3(1) = 1
+      start3(2) = 1
+      start3(3) = 1

+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDlatCell, start1, count1, latCell)

+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDlonCell, start1, count1, lonCell)
+
+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_inq_varid(rd_ncid, 'meshDensity', rdVarIDmeshDensity)
+      if(nferr.eq.0) then
+         nferr = nf_get_vara_double(rd_ncid, rdVarIDmeshDensity, start1, count1, meshDensity)
+      else
+         meshDensity=1.0
+         write(6,*) ' mesh density not present ', nferr, rdVarIDmeshDensity
+      endif

+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDxCell, start1, count1, xCell)

+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDyCell, start1, count1, yCell)

+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDzCell, start1, count1, zCell)

+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDindexToCellID, start1, count1, indexToCellID)
+
+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDlatEdge, start1, count1, latEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDlonEdge, start1, count1, lonEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDxEdge, start1, count1, xEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDyEdge, start1, count1, yEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDzEdge, start1, count1, zEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDindexToEdgeID, start1, count1, indexToEdgeID)

+      start1(1) = 1
+      count1( 1) = rdLocalnVertices
+      count1( 1) = rdLocalnVertices
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDlatVertex, start1, count1, latVertex)

+      start1(1) = 1
+      count1( 1) = rdLocalnVertices
+      count1( 1) = rdLocalnVertices
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDlonVertex, start1, count1, lonVertex)

+      start1(1) = 1
+      count1( 1) = rdLocalnVertices
+      count1( 1) = rdLocalnVertices
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDxVertex, start1, count1, xVertex)

+      start1(1) = 1
+      count1( 1) = rdLocalnVertices
+      count1( 1) = rdLocalnVertices
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDyVertex, start1, count1, yVertex)

+      start1(1) = 1
+      count1( 1) = rdLocalnVertices
+      count1( 1) = rdLocalnVertices
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDzVertex, start1, count1, zVertex)

+      start1(1) = 1
+      count1( 1) = rdLocalnVertices
+      count1( 1) = rdLocalnVertices
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDindexToVertexID, start1, count1, indexToVertexID)

+      start2(2) = 1
+      count2( 1) = rdLocalTWO
+      count2( 2) = rdLocalnEdges
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDcellsOnEdge, start2, count2, cellsOnEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDnEdgesOnCell, start1, count1, nEdgesOnCell)

+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDnEdgesOnEdge, start1, count1, nEdgesOnEdge)

+      start2(2) = 1
+      count2( 1) = rdLocalmaxEdges
+      count2( 2) = rdLocalnCells
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDedgesOnCell, start2, count2, edgesOnCell)

+      start2(2) = 1
+      count2( 1) = rdLocalmaxEdges2
+      count2( 2) = rdLocalnEdges
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDedgesOnEdge, start2, count2, edgesOnEdge)

+      start2(2) = 1
+      count2( 1) = rdLocalmaxEdges2
+      count2( 2) = rdLocalnEdges
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDweightsOnEdge, start2, count2, weightsOnEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDdvEdge, start1, count1, dvEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDdcEdge, start1, count1, dcEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnEdges
+      count1( 1) = rdLocalnEdges
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDangleEdge, start1, count1, angleEdge)

+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDareaCell, start1, count1, areaCell)

+      start1(1) = 1
+      count1( 1) = rdLocalnVertices
+      count1( 1) = rdLocalnVertices
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDareaTriangle, start1, count1, areaTriangle)

+      start2(2) = 1
+      count2( 1) = rdLocalmaxEdges
+      count2( 2) = rdLocalnCells
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDcellsOnCell, start2, count2, cellsOnCell)

+      start2(2) = 1
+      count2( 1) = rdLocalmaxEdges
+      count2( 2) = rdLocalnCells
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDverticesOnCell, start2, count2, verticesOnCell)

+      start2(2) = 1
+      count2( 1) = rdLocalTWO
+      count2( 2) = rdLocalnEdges
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDverticesOnEdge, start2, count2, verticesOnEdge)

+      start2(2) = 1
+      count2( 1) = rdLocalvertexDegree
+      count2( 2) = rdLocalnVertices
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDedgesOnVertex, start2, count2, edgesOnVertex)

+      start2(2) = 1
+      count2( 1) = rdLocalvertexDegree
+      count2( 2) = rdLocalnVertices
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDcellsOnVertex, start2, count2, cellsOnVertex)

+      start2(2) = 1
+      count2( 1) = rdLocalvertexDegree
+      count2( 2) = rdLocalnVertices
+      nferr = nf_get_vara_double(rd_ncid, rdVarIDkiteAreasOnVertex, start2, count2, kiteAreasOnVertex)
+   
+
+      start1(1) = 1
+      count1( 1) = rdLocalnCells
+      count1( 1) = rdLocalnCells
+      nferr = nf_get_vara_int(rd_ncid, rdVarIDkeepCellMask, start1, count1, keepCellMask)
+
+   end subroutine read_netcdf_fields


+   subroutine read_netcdf_finalize()

+      implicit none

+      include 'netcdf.inc'

+      integer :: nferr

+      nferr = nf_close(rd_ncid)

+   end subroutine read_netcdf_finalize

+end module read_netcdf

Added: branches/land_ice_projects/grid_tools/crop_landice_grid/module_write_netcdf.F
===================================================================
--- branches/land_ice_projects/grid_tools/crop_landice_grid/module_write_netcdf.F                                (rev 0)
+++ branches/land_ice_projects/grid_tools/crop_landice_grid/module_write_netcdf.F        2013-02-28 19:12:01 UTC (rev 2521)
@@ -0,0 +1,507 @@
+module write_netcdf

+   integer :: wr_ncid
+   integer :: wrDimIDTime
+   integer :: wrDimIDnCells
+   integer :: wrDimIDnEdges
+   integer :: wrDimIDnVertices
+   integer :: wrDimIDmaxEdges
+   integer :: wrDimIDmaxEdges2
+   integer :: wrDimIDTWO
+   integer :: wrDimIDvertexDegree
+   integer :: wrDimIDnVertLevels
+   integer :: wrDimIDnMonths
+   integer :: wrVarIDlatCell
+   integer :: wrVarIDlonCell
+   integer :: wrVarIDmeshDensity
+   integer :: wrVarIDxCell
+   integer :: wrVarIDyCell
+   integer :: wrVarIDzCell
+   integer :: wrVarIDindexToCellID
+   integer :: wrVarIDlatEdge
+   integer :: wrVarIDlonEdge
+   integer :: wrVarIDxEdge
+   integer :: wrVarIDyEdge
+   integer :: wrVarIDzEdge
+   integer :: wrVarIDindexToEdgeID
+   integer :: wrVarIDlatVertex
+   integer :: wrVarIDlonVertex
+   integer :: wrVarIDxVertex
+   integer :: wrVarIDyVertex
+   integer :: wrVarIDzVertex
+   integer :: wrVarIDindexToVertexID
+   integer :: wrVarIDmaxLevelCell
+   integer :: wrVarIDcellsOnEdge
+   integer :: wrVarIDnEdgesOnCell
+   integer :: wrVarIDnEdgesOnEdge
+   integer :: wrVarIDedgesOnCell
+   integer :: wrVarIDedgesOnEdge
+   integer :: wrVarIDweightsOnEdge
+   integer :: wrVarIDdvEdge
+   integer :: wrVarIDdcEdge
+   integer :: wrVarIDangleEdge
+   integer :: wrVarIDareaCell
+   integer :: wrVarIDareaTriangle
+   integer :: wrVarIDcellsOnCell
+   integer :: wrVarIDverticesOnCell
+   integer :: wrVarIDverticesOnEdge
+   integer :: wrVarIDedgesOnVertex
+   integer :: wrVarIDcellsOnVertex
+   integer :: wrVarIDkiteAreasOnVertex
+   integer :: wrVarIDfEdge
+   integer :: wrVarIDfVertex
+   integer :: wrVarIDbottomDepth
+   integer :: wrVarIDu
+   integer :: wrVarIDboundaryEdge
+   integer :: wrVarIDboundaryVertex
+   integer :: wrVarIDu_src
+   integer :: wrVarIDwindStressMonthly
+   integer :: wrVarIDh
+   integer :: wrVarIDrho
+   integer :: wrVarIDtemperature
+   integer :: wrVarIDsalinity
+   integer :: wrVarIDtracer1
+   integer :: wrVarIDtemperatureRestore
+   integer :: wrVarIDsalinityRestore
+   integer :: wrVarIDtemperatureRestoreMonthly
+   integer :: wrVarIDsalinityRestoreMonthly
+   integer :: wrVarIDhZLevel
+   integer :: wrVarIDrefBottomDepth

+   integer :: wrLocalnCells
+   integer :: wrLocalnEdges
+   integer :: wrLocalnVertices
+   integer :: wrLocalmaxEdges
+   integer :: wrLocalnVertLevels
+   integer :: wrLocalvertexDegree
+

+   contains

+   subroutine write_netcdf_init( &amp;
+                               nCells, &amp;
+                               nEdges, &amp;
+                               nVertices, &amp;
+                               maxEdges, &amp;
+                               nVertLevels, &amp;
+                               vertexDegree, &amp;
+                               sphere_radius, &amp; 
+                               on_a_sphere &amp;
+                               )

+      implicit none

+      include 'netcdf.inc'

+      integer, intent(in) :: nCells
+      integer, intent(in) :: nEdges
+      integer, intent(in) :: nVertices
+      integer, intent(in) :: maxEdges
+      integer, intent(in) :: nVertLevels
+      integer, intent(in) :: vertexDegree
+      character (len=16) :: on_a_sphere
+      real*8 :: sphere_radius
+

+      integer :: nferr
+      integer, dimension(10) :: dimlist


+      wrLocalnCells = nCells
+      wrLocalnEdges = nEdges
+      wrLocalnVertices = nVertices
+      wrLocalmaxEdges = maxEdges
+      wrLocalnVertLevels = nVertLevels
+      wrLocalvertexDegree = vertexDegree

+      nferr = nf_create('land_ice_grid_culled.nc', IOR(NF_CLOBBER,NF_64BIT_OFFSET), wr_ncid)

+      !
+      ! Define dimensions
+      !
+      nferr = nf_def_dim(wr_ncid, 'nCells', nCells, wrDimIDnCells)
+      nferr = nf_def_dim(wr_ncid, 'nEdges', nEdges, wrDimIDnEdges)
+      nferr = nf_def_dim(wr_ncid, 'nVertices', nVertices, wrDimIDnVertices)
+      nferr = nf_def_dim(wr_ncid, 'maxEdges', maxEdges, wrDimIDmaxEdges)
+      nferr = nf_def_dim(wr_ncid, 'maxEdges2', 2*maxEdges, wrDimIDmaxEdges2)
+      nferr = nf_def_dim(wr_ncid, 'TWO', 2, wrDimIDTWO)
+      nferr = nf_def_dim(wr_ncid, 'vertexDegree', vertexDegree, wrDimIDvertexDegree)
+      nferr = nf_def_dim(wr_ncid, 'nVertLevels', nVertLevels, wrDimIDnVertLevels)
+      nferr = nf_def_dim(wr_ncid, 'Time', NF_UNLIMITED, wrDimIDTime)

+      !
+      ! Define variables
+      !
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'latCell', NF_DOUBLE,  1, dimlist, wrVarIDlatCell)
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'lonCell', NF_DOUBLE,  1, dimlist, wrVarIDlonCell)
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'meshDensity', NF_DOUBLE,  1, dimlist, wrVarIDmeshDensity)
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'xCell', NF_DOUBLE,  1, dimlist, wrVarIDxCell)
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'yCell', NF_DOUBLE,  1, dimlist, wrVarIDyCell)
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'zCell', NF_DOUBLE,  1, dimlist, wrVarIDzCell)
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'indexToCellID', NF_INT,  1, dimlist, wrVarIDindexToCellID)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'latEdge', NF_DOUBLE,  1, dimlist, wrVarIDlatEdge)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'lonEdge', NF_DOUBLE,  1, dimlist, wrVarIDlonEdge)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'xEdge', NF_DOUBLE,  1, dimlist, wrVarIDxEdge)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'yEdge', NF_DOUBLE,  1, dimlist, wrVarIDyEdge)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'zEdge', NF_DOUBLE,  1, dimlist, wrVarIDzEdge)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'indexToEdgeID', NF_INT,  1, dimlist, wrVarIDindexToEdgeID)
+      dimlist( 1) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'latVertex', NF_DOUBLE,  1, dimlist, wrVarIDlatVertex)
+      dimlist( 1) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'lonVertex', NF_DOUBLE,  1, dimlist, wrVarIDlonVertex)
+      dimlist( 1) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'xVertex', NF_DOUBLE,  1, dimlist, wrVarIDxVertex)
+      dimlist( 1) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'yVertex', NF_DOUBLE,  1, dimlist, wrVarIDyVertex)
+      dimlist( 1) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'zVertex', NF_DOUBLE,  1, dimlist, wrVarIDzVertex)
+      dimlist( 1) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'indexToVertexID', NF_INT,  1, dimlist, wrVarIDindexToVertexID)
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'maxLevelCell', NF_INT,  1, dimlist, wrVarIDmaxLevelCell)
+      dimlist( 1) = wrDimIDTWO
+      dimlist( 2) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'cellsOnEdge', NF_INT,  2, dimlist, wrVarIDcellsOnEdge)
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'nEdgesOnCell', NF_INT,  1, dimlist, wrVarIDnEdgesOnCell)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'nEdgesOnEdge', NF_INT,  1, dimlist, wrVarIDnEdgesOnEdge)
+      dimlist( 1) = wrDimIDmaxEdges
+      dimlist( 2) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'edgesOnCell', NF_INT,  2, dimlist, wrVarIDedgesOnCell)
+      dimlist( 1) = wrDimIDmaxEdges2
+      dimlist( 2) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'edgesOnEdge', NF_INT,  2, dimlist, wrVarIDedgesOnEdge)
+      dimlist( 1) = wrDimIDmaxEdges2
+      dimlist( 2) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'weightsOnEdge', NF_DOUBLE,  2, dimlist, wrVarIDweightsOnEdge)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'dvEdge', NF_DOUBLE,  1, dimlist, wrVarIDdvEdge)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'dcEdge', NF_DOUBLE,  1, dimlist, wrVarIDdcEdge)
+      dimlist( 1) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'angleEdge', NF_DOUBLE,  1, dimlist, wrVarIDangleEdge)
+      dimlist( 1) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'areaCell', NF_DOUBLE,  1, dimlist, wrVarIDareaCell)
+      dimlist( 1) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'areaTriangle', NF_DOUBLE,  1, dimlist, wrVarIDareaTriangle)
+      dimlist( 1) = wrDimIDmaxEdges
+      dimlist( 2) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'cellsOnCell', NF_INT,  2, dimlist, wrVarIDcellsOnCell)
+      dimlist( 1) = wrDimIDmaxEdges
+      dimlist( 2) = wrDimIDnCells
+      nferr = nf_def_var(wr_ncid, 'verticesOnCell', NF_INT,  2, dimlist, wrVarIDverticesOnCell)
+      dimlist( 1) = wrDimIDTWO
+      dimlist( 2) = wrDimIDnEdges
+      nferr = nf_def_var(wr_ncid, 'verticesOnEdge', NF_INT,  2, dimlist, wrVarIDverticesOnEdge)
+      dimlist( 1) = wrDimIDvertexDegree
+      dimlist( 2) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'edgesOnVertex', NF_INT,  2, dimlist, wrVarIDedgesOnVertex)
+      dimlist( 1) = wrDimIDvertexDegree
+      dimlist( 2) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'cellsOnVertex', NF_INT,  2, dimlist, wrVarIDcellsOnVertex)
+      dimlist( 1) = wrDimIDvertexDegree
+      dimlist( 2) = wrDimIDnVertices
+      nferr = nf_def_var(wr_ncid, 'kiteAreasOnVertex', NF_DOUBLE,  2, dimlist, wrVarIDkiteAreasOnVertex)
+
+
+

+      nferr = nf_put_att_text(wr_ncid, NF_GLOBAL, 'on_a_sphere', 16, on_a_sphere)
+      nferr = nf_put_att_double(wr_ncid, NF_GLOBAL, 'sphere_radius', NF_DOUBLE, 1, sphere_radius)
+
+      nferr = nf_enddef(wr_ncid)
+
+   end subroutine write_netcdf_init


+   subroutine write_netcdf_fields( &amp;
+                                  time, &amp;
+                                  latCell, &amp;
+                                  lonCell, &amp;
+                                  meshDensity, &amp;
+                                  xCell, &amp;
+                                  yCell, &amp;
+                                  zCell, &amp;
+                                  indexToCellID, &amp;
+                                  latEdge, &amp;
+                                  lonEdge, &amp;
+                                  xEdge, &amp;
+                                  yEdge, &amp;
+                                  zEdge, &amp;
+                                  indexToEdgeID, &amp;
+                                  latVertex, &amp;
+                                  lonVertex, &amp;
+                                  xVertex, &amp;
+                                  yVertex, &amp;
+                                  zVertex, &amp;
+                                  indexToVertexID, &amp;
+                                  cellsOnEdge, &amp;
+                                  nEdgesOnCell, &amp;
+                                  nEdgesOnEdge, &amp;
+                                  edgesOnCell, &amp;
+                                  edgesOnEdge, &amp;
+                                  weightsOnEdge, &amp;
+                                  dvEdge, &amp;
+                                  dcEdge, &amp;
+                                  angleEdge, &amp;
+                                  areaCell, &amp;
+                                  areaTriangle, &amp;
+                                  cellsOnCell, &amp;
+                                  verticesOnCell, &amp;
+                                  verticesOnEdge, &amp;
+                                  edgesOnVertex, &amp;
+                                  cellsOnVertex, &amp;
+                                  kiteAreasOnVertex &amp;
+                                 )

+      implicit none

+      include 'netcdf.inc'

+      integer, intent(in) :: time
+      real (kind=8), dimension(:), intent(in) :: latCell
+      real (kind=8), dimension(:), intent(in) :: lonCell
+      real (kind=8), dimension(:), intent(in) :: meshDensity
+      real (kind=8), dimension(:), intent(in) :: xCell
+      real (kind=8), dimension(:), intent(in) :: yCell
+      real (kind=8), dimension(:), intent(in) :: zCell
+      integer, dimension(:), intent(in) :: indexToCellID
+      real (kind=8), dimension(:), intent(in) :: latEdge
+      real (kind=8), dimension(:), intent(in) :: lonEdge
+      real (kind=8), dimension(:), intent(in) :: xEdge
+      real (kind=8), dimension(:), intent(in) :: yEdge
+      real (kind=8), dimension(:), intent(in) :: zEdge
+      integer, dimension(:), intent(in) :: indexToEdgeID
+      real (kind=8), dimension(:), intent(in) :: latVertex
+      real (kind=8), dimension(:), intent(in) :: lonVertex
+      real (kind=8), dimension(:), intent(in) :: xVertex
+      real (kind=8), dimension(:), intent(in) :: yVertex
+      real (kind=8), dimension(:), intent(in) :: zVertex
+      integer, dimension(:), intent(in) :: indexToVertexID
+      integer, dimension(:,:), intent(in) :: cellsOnEdge
+      integer, dimension(:), intent(in) :: nEdgesOnCell
+      integer, dimension(:), intent(in) :: nEdgesOnEdge
+      integer, dimension(:,:), intent(in) :: edgesOnCell
+      integer, dimension(:,:), intent(in) :: edgesOnEdge
+      real (kind=8), dimension(:,:), intent(in) :: weightsOnEdge
+      real (kind=8), dimension(:), intent(in) :: dvEdge
+      real (kind=8), dimension(:), intent(in) :: dcEdge
+      real (kind=8), dimension(:), intent(in) :: angleEdge
+      real (kind=8), dimension(:), intent(in) :: areaCell
+      real (kind=8), dimension(:), intent(in) :: areaTriangle
+      integer, dimension(:,:), intent(in) :: cellsOnCell
+      integer, dimension(:,:), intent(in) :: verticesOnCell
+      integer, dimension(:,:), intent(in) :: verticesOnEdge
+      integer, dimension(:,:), intent(in) :: edgesOnVertex
+      integer, dimension(:,:), intent(in) :: cellsOnVertex
+      real (kind=8), dimension(:,:), intent(in) :: kiteAreasOnVertex
+
+

+      integer :: nferr
+      integer, dimension(1) :: start1, count1
+      integer, dimension(2) :: start2, count2
+      integer, dimension(3) :: start3, count3
+      integer, dimension(4) :: start4, count4

+      start1(1) = 1

+      start2(1) = 1
+      start2(2) = 1

+      start3(1) = 1
+      start3(2) = 1
+      start3(3) = 1

+      start4(1) = 1
+      start4(2) = 1
+      start4(3) = 1
+      start4(4) = 1

+      start1(1) = 1
+      count1( 1) = wrLocalnCells
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDlatCell, start1, count1, latCell)

+      start1(1) = 1
+      count1( 1) = wrLocalnCells
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDlonCell, start1, count1, lonCell)
+
+      start1(1) = 1
+      count1( 1) = wrLocalnCells
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDmeshDensity, start1, count1, meshDensity)

+      start1(1) = 1
+      count1( 1) = wrLocalnCells
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDxCell, start1, count1, xCell)

+      start1(1) = 1
+      count1( 1) = wrLocalnCells
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDyCell, start1, count1, yCell)

+      start1(1) = 1
+      count1( 1) = wrLocalnCells
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDzCell, start1, count1, zCell)

+      start1(1) = 1
+      count1( 1) = wrLocalnCells
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDindexToCellID, start1, count1, indexToCellID)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDlatEdge, start1, count1, latEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDlonEdge, start1, count1, lonEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDxEdge, start1, count1, xEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDyEdge, start1, count1, yEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDzEdge, start1, count1, zEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDindexToEdgeID, start1, count1, indexToEdgeID)

+      start1(1) = 1
+      count1( 1) = wrLocalnVertices
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDlatVertex, start1, count1, latVertex)

+      start1(1) = 1
+      count1( 1) = wrLocalnVertices
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDlonVertex, start1, count1, lonVertex)

+      start1(1) = 1
+      count1( 1) = wrLocalnVertices
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDxVertex, start1, count1, xVertex)

+      start1(1) = 1
+      count1( 1) = wrLocalnVertices
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDyVertex, start1, count1, yVertex)

+      start1(1) = 1
+      count1( 1) = wrLocalnVertices
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDzVertex, start1, count1, zVertex)

+      start1(1) = 1
+      count1( 1) = wrLocalnVertices
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDindexToVertexID, start1, count1, indexToVertexID)
+
+      start2(2) = 1
+      count2( 1) = 2
+      count2( 2) = wrLocalnEdges
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDcellsOnEdge, start2, count2, cellsOnEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnCells
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDnEdgesOnCell, start1, count1, nEdgesOnCell)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDnEdgesOnEdge, start1, count1, nEdgesOnEdge)

+      start2(2) = 1
+      count2( 1) = wrLocalmaxEdges
+      count2( 2) = wrLocalnCells
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDedgesOnCell, start2, count2, edgesOnCell)

+      start2(2) = 1
+      count2( 1) = 2*wrLocalmaxEdges
+      count2( 2) = wrLocalnEdges
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDedgesOnEdge, start2, count2, edgesOnEdge)

+      start2(2) = 1
+      count2( 1) = 2*wrLocalmaxEdges
+      count2( 2) = wrLocalnEdges
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDweightsOnEdge, start2, count2, weightsOnEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDdvEdge, start1, count1, dvEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDdcEdge, start1, count1, dcEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnEdges
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDangleEdge, start1, count1, angleEdge)

+      start1(1) = 1
+      count1( 1) = wrLocalnCells
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDareaCell, start1, count1, areaCell)

+      start1(1) = 1
+      count1( 1) = wrLocalnVertices
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDareaTriangle, start1, count1, areaTriangle)

+      start2(2) = 1
+      count2( 1) = wrLocalmaxEdges
+      count2( 2) = wrLocalnCells
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDcellsOnCell, start2, count2, cellsOnCell)

+      start2(2) = 1
+      count2( 1) = wrLocalmaxEdges
+      count2( 2) = wrLocalnCells
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDverticesOnCell, start2, count2, verticesOnCell)

+      start2(2) = 1
+      count2( 1) = 2
+      count2( 2) = wrLocalnEdges
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDverticesOnEdge, start2, count2, verticesOnEdge)

+      start2(2) = 1
+      count2( 1) = wrLocalvertexDegree
+      count2( 2) = wrLocalnVertices
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDedgesOnVertex, start2, count2, edgesOnVertex)

+      start2(2) = 1
+      count2( 1) = wrLocalvertexDegree
+      count2( 2) = wrLocalnVertices
+      nferr = nf_put_vara_int(wr_ncid, wrVarIDcellsOnVertex, start2, count2, cellsOnVertex)

+      start2(2) = 1
+      count2( 1) = wrLocalvertexDegree
+      count2( 2) = wrLocalnVertices
+      nferr = nf_put_vara_double(wr_ncid, wrVarIDkiteAreasOnVertex, start2, count2, kiteAreasOnVertex)

+


+   end subroutine write_netcdf_fields


+   subroutine write_netcdf_finalize()

+      implicit none

+      include 'netcdf.inc'

+      integer :: nferr

+      nferr = nf_close(wr_ncid)

+   end subroutine write_netcdf_finalize

+end module write_netcdf

Added: branches/land_ice_projects/grid_tools/crop_landice_grid/utilities.F
===================================================================
--- branches/land_ice_projects/grid_tools/crop_landice_grid/utilities.F                                (rev 0)
+++ branches/land_ice_projects/grid_tools/crop_landice_grid/utilities.F        2013-02-28 19:12:01 UTC (rev 2521)
@@ -0,0 +1,781 @@
+module utilities
+
+contains
+
+subroutine write_OpenDX(    on_a_sphere, &amp;
+                            nCells, &amp;
+                            nVertices, &amp;
+                            nEdges, &amp;
+                            vertexDegree, &amp;
+                            maxEdges, &amp;
+                            xCell, &amp;
+                            yCell, &amp;
+                            zCell, &amp;
+                            xVertex, &amp;
+                            yVertex, &amp;
+                            zVertex, &amp;
+                            xEdge, &amp;
+                            yEdge, &amp;
+                            zEdge, &amp;
+                            nEdgesOnCell, &amp;
+                            verticesOnCell, &amp;
+                            verticesOnEdge, &amp;
+                            cellsOnVertex, &amp;
+                            edgesOnCell, &amp;
+                            areaCell, &amp;
+                            maxLevelCell, &amp;
+                            meshSpacing, &amp;
+                            depthCell, &amp;
+                            SST, &amp;
+                            kiteAreasOnVertex )
+
+      implicit none
+
+      character (len=16), intent(in) :: on_a_sphere
+      integer, intent(in) :: nCells, nVertices, vertexDegree, nEdges, maxEdges
+      real (kind=8), dimension(nCells), intent(inout) :: xCell
+      real (kind=8), dimension(nCells), intent(inout) :: yCell
+      real (kind=8), dimension(nCells), intent(inout) :: zCell
+      real (kind=8), dimension(nVertices), intent(inout) :: xVertex
+      real (kind=8), dimension(nVertices), intent(inout) :: yVertex
+      real (kind=8), dimension(nVertices), intent(inout) :: zVertex
+      real (kind=8), dimension(nEdges), intent(inout) :: xEdge
+      real (kind=8), dimension(nEdges), intent(inout) :: yEdge
+      real (kind=8), dimension(nEdges), intent(inout) :: zEdge
+      integer, dimension(nCells), intent(in) :: nEdgesOnCell
+      integer, dimension(maxEdges,nCells), intent(in) :: verticesOnCell
+      integer, dimension(maxEdges,nCells), intent(in) :: edgesOnCell
+      integer, dimension(2,nEdges), intent(in) :: verticesOnEdge
+      integer, dimension(vertexDegree, nVertices), intent(in) :: cellsOnVertex
+      integer, dimension(nCells), intent(in) :: maxLevelCell
+      real (kind=8), dimension(nCells), intent(in) :: areaCell
+      real (kind=8), dimension(nCells), intent(in) :: depthCell, SST, meshSpacing
+      real (kind=8), dimension(vertexDegree,nVertices), intent(in) :: kiteAreasOnVertex
+
+      character(len=80) :: a, b, c, d, e, f
+      integer :: i, j, k, nVerticesTotal, iEdge, iLoop, iFace, Vert(4), Edge(4), iVertex, i1, i2, jp1
+      integer :: nKitesTotal, iCell, iEdge1, iEdge2, iVertex11, iVertex12, iVertex21, iVertex22, ksave
+      real (kind=8) :: x1, x2, x3, x4, y1, y2, y3, y4, z1, z2, z3, z4, xscale, work(nCells), work1(nCells), work2(nCells)
+      real (kind=8) :: xv, yv, zv, xc, yc, zc, dist
+      logical (kind=8) :: eflag
+
+      if(on_a_sphere.eq.'NO              ') then
+         write(6,*) ' write_dx, not on a sphere '
+      endif
+
+      xscale = 1.00
+      xCell = xCell*xscale
+      yCell = yCell*xscale
+      zCell = zCell*xscale
+      xVertex = xVertex*xscale
+      yVertex = yVertex*xscale
+      zVertex = zVertex*xscale
+      xEdge = xEdge*xscale
+      yEdge = yEdge*xscale
+      zEdge = zEdge*xscale
+
+      write(6,*) 'xCell', minval(xCell), maxval(xCell)
+      write(6,*) ' nCells', nCells
+      write(6,*) ' nEdges', nEdges
+      write(6,*) ' nVertices', nVertices
+      write(6,*) ' nEdgesOnCell',minval(nEdgesOnCell), maxval(nEdgesOnCell)
+
+      open(unit=1,file='dx/vector.dx',form='formatted',status='unknown')
+
+      a = trim('object &quot;positions list&quot; class array type float rank 1 shape 3 items')
+      b = trim('ascii data file vector.position.data')
+      write(1,10) a, nCells
+      write(1,10) b
+      write(1,*)
+
+      a = trim('object 0  class array type float rank 1 shape 3 items')
+      b = trim('ascii data file vector.data')
+      c = trim('attribute &quot;dep&quot; string &quot;positions&quot;')
+      write(1,10) a, nCells
+      write(1,10) b
+      write(1,10) c
+      write(1,*)
+
+      a = trim('object &quot;vector&quot; class field')
+      b = trim('component &quot;positions&quot;     &quot;positions list&quot;')
+      c = trim('component &quot;data&quot;           0')
+      write(1,10) a
+      write(1,10) b
+      write(1,10) c
+
+      close(1)
+
+      open(unit=14,file='dx/vector.position.data',form='formatted',status='unknown')
+      do i=1,nCells
+       write(14,22) xCell(i), yCell(i), zCell(i)
+      enddo
+      close(14)
+
+
+
+      nVerticesTotal = 0
+      do i=1,nCells
+       nVerticesTotal = nVerticesTotal + nEdgesOnCell(i)
+      enddo
+      write(6,*) 'total number of vertices', nVerticesTotal
+
+      open(unit=1,file='dx/ocean.dx',form='formatted',status='unknown')
+
+      a = trim('object &quot;positions list&quot; class array type float rank 1 shape 3 items')
+      b = trim('ascii data file ocean.position.data')
+      write(1,10) a, nVerticesTotal
+      write(1,10) b
+      write(1,*)
+      10 format(a70,i10)
+      
+      a = trim('object &quot;edge list&quot; class array type int rank 0 items')
+      b = trim('ascii data file ocean.edge.data')
+      c = trim('attribute &quot;ref&quot; string &quot;positions&quot;')
+      write(1,10) a, nVerticesTotal
+      write(1,10) b
+      write(1,10) c
+      write(1,*)
+      
+      a = trim('object &quot;loops list&quot; class array type int rank 0 items')
+      b = trim('ascii data file ocean.loop.data')
+      c = trim('attribute &quot;ref&quot; string &quot;edges&quot;')
+      write(1,10) a, nCells
+      write(1,10) b
+      write(1,10) c
+      write(1,*)
+      
+      a = trim('object &quot;face list&quot; class array type int rank 0 items')
+      b = trim('ascii data file ocean.face.data')
+      c = trim('attribute &quot;ref&quot; string &quot;loops&quot;')
+      write(1,10) a, nCells
+      write(1,10) b
+      write(1,10) c
+      write(1,*)
+      
+      a = trim('object 0  class array type float rank 0 items')
+      b = trim('data file ocean.meshSpacing.data')
+      c = trim('attribute &quot;dep&quot; string &quot;faces&quot;')
+      write(1,10) a, nCells
+      write(1,10) b
+      write(1,10) c
+      write(1,*)
+      
+      a = trim('object &quot;area&quot; class field')
+      b = trim('component &quot;positions&quot;     &quot;positions list&quot;')
+      c = trim('component &quot;edges&quot;         &quot;edge list&quot;')
+      d = trim('component &quot;loops&quot;         &quot;loops list&quot;')
+      e = trim('component &quot;faces&quot;         &quot;face list&quot;')
+      f = trim('component &quot;data&quot;           0')
+      write(1,10) a
+      write(1,10) b
+      write(1,10) c
+      write(1,10) d
+      write(1,10) e
+      write(1,10) f
+
+      close(1)
+
+     
+      work2 = meshSpacing
+      work1 = depthCell
+      work = SST
+
+      open(unit= 8,file='dx/ocean.meshSpacing.data',form='formatted',status='unknown')
+      open(unit= 9,file='dx/ocean.depth.data',form='formatted',status='unknown')
+      open(unit=10,file='dx/ocean.area.data',form='formatted',status='unknown')
+      open(unit=11,file='dx/ocean.face.data',form='formatted',status='unknown')
+      open(unit=12,file='dx/ocean.loop.data',form='formatted',status='unknown')
+      open(unit=13,file='dx/ocean.edge.data',form='formatted',status='unknown')
+      open(unit=14,file='dx/ocean.position.data',form='formatted',status='unknown')
+
+      iLoop = 0
+      iEdge = 0
+      do i=1,nCells
+       write(8,20) work2(i)
+       write(9,20) work1(i)
+       write(10,20) work(i)
+       write(11,21) i-1
+       write(12,21) iLoop
+       iLoop = iLoop + nEdgesOnCell(i)
+
+       eflag = .false.
+       do j=1,nEdgesOnCell(i)
+         k = verticesOnCell(j,i)
+         xv = xVertex(k); yv = yVertex(k); zv = zVertex(k)
+         xc = xCell(i); yc = yCell(i); zc = zCell(i)
+         dist = sqrt( (xc-xv)**2 + (yc-yv)**2 + (zc-zv)**2 )
+         if(dist.gt.5.0e5.and.on_a_sphere.eq.'NO              ') then
+           eflag = .true.
+         endif
+       enddo
+
+       if(eflag) then
+
+       do j=1,nEdgesOnCell(i)
+         write(13,21) iEdge
+         iEdge = iEdge + 1
+         k = verticesOnCell(j,i)
+         xv = xVertex(k); yv = yVertex(k); zv = zVertex(k)
+         xc = xCell(i); yc = yCell(i); zc = zCell(i)
+         dist = sqrt( (xc-xv)**2 + (yc-yv)**2 + (zc-zv)**2 )
+         if(dist.gt.5.0e5) then
+            write(14,22) xc, yc, zc
+         else
+            write(14,22) xv, yv, zv
+         endif
+       enddo
+
+       else
+
+       do j=1,nEdgesOnCell(i)
+         write(13,21) iEdge
+         iEdge = iEdge + 1
+         k = verticesOnCell(j,i)
+         if(k.le.0) write(6,*) ' vert1 ',k, verticesOnCell(:,i)
+         write(14,22) xVertex(k), yVertex(k), zVertex(k)
+         write(15,23) j,i,k,xVertex(k), yVertex(k), zVertex(k)
+       enddo
+      endif
+      enddo
+
+ 20   format(e20.10)
+ 21   format(i20)
+ 22   format(3e20.10)
+ 23   format(3i8, 3e20.10)
+
+      close(9)
+      close(10)
+      close(11)
+      close(12)
+      close(13)
+      close(14)
+
+  !   nVerticesTotal = 0
+  !   nKitesTotal = 0
+  !   do i=1,nCells
+  !    nKitesTotal = nKitesTotal + nEdgesOnCell(i)
+  !   enddo
+  !   nVerticesTotal = nKitesTotal*4
+  !   write(6,*) nKitesTotal, nVerticesTotal
+
+  !   open(unit=1,file='dx/kite.dx',form='formatted',status='unknown')
+
+  !   a = trim('object &quot;positions list&quot; class array type float rank 1 shape 3 items')
+  !   b = trim('ascii data file kite.position.data')
+  !   write(1,10) a, nVerticesTotal
+  !   write(1,10) b
+  !   write(1,*)
+
+  !   a = trim('object &quot;edge list&quot; class array type int rank 0 items')
+  !   b = trim('ascii data file kite.edge.data')
+  !   c = trim('attribute &quot;ref&quot; string &quot;positions&quot;')
+  !   write(1,10) a, nVerticesTotal
+  !   write(1,10) b
+  !   write(1,10) c
+  !   write(1,*)
+
+  !   a = trim('object &quot;loops list&quot; class array type int rank 0 items')
+  !   b = trim('ascii data file kite.loop.data')
+  !   c = trim('attribute &quot;ref&quot; string &quot;edges&quot;')
+  !   write(1,10) a, nKitesTotal
+  !   write(1,10) b
+  !   write(1,10) c
+  !   write(1,*)
+
+  !   a = trim('object &quot;face list&quot; class array type int rank 0 items')
+  !   b = trim('ascii data file kite.face.data')
+  !   c = trim('attribute &quot;ref&quot; string &quot;loops&quot;')
+  !   write(1,10) a, nKitesTotal
+  !   write(1,10) b
+  !   write(1,10) c
+  !   write(1,*)
+
+  !   a = trim('object 0  class array type float rank 0 items')
+  !   b = trim('data file kite.area.data')
+  !   c = trim('attribute &quot;dep&quot; string &quot;faces&quot;')
+  !   write(1,10) a, nKitesTotal
+  !   write(1,10) b
+  !   write(1,10) c
+  !   write(1,*)
+
+  !   a = trim('object &quot;area&quot; class field')
+  !   b = trim('component &quot;positions&quot;     &quot;positions list&quot;')
+  !   c = trim('component &quot;edges&quot;         &quot;edge list&quot;')
+  !   d = trim('component &quot;loops&quot;         &quot;loops list&quot;')
+  !   e = trim('component &quot;faces&quot;         &quot;face list&quot;')
+  !   f = trim('component &quot;data&quot;           0')
+  !   write(1,10) a
+  !   write(1,10) b
+  !   write(1,10) c
+  !   write(1,10) d
+  !   write(1,10) e
+  !   write(1,10) f
+
+  !   close(1)
+
+  !   open(unit=10,file='dx/kite.area.data',form='formatted',status='unknown')
+  !   open(unit=11,file='dx/kite.face.data',form='formatted',status='unknown')
+  !   open(unit=12,file='dx/kite.loop.data',form='formatted',status='unknown')
+  !   open(unit=13,file='dx/kite.edge.data',form='formatted',status='unknown')
+  !   open(unit=14,file='dx/kite.position.data',form='formatted',status='unknown')
+
+  !   iLoop = 0
+  !   iEdge = 0
+  !   iFace = 0
+
+  !   do iCell=1,nCells
+  !     do j=1,nEdgesOnCell(iCell)
+  !        iEdge1 = edgesOnCell(j,iCell)
+  !        jp1 = j+1
+  !        if(j.eq.nEdgesOnCell(iCell)) jp1=1
+  !        iEdge2 = edgesOnCell(jp1,iCell)
+
+  !        iVertex11 = verticesOnEdge(1,iEdge1)
+  !        iVertex21 = verticesOnEdge(2,iEdge1)
+  !        iVertex12 = verticesOnEdge(1,iEdge2)
+  !        ivertex22 = verticesOnEdge(2,iEdge2)
+
+  !        if(iVertex11.eq.iVertex12.or.iVertex11.eq.iVertex22) then
+  !           iVertex = iVertex11
+  !        elseif(iVertex21.eq.iVertex12.or.iVertex21.eq.iVertex22)  then
+  !           iVertex = iVertex21
+  !        else
+  !           write(6,*) iVertex11, iVertex21, iVertex12, iVertex22
+  !           stop
+  !        endif
+
+  !        ksave = 0
+  !        do k=1,vertexDegree
+  !          if(cellsOnVertex(k,iVertex).eq.iCell) ksave=k
+  !        enddo
+  !        if(ksave.eq.0) then 
+  !           write(6,*) ' can not find iCell'
+  !           write(6,*) cellsOnVertex(:,iVertex)
+  !           write(6,*) iCell
+  !           write(6,*) iEdge1, iEdge2
+  !           write(6,*) iVertex11, iVertex21, iVertex21, iVertex22
+  !           write(6,*) iVertex
+  !           stop
+  !         endif
+
+  !        write(11,21) iFace
+  !        write(12,21) iLoop
+  !        iFace = iFace + 1
+  !        iLoop = iLoop + 4
+  !        do k=1,4
+  !          write(13,21) iEdge
+  !          iEdge = iEdge + 1
+  !        enddo
+ !
+ !         x1 = xCell(iCell)    ; y1 = yCell(iCell)    ; z1 = zCell(iCell)
+ !         x2 = xEdge(iEdge1)   ; y2 = yEdge(iEdge1)   ; z2 = zEdge(iEdge1)
+ !         x3 = xVertex(iVertex); y3 = yVertex(iVertex); z3 = zVertex(iVertex)
+ !         x4 = xEdge(iEdge2)   ; y4 = yEdge(iEdge2)   ; z4 = zEdge(iEdge2)
+ !
+ !         write(14,22) x1, y1, z1
+ !         write(14,22) x2, y2, z2
+ !         write(14,22) x3, y3, z3
+ !         write(14,22) x4, y4, z4
+ !         write(10,22) kiteAreasOnVertex(ksave,iVertex)
+
+ !      enddo
+ !    enddo
+
+end subroutine write_OpenDX
+
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! SUBROUTINE CONVERT_LX
+!
+! Convert (lat,lon) to an (x, y, z) location on a sphere with specified radius.
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+subroutine convert_lx(x, y, z, radius, lat, lon)
+
+   implicit none
+
+   real, intent(in) :: radius
+   real, intent(in) :: lat, lon
+   real, intent(out) :: x, y, z
+
+   z = radius * sin(lat)
+   x = radius * cos(lon) * cos(lat)
+   y = radius * sin(lon) * cos(lat)
+
+end subroutine convert_lx
+
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! SUBROUTINE CONVERT_XL
+!
+! Convert (x, y, z) to a (lat, lon) location on a sphere with
+!    radius sqrt(x^2 + y^2 + z^2).
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+subroutine convert_xl(x, y, z, lat,lon)
+
+   implicit none
+
+   real, intent(in) :: x, y, z
+   real, intent(out) :: lat, lon
+
+   real :: dl, clat, pii, rtod
+   real :: eps
+   parameter (eps=1.e-10)
+
+   pii = 2.*asin(1.0)
+   rtod=180./pii
+   dl = sqrt(x*x + y*y + z*z)
+
+   lat = asin(z/dl)
+
+!  check for being close to either pole
+
+   if (abs(x) &gt; eps) then
+
+      if (abs(y) &gt; eps) then
+
+         lon = atan(abs(y/x))
+
+         if ((x &lt;= 0.) .and. (y &gt;= 0.)) then
+            lon = pii-lon
+         else if ((x &lt;= 0.) .and. (y &lt; 0.)) then
+            lon = lon+pii
+         else if ((x &gt;= 0.) .and. (y &lt;= 0.)) then
+            lon = 2*pii-lon
+         end if
+
+      else ! we're either on longitude 0 or 180
+
+         if (x &gt; 0) then
+            lon = 0.
+         else
+            lon = pii
+         end if
+
+      end if
+
+   else if (abs(y) &gt; eps) then
+
+      if (y &gt; 0) then
+         lon = pii/2.
+      else
+         lon = 3.*pii/2.
+      end if
+
+   else  ! we are at a pole
+
+      lon = 0.
+
+   end if
+
+end subroutine convert_xl
+
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+subroutine transform_from_lonlat_to_xyz(xin, yin, zin, ulon, ulat, ux, uy, uz)
+!
+!  transform vector measured in latitude/longitude space to a vector measured in x,y,z
+!
+!     INTENT(IN)
+!     xin = x position
+!     yin = y position
+!     zin = z position
+!     ulon = east component of vector
+!     ulat = north component of vector
+!
+!     INTENT(OUT)
+!     ux = x component of vector
+!     uy = y component of vector
+!     uz = z component of vector
+!
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+implicit none
+real, intent(in) :: xin, yin, zin, ulon, ulat
+real, intent(out) :: ux, uy, uz
+real :: h(3,3), p(3), q(3), g(3), X1(3,3), X2(3,3), trans_X2_to_X1(3,3), r
+integer :: i,j,k
+logical :: l_Pole
+real, parameter :: epsvt = 1.0e-10
+
+!-----------------------------------------------------------------------
+! define the e1, e2, and e3 directions
+!-----------------------------------------------------------------------
+        X1(1,1) = 1.0; X1(1,2) = 0.0; X1(1,3) = 0.0
+        X1(2,1) = 0.0; X1(2,2) = 1.0; X1(2,3) = 0.0
+        X1(3,1) = 0.0; X1(3,2) = 0.0; X1(3,3) = 1.0
+
+!-----------------------------------------------------------------------
+! find the vectors (measured in X1) that point in the local
+!   east (h(1,:)), north (h(2,:)), and vertical (h(3,:)) direction
+!-----------------------------------------------------------------------
+        h(3,1) = xin; h(3,2) = yin; h(3,3) = zin
+        call unit_vector_in_3space(h(3,:))
+
+!-----------------------------------------------------------------------
+! g(:) is a work array and holds the vector pointing to the North Pole.
+! measured in X1
+!-----------------------------------------------------------------------
+              g(:) = X1(3,:)
+
+!-----------------------------------------------------------------------
+! determine if the local vertical hits a pole
+!-----------------------------------------------------------------------
+              l_Pole = .false.
+              r = g(1)*h(3,1) + g(2)*h(3,2) + g(3)*h(3,3)
+              r = abs(r) + epsvt
+              if(r.gt.1.0) then
+                l_Pole = .true.
+                h(3,:) = h(3,:) + epsvt
+                call unit_vector_in_3space(h(3,:))
+              endif
+
+!-----------------------------------------------------------------------
+! find the vector that is perpendicular to the local vertical vector
+! and points in the direction of of the North pole, this defines the local
+! north direction. measured in X1
+!-----------------------------------------------------------------------
+              call vector_on_tangent_plane ( h(3,:), g(:), h(2,:) )
+
+!-----------------------------------------------------------------------
+! take the cross product of the local North direction and the local vertical
+! to find the local east vector. still in X1
+!-----------------------------------------------------------------------
+              call cross_product_in_3space ( h(2,:), h(3,:), h(1,:) )
+
+!-----------------------------------------------------------------------
+! put these 3 vectors into a matrix X2
+!-----------------------------------------------------------------------
+              X2(1,:) = h(1,:)              ! local east     (measured in X1)
+              X2(2,:) = h(2,:)              ! local north    (measured in X1)
+              X2(3,:) = h(3,:)              ! local vertical (measured in X1)
+
+!-----------------------------------------------------------------------
+! compute the transformation matrix
+!-----------------------------------------------------------------------
+              trans_X2_to_X1(:,:) = matmul(X1,transpose(X2))
+
+!-----------------------------------------------------------------------
+! transform (ulon, ulat) into (x,y,z)
+!-----------------------------------------------------------------------
+              p(1) = ulon; p(2) = ulat; p(3) = 0
+              g(:) = matmul(trans_X2_to_X1(:, :), p(:))
+              ux = g(1); uy = g(2); uz = g(3)
+
+end subroutine transform_from_lonlat_to_xyz
+
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+subroutine transform_from_xyz_to_lonlat(xin, yin, zin, ux, uy, uz, ulon, ulat)
+!
+!  transform vector measured in x,y,z space to a vector measured in latitude/longitude space
+!
+!     INTENT(IN)
+!     xin = x position
+!     yin = y position
+!     zin = z position
+!     ux = x component of vector
+!     uy = y component of vector
+!     uz = z component of vector
+!
+!     INTENT(OUT)
+!     ulon = east component of vector
+!     ulat = north component of vector
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+implicit none
+real, intent(in) :: xin, yin, zin, ux, uy, uz
+real, intent(out) :: ulon, ulat
+real :: h(3,3), p(3), q(3), g(3), X1(3,3), X2(3,3), trans_X1_to_X2(3,3), r
+integer :: i,j,k
+logical :: l_Pole
+real, parameter :: epsvt = 1.0e-10
+
+!-----------------------------------------------------------------------
+! define the e1, e2, and e3 directions
+!-----------------------------------------------------------------------
+        X1(1,1) = 1.0; X1(1,2) = 0.0; X1(1,3) = 0.0
+        X1(2,1) = 0.0; X1(2,2) = 1.0; X1(2,3) = 0.0
+        X1(3,1) = 0.0; X1(3,2) = 0.0; X1(3,3) = 1.0
+
+!-----------------------------------------------------------------------
+! find the vectors (measured in X1) that point in the local
+!   east (h(1,:)), north (h(2,:)), and vertical (h(3,:)) direction
+!-----------------------------------------------------------------------
+        h(3,1) = xin; h(3,2) = yin; h(3,3) = zin
+        call unit_vector_in_3space(h(3,:))
+
+!-----------------------------------------------------------------------
+! g(:) is a work array and holds the vector pointing to the North Pole.
+! measured in X1
+!-----------------------------------------------------------------------
+              g(:) = X1(3,:)
+
+!-----------------------------------------------------------------------
+! determine if the local vertical hits a pole
+!-----------------------------------------------------------------------
+              l_Pole = .false.
+              r = g(1)*h(3,1) + g(2)*h(3,2) + g(3)*h(3,3)
+              r = abs(r) + epsvt
+              if(r.gt.1.0) then
+                l_Pole = .true.
+                h(3,:) = h(3,:) + epsvt
+                call unit_vector_in_3space(h(3,:))
+              endif
+
+!-----------------------------------------------------------------------
+! find the vector that is perpendicular to the local vertical vector
+! and points in the direction of of the North pole, this defines the local
+! north direction. measured in X1
+!-----------------------------------------------------------------------
+              call vector_on_tangent_plane ( h(3,:), g(:), h(2,:) )
+
+!-----------------------------------------------------------------------
+! take the cross product of the local North direction and the local vertical
+! to find the local east vector. still in X1
+!-----------------------------------------------------------------------
+              call cross_product_in_3space ( h(2,:), h(3,:), h(1,:) )
+
+!-----------------------------------------------------------------------
+! put these 3 vectors into a matrix X2
+!-----------------------------------------------------------------------
+              X2(1,:) = h(1,:)              ! local east     (measured in X1)
+              X2(2,:) = h(2,:)              ! local north    (measured in X1)
+              X2(3,:) = h(3,:)              ! local vertical (measured in X1)
+
+!-----------------------------------------------------------------------
+! compute the transformation matrix
+!-----------------------------------------------------------------------
+              trans_X1_to_X2(:,:) = matmul(X2,transpose(X1))
+
+!-----------------------------------------------------------------------
+! transform (ulon, ulat) into (x,y,z)
+!-----------------------------------------------------------------------
+              p(1) = ux; p(2) = uy; p(3) = uz
+              g(:) = matmul(trans_X1_to_X2(:, :), p(:))
+              ulon = g(1); ulat= g(2);
+
+end subroutine transform_from_xyz_to_lonlat
+
+!======================================================================
+! BEGINNING OF UNIT_VECTOR_IN_3SPACE
+!======================================================================
+        subroutine unit_vector_in_3space (p_1)
+
+!-----------------------------------------------------------------------
+! PURPOSE : normalize p_1 to unit length and overwrite p_1
+!-----------------------------------------------------------------------
+
+!-----------------------------------------------------------------------
+! intent(inout)
+!-----------------------------------------------------------------------
+        real , intent(inout) ::                         &amp;
+                        p_1 (:)
+
+!-----------------------------------------------------------------------
+! local
+!-----------------------------------------------------------------------
+        real  :: length
+
+        length = SQRT (p_1(1)**2 + p_1(2)**2 + p_1(3)**2 )
+        length = 1.0/length
+        p_1(1) = p_1(1)*length
+        p_1(2) = p_1(2)*length
+        p_1(3) = p_1(3)*length
+
+        end subroutine unit_vector_in_3space
+!======================================================================
+! END OF UNIT_VECTOR_IN_3SPACE
+!======================================================================
+
+!======================================================================
+! BEGINNING OF CROSS_PRODUCT_IN_3SPACE
+!======================================================================
+        subroutine cross_product_in_3space(p_1,p_2,p_out)
+
+!-----------------------------------------------------------------------
+! PURPOSE: compute p_1 cross p_2 and place in p_out
+!-----------------------------------------------------------------------
+
+!-----------------------------------------------------------------------
+! intent(in)
+!-----------------------------------------------------------------------
+        real , intent(in) ::                            &amp;
+                        p_1 (:),                                      &amp;
+                        p_2 (:)
+
+!-----------------------------------------------------------------------
+! intent(out)
+!-----------------------------------------------------------------------
+        real , intent(out) ::                           &amp;
+                        p_out (:)
+
+        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_3space
+!======================================================================
+! END OF CROSS_PRODUCT_IN_3SPACE
+!======================================================================
+
+!======================================================================
+! BEGINNING OF VECTOR_ON_TANGENT_PLANE
+!======================================================================
+        subroutine vector_on_tangent_plane(p_1, p_2, p_out)
+
+!-----------------------------------------------------------------------
+! PURPOSE : given two points measured in (x,y,z) and lying on
+!       the unit sphere, find the vector (p_out) that lies on the plane
+!       perpendicular to the p_1 vector and points in the direction of
+!       the projection of p_2 onto the tangent plane.
+!
+! NOTE : p_1 and p_2 are assumed to be of unit length
+! NOTE : p_out is normalized to unit length
+!-----------------------------------------------------------------------
+
+!-----------------------------------------------------------------------
+! intent(in)
+!-----------------------------------------------------------------------
+        real , intent(in) ::                            &amp;
+                        p_1 (:),                                      &amp;
+                        p_2 (:)
+
+!-----------------------------------------------------------------------
+! intent(out)
+!-----------------------------------------------------------------------
+        real , intent(out) ::                           &amp;
+                        p_out (:)
+
+!-----------------------------------------------------------------------
+! local
+!-----------------------------------------------------------------------
+        real  ::                                        &amp;
+                        work (3), t1(3), t2(3)
+
+!       work (1) = - p_1(2) * ( -p_1(2) * p_2(1) + p_1(1) * p_2(2) )   &amp;
+!                  + p_1(3) * (  p_1(3) * p_2(1) - p_1(1) * p_2(3) )
+
+!       work (2) = + p_1(1) * ( -p_1(2) * p_2(1) + p_1(1) * p_2(2) )   &amp;
+!                  - p_1(3) * ( -p_1(3) * p_2(2) + p_1(2) * p_2(3) )
+
+!       work (3) = - p_1(1) * (  p_1(3) * p_2(1) - p_1(1) * p_2(3) )   &amp;
+!                  + p_1(2) * ( -p_1(3) * p_2(2) + p_1(2) * p_2(3) )
+
+
+        t1(:) = p_2(:) - p_1(:)
+        t2(:) = p_1
+
+        call unit_vector_in_3space (t1)
+        call unit_vector_in_3space (t2)
+
+        call cross_product_in_3space(t1(:), t2(:), work(:))
+        call unit_vector_in_3space (work)
+        call cross_product_in_3space(t2(:),work(:),p_out(:))
+        call unit_vector_in_3space (p_out)
+
+        end subroutine vector_on_tangent_plane
+!======================================================================
+! END OF VECTOR_ON_TANGENT_PLANE
+!======================================================================
+
+end module utilities

</font>
</pre>