[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[netCDF #AOX-617597]: 2D character string array (Fortran 90)
- Subject: [netCDF #AOX-617597]: 2D character string array (Fortran 90)
- Date: Tue, 19 May 2009 10:04:37 -0600
Ruslan,
> The array I'm trying to store to netCDF file is declared in Fortran as:
> character(35) :: array(700,100).
> What should it like in CDL syntax?
>
> I use pre-existing CDL file from which I generate netCDF file and
> where I write data to. I tried to use the following:
>
> netcdf test {
> dimensions:
> Dim1 = 700 ;
> Dim2 = 100 ;
> Dim3 = 20 ;
> variables:
> char Var1(Dim1, Dim3, Dim2) ;
> data: .
>
> and:
> status=NF_PUT_VARA_TEXT(ncid,var_id,(/1,1,1/),(/700,20,100/),array)
>
> But data section looks messy (multiple '\000' symbols instead of data).
> If I don't include Dim3 it stores only first letter of each array element.
The CDL dimension order is the C order, in which the last dimension
varies fastest and the first dimension variews most slowly. In
Fortran uses the opposite order, in which the first dimension varies
fastes and the last most slowly.
So for a Fortran array declared like:
character(35) :: array(700,100)
and assuming you only want 20 characters in the netCDF file rather
than the 35 character length you have in your program, the
corresponding CDL would be
netcdf test {
dimensions:
Dim1 = 100 ;
Dim2 = 700 ;
Dim3 = 20 ;
variables:
char Var1(Dim1, Dim2, Dim3) ;
data:
...
}
If you made Dim3=35 to match your in-memory character string length,
the NF_PUT_VARA_TEXT call would be pretty easy:
status=NF_PUT_VARA_TEXT(ncid,var_id,(/1,1,1/),(/35,700,100/),array)
but apparently you only want to write the subarray of the first 20
characters of each string into the netCDF file, skipping over the last
15 characters for each array value. That makes it trickier, and you
have to instead use the NF_PUT_VARM_TEXT call, providing more
arguments to tell how much to skip along each in-memory dimension to
get to the next element along that dimension:
status = nf_put_varm_text(ncid, var_id, (/1,1,1/), (/35,700,100/),
* (/1,1,1/), (/1,35,35*700/), array)
I've appended a small F77 example program illustrating this with a
3x2x20 array instead of your 700x100x20 array. It creates a netCDF
file that has strings of length 20 and also shows that a string of
length 35 gets truncated when written in the file. You should be able
to modify this example to get it working the way you want.
When I compile and run the program, it creates a netCDF file that
looks like this in ncdump:
netcdf test {
dimensions:
Dim1 = 3 ;
Dim2 = 2 ;
Dim3 = 20 ;
variables:
char Var1(Dim1, Dim2, Dim3) ;
data:
Var1 =
"string A, length 20.",
"string B, length 20.",
"string C, length 20.",
"string D, length 20.",
"string E, length 20.",
"Here is F string 35 " ;
}
--Russ
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
program chartst
include 'netcdf.inc'
integer ncid, var1id, dim1id, dim2id, dim3id
integer ndims
parameter(NDIMS = 3)
parameter(LEN1 = 3, LEN2 = 2, LEN3 = 20)
integer dimids(NDIMS), start(NDIMS), count(NDIMS)
integer stride(NDIMS), amap(NDIMS)
integer status
character*35 :: array(LEN1,LEN2)
data array /
* "string A, length 20.",
* "string B, length 20.",
* "string C, length 20.",
* "string D, length 20.",
* "string E, length 20.",
* "Here is F string 35 characters long"
* /
status = nf_create('test.nc', nf_clobber, ncid)
if(status .ne. nf_noerr) then
print *, nf_strerror(status)
stop 1
endif
status = nf_def_dim(ncid, 'Dim1', LEN1, dim1id)
if(status .ne. nf_noerr) then
print *, nf_strerror(status)
stop 1
endif
status = nf_def_dim(ncid, 'Dim2', LEN2, dim2id)
if(status .ne. nf_noerr) then
print *, nf_strerror(status)
stop 1
endif
status = nf_def_dim(ncid, 'Dim3', LEN3, dim3id)
if(status .ne. nf_noerr) then
print *, nf_strerror(status)
stop 1
endif
dimids(1) = dim3id
dimids(2) = dim2id
dimids(3) = dim1id
status = nf_def_var(ncid, 'Var1', nf_char, NDIMS, dimids, var1id)
if(status .ne. nf_noerr) then
print *, nf_strerror(status)
stop 1
endif
status = nf_enddef(ncid)
if(status .ne. nf_noerr) then
print *, nf_strerror(status)
stop 1
endif
start(1) = 1
start(2) = 1
start(3) = 1
count(1) = LEN3
count(2) = LEN2
count(3) = LEN1
stride(1) = 1
stride(2) = 1
stride(3) = 1
amap(1) = 1
amap(2) = 35
amap(3) = 35*LEN2
c status = nf_put_vara_text(ncid, var1id, start, count, array)
c if(status .ne. nf_noerr) then
c print *, nf_strerror(status)
c stop 1
c endif
status = nf_put_varm_text(ncid, var1id, start, count,
* stride, amap, array)
if(status .ne. nf_noerr) then
print *, nf_strerror(status)
stop 1
endif
status = nf_close(ncid)
if(status .ne. nf_noerr) then
print *, nf_strerror(status)
stop 1
endif
end