/*
 * =====================================================================================
 *
 *       Filename:  mkncfile.c 
 *
 *    Description:  Create an example NetCDF file.
 *
 *        Version:  1.0
 *        Created:  07/15/2016 11:21:49 AM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Eugen Betke (betke@dkrz.de), Julian Kunkel (juliankunkel@googlemail.com)
 *   Organization:  Deutsches Klimarechenzentrum / German Climate Computing Center
 *
 * =====================================================================================
 */

#include <mpi.h>
#include <netcdf.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

#define TIMEIDX 0
#define LATIDX 1
#define LONIDX 2

#define NLON 5
#define NLAT 6
#define NTIME 4

int main(int argc, char** argv){
	int ret;
	const char* gridfile = "grid.nc";
	const char* datafile = "data.nc";
	int ncid;
	const int dimsize = 3;
	int var, dimids[dimsize], varids[dimsize];

	MPI_Init(& argc, & argv);

	// create labels for dimensions
	float latdata[NLAT], londata[NLON], timedata[NTIME];
	for (int i = 0; i < NLAT; ++i) {
		latdata[i] = 0.98 + i * 0.75;
	}

	for (int i = 0; i < NLON; ++i) {
		londata[i] = 10.34 + i * 0.75;
	}

	for (int i = 0; i < NTIME; ++i) {
		timedata[i] = 1000.5 + i * 0.75;
	}

	//ret = nc_create_par(file, NC_MPIIO, MPI_COMM_WORLD, MPI_INFO_NULL, & ncid);
	ret = nc_create(gridfile, NC_NETCDF4, & ncid);
	assert(ret == NC_NOERR);

	// create unlimited, labeled time dimension
	const size_t start[] = {0};
	const size_t count[] = {NTIME};
	ret = nc_def_dim(ncid, "time", NC_UNLIMITED, &dimids[TIMEIDX]);
	assert(ret == NC_NOERR);
	ret = nc_def_var(ncid, "time", NC_FLOAT, 1, &dimids[TIMEIDX], &varids[TIMEIDX]);
	assert(ret == NC_NOERR);
	ret = nc_put_vara(ncid, varids[TIMEIDX], start, count, &timedata);
	assert(ret == NC_NOERR);

	// create labeled latitude dimension
	ret = nc_def_dim(ncid, "lat", NLAT, & dimids[LATIDX]);
	assert(ret == NC_NOERR);
	ret = nc_def_var(ncid, "lat", NC_FLOAT, 1, &dimids[LATIDX], &varids[LATIDX]);
	assert(ret == NC_NOERR);
	ret = nc_put_var(ncid, varids[LATIDX], &latdata);
	assert(ret == NC_NOERR);

	// create labeled longitude dimension
	ret = nc_def_dim(ncid, "lon", NLON, & dimids[LONIDX]);
	assert(ret == NC_NOERR);
	ret = nc_def_var(ncid, "lon", NC_FLOAT, 1, &dimids[LONIDX], &varids[LONIDX]);
	assert(ret == NC_NOERR);
	ret = nc_put_var(ncid, varids[LONIDX], &londata);
	assert(ret == NC_NOERR);

	// data
	ret = nc_def_var(ncid, "var1", NC_INT, dimsize, dimids, &var);
	assert(ret == NC_NOERR);
	ret = nc_enddef(ncid);
	assert(ret == NC_NOERR);

	int (*data)[NLAT][NLON] = malloc(NTIME * sizeof(*data));

	for (int time = 0; time < NTIME; ++time) {
		for(int lat = 0; lat < NLAT; lat++) {
			for(int lon = 0; lon < NLON; lon++) {
				data[time][lat][lon] = lat + lon + time;
			}
		}
	}

	// nc_set_var_chunk_cache (int ncid, int varid, size_t size, size_t nelems, float preemption)
	size_t countp[] = {1,NLAT,NLON};

	// writing data
	for(int time=0; time < NTIME; time++){
		size_t startp[] = {time,0,0};
		ret = nc_put_vara_int(ncid, var, startp, countp, &data[time][0][0]);
		assert(ret == NC_NOERR);
	}

	// reading data back
	for(int time=0; time < NTIME; time++){
		size_t startp[] = {time,0,0};
		ret = nc_get_vara_int(ncid, var, startp, countp, &data[time][0][0]);
		assert(ret == NC_NOERR);
	}

	// clean up
	free(data);
	nc_close(ncid);
	MPI_Finalize();
	return 0;
}

