htcp

Properties of water suspended in clouds
git clone git://git.meso-star.fr/htcp.git
Log | Files | Refs | README | LICENSE

commit 09a981163886fdfb7c5c402f2ecc1a604d00d8b2
parent 4ec8ec7374795728edb3621c12b27c4f1ac12d5c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 30 Apr 2018 15:28:36 +0200

Fix the les2htcop program

LES data saved as float are now corectly converted in double in the
htcop output file.

Diffstat:
Msrc/les2htcop.c | 125++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 85 insertions(+), 40 deletions(-)

diff --git a/src/les2htcop.c b/src/les2htcop.c @@ -455,19 +455,26 @@ setup_Z_dimension int8_t* is_z_irregular, const int check) { - enum { Z, X, Y, NDIMS }; - char* mem = NULL; - char* mem2 = NULL; - double* pvxsz = NULL; - size_t len[NDIMS], start[NDIMS], dim_len[NDIMS], iz; - size_t i; - double vxsz; - nc_type type; - int varid, dimids[NDIMS], irregular, ndims; + enum { Z, X, Y, NDIMS }; /* Helper constants */ + char* mem = NULL; /* Memory where NetCDF data are copied */ + char* mem2 = NULL; /* Temporary memory used to check the VLEV data */ + size_t len[NDIMS]; + size_t start[NDIMS]; + size_t dim_len[NDIMS]; + size_t z; /* Id over the Z dimension */ + size_t i; /* Common id */ + double vxsz; /* Voxel size */ + double* pvxsz = NULL; /* Pointer toward voxel sizes */ + nc_type type; /* Type of the NetCDF VLEV variable */ + int varid; /* NetCDF id of the VLEV variable */ + int dimids[NDIMS]; /* NetCDF id of the VLEV dimensions */ + int irregular; /* Boolean defining if the Z dimension is irregular */ + int ndims; /* #dims of the VLEV variable */ int err = NC_NOERR; res_T res = RES_OK; ASSERT(nc && voxel_size && lower_pos && is_z_irregular); + /* Retrieve the VLEV variable */ err = nc_inq_varid(nc, "VLEV", &varid); if(err != NC_NOERR) { fprintf(stderr, "Could not inquire the 'VLEV' variable -- %s\n", @@ -476,6 +483,7 @@ setup_Z_dimension goto error; } + /* Inquire the VLEV dimensionality */ NC(inq_varndims(nc, varid, &ndims)); if(ndims != NDIMS) { fprintf(stderr, "The dimension of the 'VLEV' variable must be %i .\n", @@ -483,10 +491,10 @@ setup_Z_dimension res = RES_BAD_ARG; goto error; } - NC(inq_vardimid(nc, varid, dimids)); FOR_EACH(i, 0, NDIMS) NC(inq_dimlen(nc, dimids[i], len+i)); + /* Inquire the type of the VLEV variable */ NC(inq_vartype(nc, varid, &type)); if(type != NC_DOUBLE && type != NC_FLOAT) { fprintf(stderr, "The type of 'VLEV' variable must be float or double.\n"); @@ -494,6 +502,8 @@ setup_Z_dimension goto error; } + /* Allocate te memory space where a Z column of the VLEV variable is going to + * be copied */ mem = mem_alloc(len[Z]*sizeof_nctype(type)); if(!mem) { fprintf(stderr, "Could not allocate memory for the 'VLEV' variable.\n"); @@ -501,10 +511,10 @@ setup_Z_dimension goto error; } + /* Get only one Z column */ start[X] = 0; dim_len[X] = 1; start[Y] = 0; dim_len[Y] = 1; start[Z] = 0; dim_len[Z] = len[Z]; - NC(get_vara(nc, varid, start, dim_len, mem)); #define AT(Mem, Id) (type == NC_FLOAT ? ((float*)Mem)[Id] : ((double*)Mem)[Id]) @@ -518,10 +528,10 @@ setup_Z_dimension } /* Check if the Z dimension is regular */ - FOR_EACH(iz, 1, len[Z]) { - if(!eq_eps(AT(mem, iz) - AT(mem, iz-1), vxsz, 1.e-6)) break; + FOR_EACH(z, 1, len[Z]) { + if(!eq_eps(AT(mem, z) - AT(mem, z-1), vxsz, 1.e-6)) break; } - irregular = (iz != len[Z]); + irregular = (z != len[Z]); /* Setup the size of the voxel */ pvxsz = mem_alloc(sizeof(double) * (irregular ? len[Z] : 1)); @@ -534,9 +544,9 @@ setup_Z_dimension pvxsz[0] = vxsz; if(irregular) { - FOR_EACH(iz, 1, len[Z]) { - pvxsz[iz] = (AT(mem, iz) - (AT(mem, iz-1) + pvxsz[iz-1]*0.5)) * 2.0; - if(pvxsz[iz] <= 0) { + FOR_EACH(z, 1, len[Z]) { + pvxsz[z] = (AT(mem, z) - (AT(mem, z-1) + pvxsz[z-1]*0.5)) * 2.0; + if(pvxsz[z] <= 0) { fprintf(stderr, "The 'VLEV' variable can't have negative or null values.\n"); res = RES_BAD_ARG; @@ -562,8 +572,8 @@ setup_Z_dimension FOR_EACH(ix, 1, len[X]) { start[X] = ix; NC(get_vara(nc, varid, start, dim_len, mem2)); - FOR_EACH(iz, 0, len[Z]) { - if(!eq_eps(AT(mem2, iz), AT(mem, iz), 1.e-6)) { + FOR_EACH(z, 0, len[Z]) { + if(!eq_eps(AT(mem2, z), AT(mem, z), 1.e-6)) { fprintf(stderr, "The Z columns of the 'VLEV' variable must be the same.\n"); res = RES_BAD_ARG; @@ -590,15 +600,26 @@ error: static res_T write_data(int nc, const char* var_name, FILE* stream) { - enum { TIME, Z, X, Y, NDIMS }; - char* mem = NULL; - size_t start[NDIMS], dim_len[NDIMS], len[NDIMS], i, grid_len; + enum { TIME, Z, X, Y, NDIMS }; /* Helper constants */ + + char* mem = NULL; /* Memory where NetCDF data are copied */ + char* mem2 = NULL; /* Tmp memory where NetCDF data are converted */ + size_t start[NDIMS]; + size_t dim_len[NDIMS]; + size_t len[NDIMS]; + size_t slice_len; /* #elements per slice the 3D grid */ + size_t i; /* Common id */ + size_t t; /* Id over the time dimension */ + size_t z; /* Id over the Z dimension */ nc_type type; - int varid, ndims, dimids[NDIMS]; + int varid; /* NetCDF id of the data to write */ + int ndims; /* #dimensions of the NetCDF data to write */ + int dimids[NDIMS]; /* NetCDF id of the data dimension */ int err = NC_NOERR; res_T res = RES_OK; CHK(var_name); + /* Retrieve the NetCDF id of the variable */ err = nc_inq_varid(nc, var_name, &varid); if(err != NC_NOERR) { fprintf(stderr, "Could not inquire the '%s' variable -- %s\n", @@ -607,6 +628,7 @@ write_data(int nc, const char* var_name, FILE* stream) goto error; } + /* Inquire the dimensions of the variable */ NC(inq_varndims(nc, varid, &ndims)); if(ndims != NDIMS) { fprintf(stderr, "The dimension of the '%s' variable must be %i .\n", @@ -614,10 +636,10 @@ write_data(int nc, const char* var_name, FILE* stream) res = RES_BAD_ARG; goto error; } - NC(inq_vardimid(nc, varid, dimids)); FOR_EACH(i, 0, NDIMS) NC(inq_dimlen(nc, dimids[i], len+i)); + /* Inquire the type of the variable */ NC(inq_vartype(nc, varid, &type)); if(type != NC_DOUBLE && type != NC_FLOAT) { fprintf(stderr, @@ -627,31 +649,54 @@ write_data(int nc, const char* var_name, FILE* stream) goto error; } - grid_len = len[X]*len[Y]*len[Z]; - mem = mem_alloc(grid_len*sizeof_nctype(type)); - if(!mem) { + /* Alloc the memory space where the variable data wille be copied. Note that, + * in order to reduce memory consumption, only one slice is read at a given + * time and Z position. */ + slice_len = len[X]*len[Y]; /* # elements per slice */ + mem = mem_alloc(slice_len*sizeof_nctype(type)); + + /* Allocate a temporary memory space to store the variable data converted in + * double precision if they are stored in single precision. */ + mem2 = type==NC_DOUBLE ? mem : mem_alloc(slice_len*sizeof_nctype(NC_DOUBLE)); + + if(!mem || !mem2) { fprintf(stderr, "Could not allocate memory for the '%s' variable.\n", var_name); res = RES_MEM_ERR; goto error; } + /* Read the whole slice */ start[X] = 0; dim_len[X] = len[X]; start[Y] = 0; dim_len[Y] = len[Y]; - start[Z] = 0; dim_len[Z] = len[Z]; - FOR_EACH(i, 0, len[TIME]) { - start[TIME] = i; - dim_len[TIME] = 1; - NC(get_vara(nc, varid, start, dim_len, mem)); - if(fwrite(mem, sizeof_nctype(type), grid_len, stream) != grid_len) { - fprintf(stderr, "Error writing data of the '%s' variable -- '%s'.\n", - var_name, strerror(errno)); - res = RES_IO_ERR; - goto error; + FOR_EACH(t, 0, len[TIME]) { + start[TIME] = t, dim_len[TIME] = 1; + FOR_EACH(z, 0, len[Z]) { + size_t n; + start[Z] = z; dim_len[Z] = 1; + + NC(get_vara(nc, varid, start, dim_len, mem)); /* Fetch the slice data */ + + /* In order to be compliant with the htgop fileformat, single precision + * data must be converted in double precision */ + if(type == NC_FLOAT) { + FOR_EACH(i, 0, slice_len) ((double*)mem2)[i] = ((float*)mem)[i]; + } + + /* Write data */ + n = fwrite(mem2, sizeof_nctype(NC_DOUBLE), slice_len, stream); + if(n != slice_len) { + fprintf(stderr, "Error writing data of the '%s' variable -- '%s'.\n", + var_name, strerror(errno)); + res = RES_IO_ERR; + goto error; + } } } + exit: + if(mem2 != mem) mem_rm(mem2); if(mem) mem_rm(mem); return res; error: @@ -718,13 +763,13 @@ main(int argc, char** argv) WRITE(&grid.vxsz_x, 1, "X voxel size"); WRITE(&grid.vxsz_y, 1, "Y voxel size"); WRITE(grid.vxsz_z, grid.is_z_irregular?(size_t)grid.nz:1, "Z voxel size(s)"); - + /* padding */ fseek(stream, ALIGN_SIZE(ftell(stream), (off_t)pagesize), SEEK_SET); write_data(nc, "RVT", stream); - + /* padding */ fseek(stream, ALIGN_SIZE(ftell(stream), (off_t)pagesize), SEEK_SET); write_data(nc, "RCT", stream); - + /*padding */ fseek(stream, ALIGN_SIZE(ftell(stream), (off_t)pagesize), SEEK_SET); } #undef WRITE