sandbox/Emily/writenetcdf.h

    Basilisk programme to write outputs as netcdf files. Written by Cyprien Bosserelle cyprien.bosserelle@niwa.co.nz 2018-2019 Usage: //Save this file in $BASILISK. In the modelling programme include this file with other includes at the top of the file: #include “writenetcdf.h” // First create a netcdf file - define name char ncfile[]=“TPacGebco-out.nc”; // In an initialisation event create file printf(“Create netcdf file for output ”); //Prepare netcdf file for output int nx=(int) 1 << MAXLEVEL; scalar * outvars = {eta,h,hmax,l,u.x,u.y}; create2dnc(ncfile,nx, L0, 0.0, outvars); // Output at designated timesteps (i.e. in ongoing event) printf(“Saving step: t=%f”,t); int nx=1<<MAXLEVEL; scalar * outvars = {eta,h,hmax,l,u.x,u.y}; write2varnc(ncfile,nx, t, outvars);

    Still to do (useful but works without): Set attributes for _FillValue, missing_value

    #include <netcdf.h>
    
    double BiInterp(double q11, double q12, double q21, double q22, double x1, double x2, double y1, double y2, double x, double y)
    {
        double x2x1, y2y1, x2x, y2y, yy1, xx1;
        x2x1 = x2 - x1;
        y2y1 = y2 - y1;
        x2x = x2 - x;
        y2y = y2 - y;
        yy1 = y - y1;
        xx1 = x - x1;
        return 1.0 / (x2x1 * y2y1) * (
            q11 * x2x * y2y +
            q21 * xx1 * y2y +
            q12 * x2x * yy1 +
            q22 * xx1 * yy1
        );
    }
    
    
    void create2dnc(char * ncfilename,int n, double len, double totaltime, scalar * outvars)
    {
    	int status;
    	int ncid, xx_dim, yy_dim, time_dim, p_dim;
    
    	int * tvar_id;
    
    	int nvars = list_len(outvars);
    
    	tvar_id=(int*)malloc(nvars*sizeof(int));
    
    
    	double *xx,*yy, *var;
    
    	double dx=len/n;
    
    	xx = (double *)malloc(n*sizeof(double));
    	yy = (double *)malloc(n*sizeof(double));
    	var = (double *)malloc(n*n*sizeof(double));
    
    	for (int ix=0; ix<n; ix++)
    	{
    		xx[ix]=ix*dx+ X0 + dx/2.;
    		yy[ix]=ix*dx+ Y0 + dx/2.;
    	}
    
    	size_t nxx, nyy, ntt;
    	size_t start[] = { 0, 0, 0 }; // start at first value
    	size_t count[] = { 1, 1, 1 };
    	count[1]=n;
    	count[2]=n;
    
    
    	int time_id, xx_id, yy_id, tt_id;	//
    	nxx = n;
    	nyy = n;
    
    
    	//create the netcdf dataset
    	status = nc_create(ncfilename, NC_NOCLOBBER, &ncid);
    
    	//Define dimensions: Name and length
    
    	status = nc_def_dim(ncid, "xx", nxx, &xx_dim);
    	status = nc_def_dim(ncid, "yy", nyy, &yy_dim);
    
    	status = nc_def_dim(ncid, "time", NC_UNLIMITED, &time_dim);
    	int tdim[] = { time_dim };
    	int xdim[] = { xx_dim };
    	int ydim[] = { yy_dim };
    
    
    	//define variables: Name, Type,...
    	int  var_dimids[3];
    	var_dimids[0] = time_dim;
    
    	var_dimids[1] = yy_dim;
    	var_dimids[2] = xx_dim;
    
    
    	status = nc_def_var(ncid, "time", NC_DOUBLE, 1, tdim, &time_id);
    	status = nc_def_var(ncid, "xx", NC_DOUBLE, 1, xdim, &xx_id);
    	status = nc_def_var(ncid, "yy", NC_DOUBLE, 1, ydim, &yy_id);
    
    	int kk=0;
    	for (scalar s in outvars)
    	{
    		status = nc_def_var(ncid, s.name, NC_DOUBLE, 3, var_dimids, &tvar_id[kk++]);
    	}
    
    
    
    	status = nc_enddef(ncid);
    
    
    	size_t tst[] = { 0 };
    	size_t xstart[] = { 0 }; // start at first value
    	size_t xcount[] = { 1 };
    	xcount[0]=n;
    
    	size_t ystart[] = { 0 }; // start at first value
    	size_t ycount[] = { 1 };
    	ycount[0]=n;
    
    
    
    
    
    	//Provide values for variables
    	status = nc_put_var1_double(ncid, time_id, tst, &totaltime);
    	status = nc_put_vara_double(ncid, xx_id, xstart, xcount, xx);
    	status = nc_put_vara_double(ncid, yy_id, ystart, ycount, yy);
    	kk=0;
    	for (scalar s in outvars)
    	{
    		for (int ii=0; ii<nxx; ii++)
    		{
    			for (int jj=0;jj<nyy;jj++)
    			{
    				var[ii+jj*nxx]=interpolate(s,ii*dx+ X0 + dx/2.,jj*dx+Y0+dx/2.);
    			}
    
    		}
    
    		status = nc_put_vara_double(ncid, tvar_id[kk++], start, count, var);
    	}
    	status = nc_close(ncid);
    
    	free(xx);
    	free(yy);
    	free(var);
    
    }
    
    
    void write2varnc(char * ncfilename,int n, double totaltime, scalar * outvars)
    {
    	int status;
    	int ncid, time_dim, recid;
    	size_t nxx, nyy;
    	size_t start[] = { 0, 0, 0 }; // start at first value should be static?
    	size_t count[] = { 1, n, n };
    
    	// Is this absurd?
    	count[1]=n;
    	count[2]=n;
    
    	static size_t tst[] = { 0 };
    	int time_id, *var_id;
    
    	int nvars = list_len(outvars);
    
    	double * var;
    
    	var_id=(int*)malloc(nvars*sizeof(int));
    
    	var = (double *)malloc(n*n*sizeof(double));
    
    
    	nxx = n;
    	nyy = n;
    
    	double dx= L0/n;
    
    	static size_t nrec;
    	status = nc_open(ncfilename, NC_WRITE, &ncid);
    
    	//read id from time dimension
    	status = nc_inq_unlimdim(ncid, &recid);
    	status = nc_inq_dimlen(ncid, recid, &nrec);// What is the point of static definition if it is redefined here!
    	//printf("nrec=%d\n",nrec);
    
    	//read file for variable ids
    	status = nc_inq_varid(ncid, "time", &time_id);
    	int kk=0;
    	for (scalar s in outvars)
    	{
    		status = nc_inq_varid(ncid, s.name, &var_id[kk++]);
    	}
    
    	start[0] = nrec;//
    	tst[0] = nrec;
    
    	//Provide values for variables
    	status = nc_put_var1_double(ncid, time_id, tst, &totaltime);
    	//status = nc_put_vara_double(ncid, var_id, start, count, var);
    	kk=0;
    	for (scalar s in outvars)
    	{
    		for (int ii=0; ii<nxx; ii++)
    		{
    			for (int jj=0;jj<nyy;jj++)
    			{
    				var[ii+jj*nxx]=interpolate(s,ii*dx+ X0 + dx/2.,jj*dx+Y0+dx/2.);
    			}
    
    		}
    
    		status = nc_put_vara_double(ncid, var_id[kk++], start, count, var);
    	}
    
    	status = nc_close(ncid);
    
    free(var);
    
    }