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

[netCDF #OPV-437501]: Reading 2D array in C, into array of pointers



Hi Tiago,

Sorry to have taken so long to respond to your question ...

> I am a great fan of NetCDF and used it extensively with the Fortran and
> Python interfaces, but now I must work with it in C. (This question may
> be related to my ignorance in C.)

The main difference is that Fortran uses column-major ordering (first
inde3x varies fastest), but C uses row-major (last index varies
fastest).

> I have a NetCDF file with a 4D variable. I would like to read a 2D slice
> of that variable into a (double **) array, called 'mm' and defined as:
> 
> m = (double *) calloc(N * M, typeSize);
> mm = (double **) malloc(N* pointerSize);
> 
> for(i=0; i< N; i++, mm += M)
> mm[i] = m;
> 
> I know I can't read a 2D slice into it all at once because it is not
> contiguous.

It looks like it *is* contiguous, because you have allocated all N*M
doubles with a single call to calloc().  Then you have made m[1] point
to the ith row of doubles, but if you print out check the addresses,
you should be able to verify that mm[1][0] is the next double in
memory after mm[0][M-1], and in general the double mm[j+1][0]
immediately follows mm[j][M-1] in memory for any j in {0, 1, ...,
N-1}.

So you should be able to read a 2D slice into m, which is the same
as &m[0], which is the same as &mm[0][0].

>  ... So I'm trying to read one column at once with nc_get_vara:
> 
> 
> for (i=0, i<N, i++){
> nc_get_vara_double(ncid,varid,start,count,mm[i]);
> start[0]++;
> }

I assume you have declared start and count as arrays of size 4
(because you are reading a 4D netCDF variable).  I also assume you
have set 
  count[0] = M;
  count[1] = count[2] = count[3] = 1;
and that the netCDF variable you are trying to read would have a CDL
declaration something like
  double var(N, M, P, R);
with N and M the first two dimensions, used for "row" and "column".
If that's true, then the code above should read M values into the ith
row of the mm array, each time it's called.

> This compiles and when running it reads the first element of each row
> (i.e. mm[*][0]), but seems to put rubbish in all the other elements,
> which give a segfault when I try to access them. How do I read a 2D
> slice into a (double **) variable? I thought this would work as mm[i]
> is a pointer to a (double *) array. In the call to nc_get_vara_double
> I also tried putting &mm[i][0], but the result is the same...

If the assumptions I've spelled out above are correct, then this
should have worked, so I assume something is different, such as the
values of count.

> I can read the array using the uglier method of nc_get_var1_double in
> a M,N loop, but was looking for something more elegant and with less
> overhead.

Just reading in the whole 2D slice should be possible and is the most
elegant.  You shouldn't have to read in each element separately!

--Russ

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



Ticket Details
===================
Ticket ID: OPV-437501
Department: Support netCDF
Priority: Normal
Status: Closed