[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[netCDF #AOX-617597]: 2D character string array (Fortran 90)



Ruslan,

> Could you explain the same for f77 interface (NF_PUT_VAR_TEXT,
> NF_PUT_VARA_TEXT).  Some people are still using it.  I'm just
> guessing if 1D array should be treated as 2D array where the second
> dimension is the length of character string should the same logic be
> applied to 2D array?

No, actually all that matters is that the characters are contiguous in
memory.  Before presenting an F77 example, here's the f90 example
with a third variable for which a 2D array is output:

-------------------------

program chartst
use netcdf
integer :: ncid, var1id, var2id, var3id, dim1id, dim2id
character (len = 1), dimension (15) :: ch = (/'a', 'b', 'c', 'd', 'e', &
                                              'f', 'g', 'h', 'i', 'j', &
                                              'k', 'l', 'm', 'n', 'o' /)
character (len = 15) :: ch15 = "abcdefghijklmno"
character (len = 5), dimension(3) :: ch5 = (/"abcde","fghij","klmno" /)

call check(nf90_create('CharTest.nc', nf90_clobber, ncid))
call check(nf90_def_dim(ncid, 'Dim1', 5, dim1id))
call check(nf90_def_dim(ncid, 'Dim2', 3, dim2id))
call check(nf90_def_var(ncid, 'Var1', nf90_char, (/dim1id, dim2id/), var1id))
call check(nf90_def_var(ncid, 'Var2', nf90_char, (/dim2id, dim1id/), var2id))
call check(nf90_def_var(ncid, 'Var3', nf90_char, (/dim1id, dim2id/), var3id))
call check(nf90_enddef(ncid))

call check(nf90_put_var(ncid, var1id, ch, start=(/ 1, 1/), count=(/ 5, 3 /)))
call check(nf90_put_var(ncid, var2id, ch15, start=(/ 1, 1/), count=(/ 3, 5 /)))
call check(nf90_put_var(ncid, var3id, ch5, start=(/ 1, 1/), count=(/ 5, 3 /)))
call check(nf90_close(ncid))

contains
  subroutine check(status)
    integer, intent ( in) :: status
    
    if(status /= nf90_noerr) then 
      print *, trim(nf90_strerror(status))
      stop 2
    end if
  end subroutine check  
end program chartst
-------------------------
The ncdump output from the resulting file looks like this:

$ ncdump CharTest.nc
netcdf CharTest {
dimensions:
        Dim1 = 5 ;
        Dim2 = 3 ;
variables:
        char Var1(Dim2, Dim1) ;
        char Var2(Dim1, Dim2) ;
        char Var3(Dim2, Dim1) ;
data:

 Var1 =
  "abcde",
  "fghij",
  "klmno" ;

 Var2 =
  "abc",
  "def",
  "ghi",
  "jkl",
  "mno" ;

 Var3 =
  "abcde",
  "fghij",
  "klmno" ;
}

Here's an F77 example of the same program:
-------------------------
      program chartst
      include 'netcdf.inc'
      integer ncid, var1id, var2id, var3id, dim1id, dim2id
      integer ndims
      parameter(NDIMS = 2)
      integer dimids(NDIMS), start(NDIMS), count(NDIMS)
      character*1 ch(15)
      data ch /"a","b","c","d","e","f","g","h","i","j","k","l","m","n"
     $     ,"o"/

      character*15 ch15
      data ch15 /"abcdefghijklmno"/
      character*5 ch5(3)
      data ch5 /"abcde","fghij","klmno"/
      integer status

      status = nf_create('CharTest.nc', nf_clobber, ncid)
                        if(status .ne. nf_noerr) stop 1
      status = nf_def_dim(ncid, 'Dim1', 5, dim1id)
                        if(status .ne. nf_noerr) stop 1
      status = nf_def_dim(ncid, 'Dim2', 3, dim2id)
                        if(status .ne. nf_noerr) stop 1
      dimids(1) = dim1id
      dimids(2) = dim2id
      status = nf_def_var(ncid, 'Var1', nf_char, NDIMS, dimids, var1id)
                        if(status .ne. nf_noerr) stop 1
      dimids(1) = dim2id
      dimids(2) = dim1id
      status = nf_def_var(ncid, 'Var2', nf_char, NDIMS, dimids, var2id)
                        if(status .ne. nf_noerr) stop 1
      dimids(1) = dim1id
      dimids(2) = dim2id
      status = nf_def_var(ncid, 'Var3', nf_char, NDIMS, dimids, var3id)
                        if(status .ne. nf_noerr) stop 1
      status = nf_enddef(ncid)
                        if(status .ne. nf_noerr) stop 1

      start(1) = 1
      start(2) = 1
      count(1) = 5
      count(2) = 3
      status = nf_put_vara_text(ncid, var1id, start, count, ch)
                        if(status .ne. nf_noerr) stop 1
      count(1) = 3
      count(2) = 5
      status = nf_put_vara_text(ncid, var2id, start, count, ch15)
                        if(status .ne. nf_noerr) stop 1
      count(1) = 5
      count(2) = 3
      status = nf_put_vara_text(ncid, var3id, start, count, ch5)
                        if(status .ne. nf_noerr) stop 1
      status = nf_close(ncid)
                        if(status .ne. nf_noerr) stop 1
      end
-------------------------

which produces an identical CharTest.nc file as the f90 example above.

> Should it be treated as 3D array where one of dimensions is the
> length of character string?

As you can see from the examples above, you may treat it that way or
not, since the Fortran function doesn't know the shape of the array it
gets passed.

> --- On Fri, 8/5/09, Unidata netCDF Support <address@hidden> wrote:
> 
> 
> From: Unidata netCDF Support <address@hidden>
> Subject: [netCDF #AOX-617597]: 2D character string array (Fortran 90)
> To: support-netcdf
> Cc: address@hidden
> Received: Friday, 8 May, 2009, 2:18 AM
> 
> 
> Hi Ruslan,
> 
> > I've got an issue with writing (and reading) 2-dimensional character
> > string arrays in Fortran 90.  I found an example how to do it in
> > java but it's not quite helpful because the language concept is
> > different.  Could you provide me with the example for Fortran 90,
> > please?
> 
> Sure, it looks like our documentation is really lacking in examples of
> writing character data using the f90 interface.  I'll put the example
> inline rather than as an attachment, so it can be found more easily by
> others searching for such examples in the future.
> 
> ----------------------------------
> program chartst
> use netcdf
> 
> integer :: ncid, var1id, var2id, dim1id, dim2id;
> character (len = 1), dimension (15) :: ch = (/'a', 'b', 'c', 'd', 'e', &
>                                               'f', 'g', 'h', 'i', 'j', &
>                                               'k', 'l', 'm', 'n', 'o' /)
> character (len = 15) :: ch15 = "abcdefghijklmno";
> 
> print *, 'Start: ', ch
> call check(nf90_create('CharTest.nc', nf90_clobber, ncid))
> call check(nf90_def_dim(ncid, 'Dim1', 5, dim1id))
> call check(nf90_def_dim(ncid, 'Dim2', 3, dim2id))
> call check(nf90_def_var(ncid, 'Var1', nf90_char, (/dim1id, dim2id/), var1id))
> call check(nf90_def_var(ncid, 'Var2', nf90_char, (/dim2id, dim1id/), var2id))
> call check(nf90_enddef(ncid))
> 
> call check(nf90_put_var(ncid, var1id, ch, start=(/ 1, 1/), count=(/ 5, 3 /)))
> call check(nf90_put_var(ncid, var2id, ch15, start=(/ 1, 1/), count=(/ 3, 5 
> /)))
> call check(nf90_close(ncid))
> print *, 'End: ', dims
> 
> contains
>   subroutine check(status)
>     integer, intent ( in) :: status
>    
>     if(status /= nf90_noerr) then
>       print *, trim(nf90_strerror(status))
>       stop 2
>     end if
>   end subroutine check 
> end program chartst
> ----------------------------------
> 
> When you compile and run the program above, it creates CharTest.nc.
> Here's the result of running "ncdump CharTest.nc":
> 
> $ ncdump CharTest.nc
> netcdf CharTest {
> dimensions:
>     Dim1 = 5 ;
>     Dim2 = 3 ;
> variables:
>     char Var1(Dim2, Dim1) ;
>     char Var2(Dim1, Dim2) ;
> data:
> 
> Var1 =
>   "abcde",
>   "fghij",
>   "klmno" ;
> 
> Var2 =
>   "abc",
>   "def",
>   "ghi",
>   "jkl",
>   "mno" ;
> }

Russ Rew                                         UCAR Unidata Program
address@hidden                     http://www.unidata.ucar.edu



Ticket Details
===================
Ticket ID: AOX-617597
Department: Support netCDF
Priority: Normal
Status: Closed