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

Re: 20020909: Need Help with Compilation



>To: address@hidden
>cc: address@hidden
>From: David Han <address@hidden>
>Subject: Need Help with Compilation
>Organization: NASA/GSFC
>Keywords: 200209091724.g89HOSj19603

Hi David,

> Below is my test program which has a compilation problem on the following 
> line:
> 
>    status = nc_put_var_double(ncid, my3d_id, my3d_data);
> 
> Can you tell me why this is a problem?  Thanks for your help.

[Note added later: parts of this answer are wrong.  These are marked
with the tags <WRONG> ... </WRONG> below.  A more detailed explanation
appears at the end of the reply.]

Yes, there are two problems with the above statement: first you need to
give the address of the first element of the array instead of the name
of the array <WRONG>(in C these are not the same for multidimensional arrays
with more than 1 dimension)</WRONG> and second you are writing a record
variable, so you need to use the interface that lets you specify how
many records to write.

Just fixing the first problem would change the statement to the following:

    status = nc_put_var_double(ncid, my3d_id, &my3d_data[0][0][0]);

That will compile without error, but it won't work as you intend,
because the nc_put_var_double() interface is for writing a whole array
at once, where the size of the array is determined by how large it is
in the netCDF file on disk.  Since this is a record variable (uses the
NC_UNLIMITED dimension) and there are no records on disk yet, the
size of the array on disk is 0x5x10, so no data will be written.  You
need to use the interface that permits you to say how many records
will be written.  If you want to write 3 records at once, you would
use the nc_put_vara_double interface:

  
http://www.unidata.ucar.edu/packages/netcdf/guidec/guidec-12.html#HEADING12-480

providing a start array specifying the starting indices and a count
array specifying how far along each dimension you want to write:

   static size_t start[] = {0, 0, 0};
   static size_t count[] = {TIMES, LATS, LONS};
 ...
   status = nc_put_vara_double(ncid, rh_id, start, count, &my3d_data[0][0][0]);

> It seems that the only way to make a scalar variable is to create a 
> 1-D variable with one element in it.  Is this correct?

No, you make a scalar variable by specifying a rank of 0 when you
create it.  That's not the same as a 1-D variable with 1 element
(which has a rank of 1).  For example, here's code to create a scalar
variable:

   int scalar_id;
 ...
   status = nc_def_var(ncid, "scalar", NC_DOUBLE, 0, 0, &scalar_id);

> David
> -----------------------------------------------------------------
> 
> #include <stdio.h>
> #include "netcdf.h"
> 
> #define TIMES   3
> #define LATS    5
> #define LONS    10
> 
> void handle_error(int);
> 
> main ()
> {
>    int  status, i, j, k, ncid, rhid, tempid, my3d_id;
>    int  lat_dim, lon_dim, time_dim, scalar_dim;
>    int  rh_dimids[3];
>    double rh_val;
>    double my3d_data[TIMES][LATS][LONS];
>    size_t rh_index[] = {1, 0, 0};
>    double rh_data[TIMES*LATS*LONS];
> 
>    status = nc_create("test.nc", NC_NOCLOBBER, &ncid);
>    if (status != NC_NOERR) handle_error(status);
> 
>    status = nc_def_dim(ncid, "scalar", 1L, &scalar_dim);
>    if (status != NC_NOERR) handle_error(status);
> 
>    status = nc_def_dim(ncid, "lat", 5L, &lat_dim);
>    if (status != NC_NOERR) handle_error(status);
> 
>    status = nc_def_dim(ncid, "lon", 10L, &lon_dim);
>    if (status != NC_NOERR) handle_error(status);
> 
>    status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim);
>    if (status != NC_NOERR) handle_error(status);
> 
>    rh_dimids[0] = time_dim;
>    rh_dimids[1] = lat_dim;
>    rh_dimids[2] = lon_dim;
>    status = nc_def_var(ncid, "my3d", NC_DOUBLE, 3, rh_dimids, &my3d_id);
>    if (status != NC_NOERR) handle_error(status);
> 
>    status = nc_enddef(ncid);
>    if (status != NC_NOERR) handle_error(status);
> 
>    rh_val = 0.5;
> 
>    for (i=0; i < TIMES; i++)
>       for (j=0; j < LATS; j++)
>          for (k=0; k < LONS; k++) {
>              my3d_data[i][j][k] = rh_val;
>              rh_val += 0.5;
>          }
> 
>    status = nc_put_var_double(ncid, my3d_id, my3d_data);
>    if (status != NC_NOERR) handle_error(status);
> 
>    status = nc_close(ncid);
>    if (status != NC_NOERR) handle_error(status);
> }
> 
> void handle_error(int status) {
>    fprintf(stderr, "%s\n", nc_strerror(status));
> }


[Note about wrong part of answer above:  while it's true for dynamically
allocated multidimensional arrays that "my3d_data" is not the same as
"&my3d_data[0][0][0]", these actually are the same for statically
allocated multidimensional arrays, as my3d_data is declared to be in
the example above.]