Index: branches/2011/dev_r2802_UKMET3_rebuild/NEMOGCM/TOOLS/REBUILD_NEMO/src/rebuild_nemo.f90
===================================================================
--- branches/2011/dev_r2802_UKMET3_rebuild/NEMOGCM/TOOLS/REBUILD_NEMO/src/rebuild_nemo.f90	(revision 3019)
+++ branches/2011/dev_r2802_UKMET3_rebuild/NEMOGCM/TOOLS/REBUILD_NEMO/src/rebuild_nemo.f90	(revision 3025)
@@ -14,4 +14,6 @@
    !!     * works for 1,2,3 and 4d arrays or types for all valid NetCDF types
    !!     * utilises OMP shared memory parallelisation where applicable
+   !!     * time 'chunking' for lower memory use 
+   !!       (only for 4D vars with unlimited dimension)
    !!
    !!  Ed Blockley - August 2011
@@ -36,4 +38,8 @@
    !!  and errors are written to numerr (default 0 - stderr).
    !!
+   !!  If time chunking is specified the code will use less memory but take a little longer.
+   !!  It does this by breaking down the 4D input variables over their 4th dimension 
+   !!  (generally time) by way of a while loop.
+   !!
    !!-------------------------------------------------------------------------------
   
@@ -61,9 +67,10 @@
    CHARACTER(LEN=nf90_max_name), DIMENSION(2) :: dims
 
-   INTEGER :: ndomain, ifile, ndomain_file
+   INTEGER :: ndomain, ifile, ndomain_file, nchunksize
    INTEGER :: ncid, outid, idim, istop
    INTEGER :: natts, attid, xtype, varid, rbdims 
    INTEGER :: jv, ndims, nvars, dimlen, dimids(4)
    INTEGER :: dimid, unlimitedDimId, di, dj, dr
+   INTEGER :: nmax_unlimited, nt, ntchunk 
    INTEGER :: chunksize = 32000000
    INTEGER :: nthreads = 1
@@ -145,5 +152,5 @@
    LOGICAL :: l_findDims = .true.
 
-   NAMELIST/nam_rebuild/ filebase, ndomain, dims
+   NAMELIST/nam_rebuild/ filebase, ndomain, dims, nchunksize
 
    !End of definitions 
@@ -163,4 +170,5 @@
 
    dims(:) = ""
+   nchunksize = 0
    OPEN( UNIT=numnam, FILE='nam_rebuild', FORM='FORMATTED', STATUS='OLD' )
    READ( numnam, nam_rebuild )
@@ -249,4 +257,5 @@
       IF( idim == unlimitedDimId ) THEN
          CALL check_nf90( nf90_def_dim( outid, dimname, nf90_unlimited, dimid) )
+         nmax_unlimited = dimlen
       ELSE
          CALL check_nf90( nf90_def_dim( outid, dimname, dimlen, dimid) )
@@ -336,4 +345,7 @@
       l_valid = .false.
       istop = nf90_noerr
+      nt = 1
+      ntchunk = nmax_unlimited
+      IF( nchunksize == 0 ) nchunksize = nmax_unlimited
 
 !3.2 Inquire variable to find out name and how many dimensions it has
@@ -349,7 +361,20 @@
       ENDIF
 
+!3.2.0 start while loop for time chunking
+
+      DO WHILE( nt <= nmax_unlimited )
+
+         IF( ndims > 3 ) THEN
+            ntchunk = MIN( nchunksize, nmax_unlimited + 1 - nt )
+         ENDIF
+
       IF (l_noRebuild) THEN
 
-         IF (l_verbose) WRITE(numout,*) 'Copying data from variable '//TRIM(varname)//'...'
+         IF( nchunksize == nmax_unlimited .OR. ndims <= 3 ) THEN
+            IF (l_verbose) WRITE(numout,*) 'Copying data from variable '//TRIM(varname)//'...'
+         ELSE
+            IF (l_verbose) WRITE(numout,'(A,I3,A,I3,A)') ' Copying data from variable '  &
+            &                 //TRIM(varname)//' for chunks ',nt,' to ',nt+ntchunk-1,' ...'
+         ENDIF
 
 !3.2.1 If rebuilding not required then just need to read in variable
@@ -452,22 +477,22 @@
                CASE( NF90_BYTE )
                   ALLOCATE(globaldata_4d_i1(indimlens(dimids(1)),indimlens(dimids(2)),       &
-                     &                      indimlens(dimids(3)),indimlens(dimids(4))))
-                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_i1 ) )
+                     &                      indimlens(dimids(3)),ntchunk))
+                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_i1, start=(/1,1,1,nt/) ) )
                CASE( NF90_SHORT )
                   ALLOCATE(globaldata_4d_i2(indimlens(dimids(1)),indimlens(dimids(2)),       &
-                     &                      indimlens(dimids(3)),indimlens(dimids(4))))
-                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_i2 ) )
+                     &                      indimlens(dimids(3)),ntchunk))
+                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_i2, start=(/1,1,1,nt/) ) )
                CASE( NF90_INT )
                   ALLOCATE(globaldata_4d_i4(indimlens(dimids(1)),indimlens(dimids(2)),       &
-                     &                      indimlens(dimids(3)),indimlens(dimids(4))))
-                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_i4 ) )
+                     &                      indimlens(dimids(3)),ntchunk))
+                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_i4, start=(/1,1,1,nt/) ) )
                CASE( NF90_FLOAT )
                   ALLOCATE(globaldata_4d_sp(indimlens(dimids(1)),indimlens(dimids(2)),       &
-                     &                      indimlens(dimids(3)),indimlens(dimids(4))))
-                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_sp ) )
+                     &                      indimlens(dimids(3)),ntchunk))
+                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_sp, start=(/1,1,1,nt/) ) )
                CASE( NF90_DOUBLE )
                   ALLOCATE(globaldata_4d_dp(indimlens(dimids(1)),indimlens(dimids(2)),       &
-                     &                      indimlens(dimids(3)),indimlens(dimids(4))))
-                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_dp ) )
+                     &                      indimlens(dimids(3)),ntchunk))
+                  CALL check_nf90( nf90_get_var( ncid, jv, globaldata_4d_dp, start=(/1,1,1,nt/) ) )
                CASE DEFAULT
                   WRITE(numerr,*) 'Unknown nf90 type: ', xtype
@@ -481,6 +506,10 @@
 !3.2.2 For variables that require rebuilding we need to read in from all ndomain files
 !      Here we allocate global variables ahead of looping over files
-         IF (l_verbose) WRITE(numout,*) 'Rebuilding data from variable '//TRIM(varname)//'...'
-
+         IF( nchunksize == nmax_unlimited .OR. ndims <= 3 ) THEN
+            IF (l_verbose) WRITE(numout,*) 'Rebuilding data from variable '//TRIM(varname)//'...'
+         ELSE
+            IF (l_verbose) WRITE(numout,'(A,I3,A,I3,A)') ' Rebuilding data from variable '  &
+            &                 //TRIM(varname)//' for chunks ',nt,' to ',nt+ntchunk-1,' ...'
+         ENDIF
          IF( ndims == 1 ) THEN
 
@@ -547,17 +576,17 @@
                CASE( NF90_BYTE )
                   ALLOCATE(globaldata_4d_i1(outdimlens(dimids(1)),outdimlens(dimids(2)),     &
-                     &                      outdimlens(dimids(3)),outdimlens(dimids(4))))
+                     &                      outdimlens(dimids(3)),ntchunk))
                CASE( NF90_SHORT )
                   ALLOCATE(globaldata_4d_i2(outdimlens(dimids(1)),outdimlens(dimids(2)),     &
-                     &                      outdimlens(dimids(3)),outdimlens(dimids(4))))
+                     &                      outdimlens(dimids(3)),ntchunk))
                CASE( NF90_INT )
                   ALLOCATE(globaldata_4d_i4(outdimlens(dimids(1)),outdimlens(dimids(2)),     &
-                     &                      outdimlens(dimids(3)),outdimlens(dimids(4))))
+                     &                      outdimlens(dimids(3)),ntchunk))
                CASE( NF90_FLOAT )
                   ALLOCATE(globaldata_4d_sp(outdimlens(dimids(1)),outdimlens(dimids(2)),     &
-                     &                      outdimlens(dimids(3)),outdimlens(dimids(4))))
+                     &                      outdimlens(dimids(3)),ntchunk))
                CASE( NF90_DOUBLE )
                   ALLOCATE(globaldata_4d_dp(outdimlens(dimids(1)),outdimlens(dimids(2)),     &
-                     &                      outdimlens(dimids(3)),outdimlens(dimids(4))))
+                     &                      outdimlens(dimids(3)),ntchunk))
                CASE DEFAULT
                   WRITE(numerr,*) 'Unknown nf90 type: ', xtype
@@ -584,5 +613,6 @@
 !$OMP&        globaldata_3d_i2,globaldata_3d_i4,globaldata_3d_sp,globaldata_3d_dp,        &
 !$OMP&        globaldata_4d_i2,globaldata_4d_i4,globaldata_4d_sp,globaldata_4d_dp,        &
-!$OMP&        globaldata_1d_i1,globaldata_2d_i1,globaldata_3d_i1,globaldata_4d_i1)
+!$OMP&        globaldata_1d_i1,globaldata_2d_i1,globaldata_3d_i1,globaldata_4d_i1,        &
+!$OMP&        ntchunk,nt,nmax_unlimited)
 
          DO ifile = 1, ndomain
@@ -811,9 +841,9 @@
                   CASE( NF90_BYTE )
                      ALLOCATE(localdata_4d_i1(local_sizes(di),local_sizes(dj),               &
-                         &                     indimlens(dimids(3)),indimlens(dimids(4))))
-                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_i1 ), istop )
+                         &                     indimlens(dimids(3)),ntchunk))
+                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_i1, start=(/1,1,1,nt/) ), istop )
 !$OMP  PARALLEL DEFAULT(NONE) PRIVATE(ji,jj,jk,jl)   &
-!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_i1,localdata_4d_i1,di,dj)
-                     DO jl = 1, indimlens(dimids(4))
+!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_i1,localdata_4d_i1,di,dj,nt,ntchunk)
+                     DO jl = 1, ntchunk
 !$OMP DO 
                         DO jk = 1, indimlens(dimids(3))
@@ -830,9 +860,9 @@
                   CASE( NF90_SHORT )
                      ALLOCATE(localdata_4d_i2(local_sizes(di),local_sizes(dj),               &
-                        &                     indimlens(dimids(3)),indimlens(dimids(4))))
-                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_i2 ), istop )
+                        &                     indimlens(dimids(3)),ntchunk))
+                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_i2, start=(/1,1,1,nt/) ), istop )
 !$OMP  PARALLEL DEFAULT(NONE) PRIVATE(ji,jj,jk,jl)   &
-!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_i2,localdata_4d_i2,di,dj)
-                     DO jl = 1, indimlens(dimids(4))
+!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_i2,localdata_4d_i2,di,dj,nt,ntchunk)
+                     DO jl = 1, ntchunk
 !$OMP DO 
                         DO jk = 1, indimlens(dimids(3))
@@ -849,9 +879,9 @@
                   CASE( NF90_INT )
                      ALLOCATE(localdata_4d_i4(local_sizes(di),local_sizes(dj),               &
-                        &                     indimlens(dimids(3)),indimlens(dimids(4))))
-                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_i4 ), istop )
+                        &                     indimlens(dimids(3)),ntchunk))
+                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_i4, start=(/1,1,1,nt/) ), istop )
 !$OMP  PARALLEL DEFAULT(NONE) PRIVATE(ji,jj,jk,jl)   &
-!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_i4,localdata_4d_i4,di,dj)
-                     DO jl = 1, indimlens(dimids(4))
+!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_i4,localdata_4d_i4,di,dj,nt,ntchunk)
+                     DO jl = 1, ntchunk
 !$OMP DO
                         DO jk = 1, indimlens(dimids(3))
@@ -868,9 +898,9 @@
                   CASE( NF90_FLOAT )
                      ALLOCATE(localdata_4d_sp(local_sizes(di),local_sizes(dj),               &
-                        &                     indimlens(dimids(3)),indimlens(dimids(4))))
-                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_sp ), istop )
+                        &                     indimlens(dimids(3)),ntchunk))
+                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_sp, start=(/1,1,1,nt/) ), istop )
 !$OMP  PARALLEL DEFAULT(NONE) PRIVATE(ji,jj,jk,jl)   &
-!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_sp,localdata_4d_sp,di,dj) 
-                     DO jl = 1, indimlens(dimids(4))
+!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_sp,localdata_4d_sp,di,dj,nt,ntchunk) 
+                     DO jl = 1, ntchunk
 !$OMP DO
                         DO jk = 1, indimlens(dimids(3))
@@ -887,9 +917,9 @@
                   CASE( NF90_DOUBLE )
                      ALLOCATE(localdata_4d_dp(local_sizes(di),local_sizes(dj),               &
-                        &                     indimlens(dimids(3)),indimlens(dimids(4))))
-                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_dp ), istop )
+                        &                     indimlens(dimids(3)),ntchunk))
+                     CALL check_nf90( nf90_get_var( ncid, jv, localdata_4d_dp, start=(/1,1,1,nt/) ), istop )
 !$OMP  PARALLEL DEFAULT(NONE) PRIVATE(ji,jj,jk,jl)   &
-!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_dp,localdata_4d_dp,di,dj) 
-                     DO jl = 1, indimlens(dimids(4))
+!$OMP& SHARED(idomain,jdomain,indimlens,dimids,start_pos,globaldata_4d_dp,localdata_4d_dp,di,dj,nt,ntchunk) 
+                     DO jl = 1, ntchunk
 !$OMP DO
                         DO jk = 1, indimlens(dimids(3))
@@ -1047,20 +1077,20 @@
     
       ELSEIF( ndims == 4 ) THEN
-      
+
          SELECT CASE( xtype )   
             CASE( NF90_BYTE )                   
-               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_i1 ) )
+               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_i1, start=(/1,1,1,nt/) ) )
                DEALLOCATE(globaldata_4d_i1)
             CASE( NF90_SHORT )                   
-               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_i2 ) )
+               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_i2, start=(/1,1,1,nt/) ) )
                DEALLOCATE(globaldata_4d_i2)
             CASE( NF90_INT )                              
-               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_i4 ) )
+               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_i4, start=(/1,1,1,nt/) ) )
                DEALLOCATE(globaldata_4d_i4)
             CASE( NF90_FLOAT )                              
-               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_sp ) )
+               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_sp, start=(/1,1,1,nt/) ) )
                DEALLOCATE(globaldata_4d_sp)
             CASE( NF90_DOUBLE )                                         
-               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_dp ) )
+               CALL check_nf90( nf90_put_var( outid, jv, globaldata_4d_dp, start=(/1,1,1,nt/) ) )
                DEALLOCATE(globaldata_4d_dp)
             CASE DEFAULT   
@@ -1070,4 +1100,8 @@
     
       ENDIF
+
+         nt = nt + ntchunk
+
+      END DO ! WHILE loop
     
    END DO  ! loop over variables
