lfi2cdf: new option: '-m or --merge' to merge LFI splitted files
authorPhilippe WAUTELET <philippe.wautelet@aero.obs-mip.fr>
Thu, 17 Sep 2015 15:36:38 +0000 (17:36 +0200)
committerPhilippe WAUTELET <philippe.wautelet@aero.obs-mip.fr>
Mon, 2 May 2016 10:23:53 +0000 (12:23 +0200)
tools/lfi2cdf/src/lfi2cdf.f90
tools/lfi2cdf/src/mode_util.f90
tools/lfi2cdf/src/newmain.c

index cd16876..bd1342d 100644 (file)
@@ -1,18 +1,29 @@
-subroutine  LFI2CDFMAIN(hinfile,iiflen,houtfile,ioflen,hvarlist,ivlen,olfi2cdf,olfilist,ohdf5)
+subroutine  LFI2CDFMAIN(hinfile,iiflen,ooutname,houtfile,ioflen,hvarlist,ivlen,olfi2cdf,olfilist,ohdf5,omerge,nb_levels)
   USE mode_util
   IMPLICIT NONE 
   INTEGER :: iiflen, ioflen, ivlen
+  INTEGER :: nb_levels !Number of vertical levels to merge (for LFI splitted files)
   CHARACTER(LEN=iiflen) :: hinfile
   CHARACTER(LEN=ioflen) :: houtfile
   CHARACTER(LEN=ivlen)  :: hvarlist
-  LOGICAL :: olfi2cdf, olfilist, ohdf5
+  LOGICAL :: ooutname, olfi2cdf, olfilist, ohdf5, omerge
   
   INTEGER :: ibuflen
   INTEGER :: ilu
   INTEGER :: inaf, ji
+  INTEGER :: nbvar_lfi  ! number of variables available in the LFI file
   INTEGER :: icdf_id
+  INTEGER :: first_level, current_level, last_level
+  INTEGER(KIND=LFI_INT) :: iresp,iverb,inap
+  CHARACTER(LEN=3)      :: suffix
+  CHARACTER(LEN=iiflen) :: filename
   TYPE(workfield), DIMENSION(:), POINTER :: tzreclist
 
+  !Remove level in the filename if merging LFI splitted files
+  if (omerge .AND. .NOT.ooutname) then
+       houtfile=houtfile(1:len(houtfile)-9)//houtfile(len(houtfile)-3:)
+  end if
+
   CALL OPEN_FILES(hinfile, houtfile, olfi2cdf, olfilist, ohdf5, icdf_id, ilu, inaf)
   IF (olfilist) return
 
@@ -29,9 +40,36 @@ subroutine  LFI2CDFMAIN(hinfile,iiflen,houtfile,ioflen,hvarlist,ivlen,olfi2cdf,o
         END DO
      END IF
      
-     CALL parse_lfi(ilu,hvarlist,inaf,tzreclist,ibuflen)
-     CALL def_ncdf(tzreclist,inaf,icdf_id)
-     CALL fill_ncdf(ilu,icdf_id,tzreclist,inaf,ibuflen)
+     !Standard treatment (one LFI file only)
+     IF (.not.omerge) THEN
+       CALL parse_lfi(ilu,hvarlist,inaf,tzreclist,ibuflen)
+       CALL def_ncdf(tzreclist,inaf,icdf_id,omerge)
+       CALL fill_ncdf(ilu,icdf_id,tzreclist,inaf,ibuflen)
+     ELSE
+     !Treat several LFI files and merge into 1 NC file
+       iverb = 0 !Verbosity level for LFI
+
+       !Determine first level (eg needed to find suffix of the variable name)
+       read( hinfile(len(hinfile)-6:len(hinfile)-4) , "(I3)" ) first_level
+       current_level = first_level
+       last_level    = first_level + nb_levels - 1
+
+       !Read 1st LFI file
+       CALL parse_lfi(ilu,hvarlist,inaf,tzreclist,ibuflen,current_level)
+       CALL def_ncdf(tzreclist,inaf,icdf_id,omerge)
+
+       DO current_level = first_level,last_level
+         print *,'Treating level ',current_level
+         IF (current_level/=first_level) THEN
+           write(suffix,'(I3.3)') current_level
+           filename=hinfile(1:len(hinfile)-7)//suffix//'.lfi'
+           CALL LFIOUV(iresp,ilu,ltrue,filename,'OLD',lfalse,lfalse,iverb,inap,nbvar_lfi)
+           CALL read_data_lfi(ilu,hvarlist,inaf,tzreclist,ibuflen,current_level)
+         END IF
+         CALL fill_ncdf(ilu,icdf_id,tzreclist,inaf,ibuflen,current_level)
+         IF (current_level/=last_level) CALL LFIFER(iresp,ilu,'KEEP')
+       END DO
+     END IF
 
   ELSE
      ! Conversion NetCDF -> LFI
index b5780e8..5deedbc 100644 (file)
@@ -65,12 +65,13 @@ CONTAINS
   END IF
   END SUBROUTINE FMREADLFIN1
 
-  SUBROUTINE parse_lfi(klu, hvarlist, knaf, tpreclist, kbuflen)
+  SUBROUTINE parse_lfi(klu, hvarlist, knaf, tpreclist, kbuflen, current_level)
     INTEGER, INTENT(IN)                    :: klu
     INTEGER, INTENT(INOUT)                 :: knaf
     CHARACTER(LEN=*), intent(IN)           :: hvarlist
     TYPE(workfield), DIMENSION(:), POINTER :: tpreclist    
     INTEGER, INTENT(OUT)                   :: kbuflen
+    INTEGER, INTENT(IN), OPTIONAL          :: current_level
 
     INTEGER                                  :: ji,jj
     INTEGER                                  :: ndb, nde
@@ -79,6 +80,7 @@ CONTAINS
     INTEGER                                  :: ich
     INTEGER                                  :: fsize,sizemax
     CHARACTER(LEN=FM_FIELD_SIZE)             :: yrecfm
+    CHARACTER(LEN=4)                         :: suffix
 #ifdef LOWMEM
     INTEGER(KIND=8),DIMENSION(:),ALLOCATABLE :: iwork
 #endif
@@ -116,6 +118,12 @@ CONTAINS
     ALLOCATE(tpreclist(knaf))
     sizemax = 0
 
+    IF (present(current_level)) THEN
+      write(suffix,'(I4.4)') current_level
+    ElSE
+      suffix=''
+    END IF
+
     ! Phase 1 : build articles list to convert.
     !
     !    Pour l'instant tous les articles du fichier LFI sont
@@ -132,7 +140,7 @@ CONTAINS
           yrecfm = hvarlist(ndb:ndb+nde-2)
           ndb = nde+ndb
 
-          CALL LFINFO(iresp,ilu,yrecfm,ileng,ipos)
+          CALL LFINFO(iresp,ilu,trim(yrecfm)//trim(suffix),ileng,ipos)
           
           IF (iresp /= 0 .OR. ileng == 0) THEN
              PRINT *,'Article ',TRIM(yrecfm), ' not found!'
@@ -173,7 +181,7 @@ CONTAINS
     !           Infos are put in tpreclist.
     CALL init_dimCDF()
     DO ji=1,inaf
-       yrecfm = tpreclist(ji)%name
+       yrecfm = trim(tpreclist(ji)%name)//trim(suffix)
        CALL LFINFO(iresp,ilu,yrecfm,ileng,ipos)
 #ifdef LOWMEM
        CALL LFILEC(iresp,ilu,yrecfm,iwork,ileng)
@@ -208,6 +216,55 @@ CONTAINS
     knaf = inaf
   END SUBROUTINE parse_lfi
   
+  SUBROUTINE read_data_lfi(klu, hvarlist, nbvar, tpreclist, kbuflen, current_level)
+    INTEGER, INTENT(IN)                    :: klu
+    INTEGER, INTENT(INOUT)                 :: nbvar
+    CHARACTER(LEN=*), intent(IN)           :: hvarlist
+    TYPE(workfield), DIMENSION(:), POINTER :: tpreclist
+    INTEGER, INTENT(IN)                    :: kbuflen
+    INTEGER, INTENT(IN), OPTIONAL          :: current_level
+
+    INTEGER                                  :: ji,jj
+    INTEGER                                  :: ndb, nde
+    LOGICAL                                  :: ladvan
+    INTEGER                                  :: ich
+    INTEGER                                  :: fsize,sizemax
+    CHARACTER(LEN=FM_FIELD_SIZE)             :: yrecfm
+    CHARACTER(LEN=4)                         :: suffix
+#ifdef LOWMEM
+    INTEGER(KIND=8),DIMENSION(:),ALLOCATABLE :: iwork
+#endif
+    INTEGER(KIND=LFI_INT)                    :: iresp,ilu,ileng,ipos
+
+    ilu = klu
+
+    IF (present(current_level)) THEN
+      write(suffix,'(I4.4)') current_level
+    ElSE
+      suffix=''
+    END IF
+
+#ifdef LOWMEM
+    ALLOCATE(iwork(kbuflen))
+#endif
+
+    DO ji=1,nbvar
+       yrecfm = trim(tpreclist(ji)%name)//trim(suffix)
+       CALL LFINFO(iresp,ilu,yrecfm,ileng,ipos)
+#ifdef LOWMEM
+       CALL LFILEC(iresp,ilu,yrecfm,iwork,ileng)
+       tpreclist(ji)%grid = iwork(1)
+#else
+       CALL LFILEC(iresp,ilu,yrecfm,lfiart(ji)%iwtab,ileng)
+       tpreclist(ji)%grid = lfiart(ji)%iwtab(1)
+#endif
+    END DO
+
+#ifdef LOWMEM
+    DEALLOCATE(iwork)
+#endif
+  END SUBROUTINE read_data_lfi
+
   SUBROUTINE HANDLE_ERR(status,line)
     INTEGER :: status,line
 
@@ -217,10 +274,11 @@ CONTAINS
     END IF
   END SUBROUTINE HANDLE_ERR
 
-  SUBROUTINE def_ncdf(tpreclist,knaf,kcdf_id)
+  SUBROUTINE def_ncdf(tpreclist,knaf,kcdf_id,omerge)
     TYPE(workfield),DIMENSION(:),INTENT(INOUT) :: tpreclist
     INTEGER,                     INTENT(IN) :: knaf
     INTEGER,                     INTENT(OUT):: kcdf_id
+    LOGICAL,                     INTENT(IN) :: omerge
 
     INTEGER :: status
     INTEGER :: ji
@@ -255,6 +313,7 @@ CONTAINS
            ivdims(1) = tpreclist(ji)%dim%id
          ELSE
            invdims = tpreclist(ji)%dim%ndims
+           IF(omerge) invdims=invdims+1 !when merging variables from LFI splitted files
            SELECT CASE(invdims)
            CASE(2)
               ivdims(1)=ptdimx%id
@@ -332,26 +391,40 @@ CONTAINS
     
   END SUBROUTINE def_ncdf
 
-  SUBROUTINE fill_ncdf(klu,kcdf_id,tpreclist,knaf,kbuflen)
+  SUBROUTINE fill_ncdf(klu,kcdf_id,tpreclist,knaf,kbuflen,current_level)
     INTEGER,                      INTENT(IN):: klu
     INTEGER,                      INTENT(IN):: kcdf_id
     TYPE(workfield), DIMENSION(:),INTENT(IN):: tpreclist
     INTEGER,                      INTENT(IN):: knaf
     INTEGER,                      INTENT(IN):: kbuflen
+    INTEGER, INTENT(IN), OPTIONAL           :: current_level
+
 #ifdef LOWMEM
     INTEGER(KIND=8),DIMENSION(:),ALLOCATABLE :: iwork
 #endif
     INTEGER                                  :: ji,jj
-    INTEGER,DIMENSION(:),ALLOCATABLE :: itab
+    INTEGER,DIMENSION(:),ALLOCATABLE         :: itab
     REAL   (KIND=8),DIMENSION(:),ALLOCATABLE :: xtab
     CHARACTER, DIMENSION(:), ALLOCATABLE     :: ytab
     INTEGER                                  :: status
     INTEGER                                  :: extent, ndims
     INTEGER                                  :: ich
-    INTEGER(KIND=LFI_INT) :: iresp,ilu,ileng,ipos
+    INTEGER                                  :: level
+    INTEGER(KIND=LFI_INT)                    :: iresp,ilu,ileng,ipos
+    CHARACTER(LEN=4)                         :: suffix
+
     !
     ilu = klu
     !
+
+    IF (present(current_level)) THEN
+      write(suffix,'(I4.4)') current_level
+      level = current_level
+    ElSE
+      suffix=''
+      level = 1
+    END IF
+
 #if LOWMEM
     ALLOCATE(iwork(kbuflen))
 #endif
@@ -360,8 +433,8 @@ CONTAINS
 
     DO ji=1,knaf
 #if LOWMEM
-       CALL LFINFO(iresp,ilu,tpreclist(ji)%name,ileng,ipos)
-       CALL LFILEC(iresp,ilu,tpreclist(ji)%name,iwork,ileng)
+       CALL LFINFO(iresp,ilu,trim(tpreclist(ji)%name)//trim(suffix),ileng,ipos)
+       CALL LFILEC(iresp,ilu,trim(tpreclist(ji)%name)//trim(suffix),iwork,ileng)
 #endif
        IF (ASSOCIATED(tpreclist(ji)%dim)) THEN
           extent = tpreclist(ji)%dim%len
@@ -387,7 +460,8 @@ print *,'lowmem: not tested!!!!!' (to be compared with no low mem version)
          CASE (1)
            status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,itab(1:extent),count=(/extent/))
          CASE (2)
-           status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,reshape(itab,(/ptdimx%len,ptdimy%len/)))
+           status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,reshape(itab,(/ptdimx%len,ptdimy%len/)), &
+                                 start = (/1,1,level/) )
          CASE (3)
            status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,reshape(itab,(/ptdimx%len,ptdimy%len,ptdimz%len/)))
          CASE DEFAULT
@@ -409,7 +483,8 @@ print *,'lowmem: not tested!!!!!' (to be compared with no low mem version)
          CASE (1)
            status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,xtab(1:extent),count=(/extent/))
          CASE (2)
-           status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,reshape(xtab,(/ptdimx%len,ptdimy%len/)))
+           status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,reshape(xtab,(/ptdimx%len,ptdimy%len/)), &
+                                 start = (/1,1,level/) )
          CASE (3)
            status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,reshape(xtab,(/ptdimx%len,ptdimy%len,ptdimz%len/)))
          CASE DEFAULT
@@ -446,7 +521,8 @@ print *,'lowmem: not tested!!!!!' (to be compared with no low mem version)
          CASE (1)
            status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,xtab(1:extent),count=(/extent/))
          CASE (2)
-           status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,reshape(xtab,(/ptdimx%len,ptdimy%len/)))
+           status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,reshape(xtab,(/ptdimx%len,ptdimy%len/)), &
+                                 start = (/1,1,level/) )
          CASE (3)
            status = NF90_PUT_VAR(kcdf_id,tpreclist(ji)%id,reshape(xtab,(/ptdimx%len,ptdimy%len,ptdimz%len/)))
          CASE DEFAULT
index 05b93ad..8b6b9b9 100644 (file)
@@ -5,7 +5,7 @@
 
 #define BUFSIZE 4096
 
-extern lfi2cdfmain_(char*, int*, char*, int*, char*, int*, int*, int*, int*);
+extern lfi2cdfmain_(char*, int*, int *, char*, int*, char*, int*, int*, int*, int*, int*, int*);
 
 char *cleancomma(char *varlist)
 {
@@ -30,6 +30,8 @@ int main(int argc, char **argv)
   int list_flag;
   int l2c_flag;
   int hdf5_flag;
+  int merge_flag, nb_levels;
+  int outname_flag;
   char *cmd, *infile;
   int c;
   char buff[BUFSIZE];
@@ -52,17 +54,23 @@ int main(int argc, char **argv)
   p = buff;
   *p = '\0';
 
+  /* Default values for merging of LFI splitted files */
+  merge_flag = 0;
+  nb_levels = 1;
+
   while (1) {
     int option_index = 0;
 
     static struct option long_options[] = {
-      {"cdf4",    no_argument,       0,  '4'},
-      {"list",  no_argument,       0,  'l' },
-      {"var",   required_argument, 0,  'v' },
-      {0,         0,                 0,  0 }
+      {"cdf4",             no_argument,       0, '4' },
+      {"list",             no_argument,       0, 'l' },
+      {"merge",            required_argument, 0, 'm' },
+      {"output",           required_argument, 0, 'o' },
+      {"var",              required_argument, 0, 'v' },
+      {0,                  0,                 0,  0  }
     };
 
-    c = getopt_long(argc, argv, "lo:v:4",
+    c = getopt_long(argc, argv, "4lm:o:v:",
                    long_options, &option_index);
     if (c == -1)
       break;
@@ -80,7 +88,12 @@ int main(int argc, char **argv)
     case 'l':
       list_flag = 1;
       break;
+    case 'm':
+      merge_flag = 1;
+      nb_levels = atoi(optarg);
+      break;
     case 'o':
+      outname_flag = 1;
       outfile = optarg;
       olen = strlen(outfile);
       break;
@@ -105,8 +118,8 @@ int main(int argc, char **argv)
   }
 
   if (optind == argc) {
-    printf("usage : lfi2cdf [--cdf4 -4] [-l] [-v var1[,...]] [-o output-file.nc] input-file.lfi\n");
-    printf("        cdf2lfi [-o output-file.lfi] input-file.nc\n");
+    printf("usage : lfi2cdf [--cdf4 -4] [-l] [-v --var var1[,...]] [-m --merge number_of_z_levels] [-o --output output-file.nc] input-file.lfi\n");
+    printf("        cdf2lfi [-o --output output-file.lfi] input-file.nc\n");
     exit(EXIT_FAILURE);
   } 
 
@@ -142,7 +155,8 @@ int main(int argc, char **argv)
          infile, ilen, outfile, olen, varlist, varlistlen);
   */
 
-  lfi2cdfmain_(infile, &ilen, outfile, &olen, varlist, &varlistlen, &l2c_flag, &list_flag, &hdf5_flag);
+  lfi2cdfmain_(infile, &ilen, &outname_flag, outfile, &olen, varlist, &varlistlen, &l2c_flag, &list_flag, &hdf5_flag, &merge_flag,
+                      &nb_levels);
 
   exit(EXIT_SUCCESS);
 }