commit c24e9dbe3b9619f8bddb3cc8276135c0ad89c227
parent a6b3f5ea231a4e70937cc0f11b362b0fa86fbda8
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Mon, 16 Jul 2018 16:16:45 +0200
Refactor les2htcp source code
Diffstat:
| M | src/les2htcp.c | | | 412 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
1 file changed, 220 insertions(+), 192 deletions(-)
diff --git a/src/les2htcp.c b/src/les2htcp.c
@@ -13,8 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#define _POSIX_C_SOURCE 200809L /* mmap/getopt/close support */
-#define _DEFAULT_SOURCE 1 /* MAP_POPULATE support */
+#define _POSIX_C_SOURCE 200112L /* getopt/close support */
#include "les2htcp.h"
@@ -29,7 +28,6 @@
#include <string.h>
#include <unistd.h> /* getopt */
#include <fcntl.h> /* open */
-#include <sys/mman.h> /* mmap */
#include <sys/stat.h> /* S_IRUSR & S_IWUSR */
/*******************************************************************************
@@ -186,6 +184,8 @@ grid_release(struct grid* grid)
} \
} (void)0
+#define NDIMS_MAX 4
+
static INLINE const char*
ncerr_to_str(const int ncerr)
{
@@ -254,6 +254,63 @@ sizeof_nctype(const nc_type type)
return sz;
}
+struct var {
+ size_t dim_len[NDIMS_MAX]; /* Length of the dimensions */
+ int ndims; /* #dimensions */
+ int id; /* NetCDF identifier */
+ int type; /* Variable type */
+};
+static const struct var VAR_NULL = {0};
+
+static INLINE res_T
+ncvar_real_inq
+ (int nc,
+ const char* var_name,
+ const size_t expected_ndims,
+ struct var* var)
+{
+ int i;
+ int dimids[NDIMS_MAX]; /* NetCDF id of the data dimension */
+ int err;
+ res_T res = RES_OK;
+ ASSERT(var_name && var && expected_ndims && expected_ndims <= NDIMS_MAX);
+
+ /* Retrieve the NetCDF id of the variable */
+ err = nc_inq_varid(nc, var_name, &var->id);
+ if(err != NC_NOERR) {
+ fprintf(stderr, "Could not inquire the '%s' variable -- %s\n",
+ var_name, ncerr_to_str(err));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Inquire the dimensions of the variable */
+ NC(inq_varndims(nc, var->id, &var->ndims));
+ if((size_t)var->ndims != expected_ndims) {
+ fprintf(stderr, "The dimension of the '%s' variable must be %lu .\n",
+ var_name, (unsigned long)(expected_ndims));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ NC(inq_vardimid(nc, var->id, dimids));
+ FOR_EACH(i, 0, var->ndims) NC(inq_dimlen(nc, dimids[i], var->dim_len+i));
+
+ /* Inquire the type of the variable */
+ NC(inq_vartype(nc, var->id, &var->type));
+ if(var->type != NC_DOUBLE && var->type != NC_FLOAT) {
+ fprintf(stderr,
+ "The type of the '%s' variable cannot be %s. Expecting floating point data.\n",
+ var_name, nctype_to_str(var->type));
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
/*******************************************************************************
* Helper functions
******************************************************************************/
@@ -366,58 +423,35 @@ setup_regular_dimension
double* lower_pos,
const int check)
{
- char* mem = NULL;
- size_t len, start, i;
+ struct var var = VAR_NULL;
+ double* mem = NULL;
+ size_t start, i;
double vxsz;
- nc_type type;
- int varid, dimid, ndims;
- int err = NC_NOERR;
res_T res = RES_OK;
ASSERT(nc && var_name && voxel_size && lower_pos);
- err = nc_inq_varid(nc, var_name, &varid);
- if(err != NC_NOERR) {
- fprintf(stderr, "Could not inquire the '%s' variable -- %s\n",
- var_name, ncerr_to_str(err));
- res = RES_BAD_ARG;
- goto error;
- }
- NC(inq_varndims(nc, varid, &ndims));
- if(ndims != 1) {
- fprintf(stderr, "The dimension of the '%s' variable must be 1 .\n", var_name);
- res = RES_BAD_ARG;
- goto error;
- }
-
- NC(inq_vardimid(nc, varid, &dimid));
- NC(inq_dimlen(nc, dimid, &len));
- ASSERT(len > 0);
-
- NC(inq_vartype(nc, varid, &type));
- if(type != NC_DOUBLE && type != NC_FLOAT) {
- fprintf(stderr, "The type of the '%s' variable must be float or double.\n",
- var_name);
- res = RES_BAD_ARG;
- goto error;
- }
+ res = ncvar_real_inq(nc, var_name, 1, &var);
+ if(res != RES_OK) goto error;
- #define AT(Mem, Id) (type == NC_FLOAT ? ((float*)Mem)[Id] : ((double*)Mem)[Id])
if(!check) {
- char* raw = alloca(8);
+ const size_t len = 1;
start = 0;
- len = 1;
- NC(get_vara(nc, varid, &start, &len, raw));
- vxsz = AT(raw, 0) * 2; /* Assume that the grid starts at 0 */
+ NC(get_vara_double(nc, var.id, &start, &len, &vxsz));
+ /* Assume that the coordinate is defined at the center of the cell and that
+ * the grid starts at 0 */
+ vxsz *= 2;
} else {
- mem = mem_alloc(len*sizeof_nctype(type));
+ mem = mem_alloc(var.dim_len[0]*sizeof(double));
if(!mem) {
fprintf(stderr, "Could not allocate memory for the '%s' variable.\n", var_name);
res = RES_MEM_ERR;
goto error;
}
start = 0;
- NC(get_vara(nc, varid, &start, &len, mem));
- vxsz = AT(mem, 0) * 2; /* Assume that the grid starts from 0 */
+ NC(get_vara_double(nc, var.id, &start, &var.dim_len[0], mem));
+ /* Assume that the coordinate is defined at the center of the cell and that
+ * the grid starts at 0 */
+ vxsz = mem[0] * 2;
}
if(vxsz <= 0) {
@@ -429,8 +463,8 @@ setup_regular_dimension
if(check) {
/* Check that the dimension is regular */
- FOR_EACH(i, 1, len) {
- if(!eq_eps(AT(mem, i) - AT(mem, i-1), vxsz, 1.e-6)) {
+ FOR_EACH(i, 1, var.dim_len[0]) {
+ if(!eq_eps(mem[i] - mem[i-1], vxsz, 1.e-6)) {
fprintf(stderr, "The voxel size of the '%s' variable must be regular.\n",
var_name);
res = RES_BAD_ARG;
@@ -438,7 +472,6 @@ setup_regular_dimension
}
}
}
- #undef AT
*voxel_size = vxsz;
*lower_pos = 0;
@@ -458,56 +491,26 @@ setup_Z_dimension
int8_t* is_z_irregular,
const int check)
{
- 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 */
+ enum { Z, Y, X, NDIMS }; /* Helper constants */
+ struct var var = VAR_NULL;
+ double* mem = NULL; /* Memory where NetCDF data are copied */
+ double* mem2 = NULL; /* Temporary variable used to check NetCDF 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",
- ncerr_to_str(err));
- res = RES_BAD_ARG;
- 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",
- NDIMS);
- 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");
- res = RES_BAD_ARG;
- goto error;
- }
+ res = ncvar_real_inq(nc, "VLEV", NDIMS, &var);
+ if(res != RES_OK) 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));
+ mem = mem_alloc(var.dim_len[Z]*sizeof(double));
if(!mem) {
fprintf(stderr, "Could not allocate memory for the 'VLEV' variable.\n");
res = RES_MEM_ERR;
@@ -515,15 +518,14 @@ setup_Z_dimension
}
/* 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])
-
- /* Assume that the Z dimension starts from 0 */
- vxsz = AT(mem, 0) * 2.0;
+ start[X] = 0; len[X] = 1;
+ start[Y] = 0; len[Y] = 1;
+ start[Z] = 0; len[Z] = var.dim_len[Z];
+ NC(get_vara_double(nc, var.id, start, len, mem));
+
+ /* Assume that the coordinate is defined at the center of the cell and that
+ * the grid starts at 0 */
+ vxsz = mem[0] * 2.0;
if(vxsz <= 0) {
fprintf(stderr, "The 'VLEV' variable can't have negative or null values.\n");
res = RES_BAD_ARG;
@@ -531,13 +533,13 @@ setup_Z_dimension
}
/* Check if the Z dimension is regular */
- FOR_EACH(z, 1, len[Z]) {
- if(!eq_eps(AT(mem, z) - AT(mem, z-1), vxsz, 1.e-6)) break;
+ FOR_EACH(z, 1, var.dim_len[Z]) {
+ if(!eq_eps(mem[z] - mem[z-1], vxsz, 1.e-6)) break;
}
- irregular = (z != len[Z]);
+ irregular = (z != var.dim_len[Z]);
/* Setup the size of the voxel */
- pvxsz = mem_alloc(sizeof(double) * (irregular ? len[Z] : 1));
+ pvxsz = mem_alloc(sizeof(double) * (irregular ? var.dim_len[Z] : 1));
if(!pvxsz) {
fprintf(stderr,
"Could not allocate memory for the voxel size along the Z dimension.\n");
@@ -547,8 +549,8 @@ setup_Z_dimension
pvxsz[0] = vxsz;
if(irregular) {
- FOR_EACH(z, 1, len[Z]) {
- pvxsz[z] = (AT(mem, z) - (AT(mem, z-1) + pvxsz[z-1]*0.5)) * 2.0;
+ FOR_EACH(z, 1, var.dim_len[Z]) {
+ pvxsz[z] = (mem[z] - (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");
@@ -562,7 +564,7 @@ setup_Z_dimension
if(check) {
size_t ix, iy;
- mem2 = mem_alloc(len[Z]*sizeof_nctype(type));
+ mem2 = mem_alloc(var.dim_len[Z]*sizeof(double));
if(!mem2) {
fprintf(stderr,
"Could not allocate memory to check the 'VLEV' variable.\n");
@@ -570,13 +572,13 @@ setup_Z_dimension
goto error;
}
- FOR_EACH(iy, 0, len[Y]) {
+ FOR_EACH(iy, 0, var.dim_len[Y]) {
start[Y] = iy;
- FOR_EACH(ix, 1, len[X]) {
+ FOR_EACH(ix, 1, var.dim_len[X]) {
start[X] = ix;
- NC(get_vara(nc, varid, start, dim_len, mem2));
- FOR_EACH(z, 0, len[Z]) {
- if(!eq_eps(AT(mem2, z), AT(mem, z), 1.e-6)) {
+ NC(get_vara_double(nc, var.id, start, len, mem2));
+ FOR_EACH(z, 0, var.dim_len[Z]) {
+ if(!eq_eps(mem2[z], mem[z], 1.e-6)) {
fprintf(stderr,
"The Z columns of the 'VLEV' variable must be the same.\n");
res = RES_BAD_ARG;
@@ -586,7 +588,6 @@ setup_Z_dimension
}
}
}
- #undef AT
*lower_pos = 0;
*voxel_size = pvxsz;
@@ -600,61 +601,44 @@ error:
goto exit;
}
+/* Functor used to convert NetCDF data */
+typedef void (*convert_data_T)
+ (double* data, /* Input data */
+ const size_t start[4], /* Start Index of the data in the NetCDF */
+ const size_t len[4], /* Lenght of the loaded data */
+ void* context); /* User defined data */
+
+/* Write data of the variable "var_name" into "stream". The data are loaded
+ * slice by slice, where each slice is a 2D array whose dimensions are
+ * "W_E_direction X S_N_direction". The "convert" functor is invoked on each
+ * loaded slice. */
static res_T
-write_data(int nc, const char* var_name, FILE* stream)
+write_data
+ (int nc,
+ const char* var_name,
+ FILE* stream,
+ convert_data_T convert_func, /* May be NULL <=> No conversion */
+ void* convert_ctx) /* Sent as the last argument of "convert_func" */
{
- enum { TIME, Z, X, Y, NDIMS }; /* Helper constants */
+ enum { TIME, Z, Y, X, NDIMS }; /* Helper constants */
+ struct var var = VAR_NULL;
double* mem = NULL; /* Memory where NetCDF data are copied */
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; /* 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",
- var_name, ncerr_to_str(err));
- res = RES_BAD_ARG;
- 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",
- var_name, NDIMS);
- 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,
- "The type of the '%s' variable cannot be %s. Expecting floating point data.\n",
- var_name, nctype_to_str(type));
- res = RES_BAD_ARG;
- goto error;
- }
+ res = ncvar_real_inq(nc, var_name, NDIMS, &var);
+ if(res != RES_OK) goto error;
/* Alloc the memory space where the variable data will 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 */
+ slice_len = var.dim_len[X]*var.dim_len[Y]; /* # elements per slice */
mem = mem_alloc(slice_len*sizeof(double));
if(!mem) {
@@ -665,19 +649,21 @@ write_data(int nc, const char* var_name, FILE* stream)
}
/* Read the whole slice */
- start[X] = 0; dim_len[X] = len[X];
- start[Y] = 0; dim_len[Y] = len[Y];
+ start[X] = 0; len[X] = var.dim_len[X];
+ start[Y] = 0; len[Y] = var.dim_len[Y];
- FOR_EACH(t, 0, len[TIME]) {
- start[TIME] = t, dim_len[TIME] = 1;
- FOR_EACH(z, 0, len[Z]) {
+ FOR_EACH(t, 0, var.dim_len[TIME]) {
+ start[TIME] = t, len[TIME] = 1;
+ FOR_EACH(z, 0, var.dim_len[Z]) {
size_t n;
- start[Z] = z; dim_len[Z] = 1;
+ start[Z] = z; len[Z] = 1;
- NC(get_vara_double(nc, varid, start, dim_len, mem)); /* Fetch the slice data */
+ NC(get_vara_double(nc, var.id, start, len, mem)); /* Fetch the slice data */
+
+ if(convert_func) convert_func(mem, start, len, convert_ctx);
/* Write data */
- n = fwrite(mem, sizeof_nctype(NC_DOUBLE), slice_len, stream);
+ n = fwrite(mem, sizeof(double), slice_len, stream);
if(n != slice_len) {
fprintf(stderr, "Error writing data of the '%s' variable -- '%s'.\n",
var_name, strerror(errno));
@@ -694,19 +680,82 @@ error:
goto exit;
}
+struct THT_to_T_context {
+ double* mem; /* Memory where to store a PABST slice */
+ size_t len; /* lenght of the mem */
+ int pabst_id; /* NetCDF id of the PABST variable */
+ int nc; /* NetCDF handler */
+};
+static const struct THT_to_T_context THT_TO_T_CONTEXT_NULL = { NULL, 0, 0, 0 };
+
+static void
+THT_to_T_context_release(struct THT_to_T_context* ctx)
+{
+ ASSERT(ctx);
+ if(ctx->mem) mem_rm(ctx->mem);
+}
+
+static res_T
+THT_to_T_context_init(struct THT_to_T_context* ctx, int nc)
+{
+ enum { TIME, Z, Y, X, NDIMS }; /* Helper constants */
+ struct var var = VAR_NULL;
+ res_T res = RES_OK;
+ ASSERT(ctx);
+
+ *ctx = THT_TO_T_CONTEXT_NULL;
+
+ res = ncvar_real_inq(nc, "PABST", NDIMS, &var);
+ if(res != RES_OK) goto error;
+
+ /* Allocate memory to store one slice of PABST data */
+ ctx->len = var.dim_len[X] * var.dim_len[Y];
+ ctx->mem = mem_alloc(ctx->len*sizeof(double));
+ if(!ctx->mem) {
+ fprintf(stderr,
+ "Could not allocate the temporary memory space of the THT_to_T_context "
+ "data structure.\n");
+ res = RES_MEM_ERR;
+ goto error;
+ }
+
+ ctx->pabst_id = var.id;
+ ctx->nc = nc;
+
+exit:
+ return res;
+error:
+ THT_to_T_context_release(ctx);
+ goto exit;
+}
+
/* Convert potential temperature to temperature
* T(i)=THT(i)*(PABST(i)/P0)^(R/(M_DA*Cp0)) */
static void
-THT_to_T(const size_t n, const double* PABST, double* THT)
+THT_to_T
+ (double* THT,
+ const size_t start[4], /* Start id of the THT var in the NetCDF file */
+ const size_t len[4], /* Len of the loaded THT */
+ void* context)
{
+ struct THT_to_T_context* ctx = context;
const double P0 = 101325; /* In Pa */
const double R = 8.3144598; /* In kg.m^2.s^-2.mol^-1.K */
const double M_DA = 28.9644e-3; /* In kg.mol^-1 */
const double Cp0 = 1.005e+3; /* In J/kg/K */
const double exponent = R/(M_DA * Cp0);
double* T = THT;
- size_t i;
- ASSERT(n && PABST && THT);
+ double* PABST;
+ size_t i, n;
+ ASSERT(THT && start && len && context);
+
+ n = len[0] * len[1] * len[2] * len[3];
+ CHK(n <= ctx->len);
+ PABST = ctx->mem;
+
+ /* Fetch the slice pressure data */
+ NC(get_vara_double(ctx->nc, ctx->pabst_id, start, len, PABST));
+
FOR_EACH(i, 0, n) T[i] = THT[i] * pow(PABST[i]/P0, exponent);
}
@@ -719,6 +768,8 @@ main(int argc, char** argv)
FILE* stream = stdout;
struct grid grid = GRID_NULL;
struct args args = ARGS_DEFAULT;
+ struct THT_to_T_context THT_to_T_ctx = THT_TO_T_CONTEXT_NULL;
+
int err = 0;
int err_nc = NC_NOERR;
int nc = INVALID_ID;
@@ -741,6 +792,7 @@ main(int argc, char** argv)
}
#define CALL(Func) { if(RES_OK != (res = Func)) goto error; } (void)0
+
CALL(setup_definition(nc, &grid.nx, &grid.ny, &grid.nz, &grid.ntimes));
CALL(setup_regular_dimension
(nc, "W_E_direction", &grid.vxsz_x, grid.lower+0, args.check));
@@ -748,7 +800,6 @@ main(int argc, char** argv)
(nc, "S_N_direction", &grid.vxsz_y, grid.lower+1, args.check));
CALL(setup_Z_dimension
(nc, &grid.vxsz_z, grid.lower+2, &grid.is_z_irregular, args.check));
- #undef CALL
#define WRITE(Var, N, Name) { \
if(fwrite((Var), sizeof(*(Var)), (N), stream) != (N)) { \
@@ -759,11 +810,6 @@ main(int argc, char** argv)
} (void)0
if(!args.no_output) {
const int64_t pagesz = (int64_t)args.pagesize;
- double* PABST = NULL;
- double* THT = NULL;
- long PABST_off, THT_off;
- size_t PABST_len, THT_len;
- size_t n;
WRITE(&pagesz, 1, "page size");
WRITE(&grid.is_z_irregular, 1, "'irregular' Z boolean");
@@ -777,48 +823,30 @@ main(int argc, char** argv)
WRITE(grid.vxsz_z, grid.is_z_irregular?(size_t)grid.nz:1, "Z voxel size(s)");
fseek(stream, ALIGN_SIZE(ftell(stream),(off_t)pagesz), SEEK_SET);/*padding*/
- write_data(nc, "RVT", stream);
+ CALL(write_data(nc, "RVT", stream, NULL, NULL));
fseek(stream, ALIGN_SIZE(ftell(stream),(off_t)pagesz), SEEK_SET);/*padding*/
-
- write_data(nc, "RCT", stream);
+ CALL(write_data(nc, "RCT", stream, NULL, NULL));
fseek(stream, ALIGN_SIZE(ftell(stream),(off_t)pagesz), SEEK_SET);/*padding*/
-
- PABST_off = ftell(stream);
- write_data(nc, "PABST", stream);
+ CALL(write_data(nc, "PABST", stream, NULL, NULL));
fseek(stream, ALIGN_SIZE(ftell(stream),(off_t)pagesz), SEEK_SET);/*padding*/
- PABST_len = (size_t)(ftell(stream) - PABST_off);
- THT_off = ftell(stream);
- write_data(nc, "THT", stream);
- fseek(stream, ALIGN_SIZE(ftell(stream),(off_t)pagesz), SEEK_SET);/*padding*/
- THT_len = (size_t)(ftell(stream) - THT_off);
-
- CHK(fclose(stream) == 0);
- CHK(stream = fopen(args.output, "rw"));
-
- #define MMAP(Var, Prot) { \
- Var = mmap(NULL, Var##_len, Prot, MAP_PRIVATE|MAP_POPULATE, \
- fileno(stream), Var##_off); \
- if(Var == MAP_FAILED) { \
- fprintf(stderr, "%s: could not map the "STR(Var)" data -- %s.\n", \
- args.input, strerror(errno)); \
- goto error; \
- } \
- } (void)0
- MMAP(PABST, PROT_READ);
- MMAP(THT, PROT_READ|PROT_WRITE);
- #undef MMAP
-
- n = (size_t)(grid.nx * grid.ny * grid.nz * grid.ntimes);
- THT_to_T(n, PABST, THT);
-
- CHK(munmap(PABST, PABST_len) == 0);
- CHK(munmap(THT, THT_len) == 0);
+ CALL(THT_to_T_context_init(&THT_to_T_ctx, nc));
+ CALL(write_data(nc, "THT", stream, THT_to_T, &THT_to_T_ctx));
+ if(!IS_ALIGNED(ftell(stream), (size_t)pagesz)) {
+ /* Padding to ensure that the size is aligned on the page size. Note that
+ * one char is written to positioned the EOF indicator */
+ const char byte = 0;
+ fseek(stream, ALIGN_SIZE(ftell(stream),(off_t)pagesz)-1, SEEK_SET);
+ WRITE(&byte, 1, "Dummy Byte");
+ }
}
#undef WRITE
+ #undef CALL
exit:
grid_release(&grid);
+ THT_to_T_context_release(&THT_to_T_ctx);
+ if(stream != stdout) CHK(fclose(stream) == 0);
if(nc != INVALID_ID) NC(close(nc));
if(mem_allocated_size() != 0) {
fprintf(stderr, "Memory leaks: %lu Bytes\n",