This archive contains answers to questions sent to Unidata support through mid-2025. Note that the archive is no longer being updated. We provide the archive for reference; many of the answers presented here remain technically correct, even if somewhat outdated. For the most up-to-date information on the use of NSF Unidata software and data services, please consult the Software Documentation first.
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