aboutsummaryrefslogtreecommitdiff
path: root/src/DumpVar.c
blob: 1d7c3f664941e02f74933b791127cf71cd27d914 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
/*@@
   @file      DumpVar.c
   @date      Fri May 21 1999
   @author    Thomas Radke / Gerd Lanfermann
   @desc 
   Do the actual writing of a variable.
   @enddesc 
   @history
   @hauthor Thomas Radke @hdate May 21 1999
   @hdesc Just copied from thorn FlexIO.
   @hendhistory
 @@*/


#include <stdio.h>
#include <stdlib.h>

#include "cctk.h"
#include "cctk_Parameters.h"
#include "CactusBase/IOUtil/src/ioGH.h"
#include "CactusPUGH/PUGHSlab/src/PUGHSlab.h"
#include "StreamedHDF5GH.h"


/*#define StreamedHDF5_DEBUG    1 */

/* local function prototypes */
static void StreamedHDF5_Dump (cGH *GH, int index, int timelevel, void *outme,
                               int hdim, int *hsizes, int hdf5_type, hid_t fid);
static void StreamedHDF5_AddCommonAttributes (cGH *GH, int index, int timelevel,
                                              hid_t dataset);
static int GetHDF5type (StreamedHDF5GH *myGH, int vtype, hid_t *hdf5_type);

/*@@
  @routine    StreamedHDF5_DumpVar
  @date       16 Apr 1999
  @author     Thomas Radke
  @desc
              Generic dump routine, just calls the appropriate dump routine
	      Extracts the data with Hyperslab.
  @enddesc
  @calledby   StreamedHDF5_DumpGH IOHDF5_Write3D
  @history
  @endhistory
  @var        GH
  @vdesc      Pointer to CCTK grid hierarchy
  @vtype      cGH
  @vio        in
  @endvar
  @var        index
  @vdesc      global index of the variable to be dumped
  @vtype      int
  @vio        in
  @endvar
  @var        timelevel
  @vdesc      the timelevel to store
  @vtype      int
  @vio        in
  @endvar
  @var        fid
  @vdesc      the HDF5 file handle
  @vtype      hid_t
  @vio        in
  @endvar
@@*/
int StreamedHDF5_DumpVar (cGH *GH, int index, int timelevel, hid_t fid)
{
  DECLARE_CCTK_PARAMETERS
  void *data;
  int *hsizes;
  hid_t hdf5_type;
  StreamedHDF5GH *myGH;
  StreamGeo_t geo;
  int vtype;
  
  int sdir[3] = {0,0,0};


  /* Get the handle for StreamedHDF5 extensions */
  myGH = (StreamedHDF5GH *) GH->extensions [CCTK_GHExtensionHandle ("StreamedHDF5")];

  vtype = CCTK_VarTypeI (index);
  if (GetHDF5type (myGH, vtype, &hdf5_type) < 0)
  {
    CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
                "Unsupported variable type %d", vtype);
    return (-1);
  }
  /* shortcut to the slab geometry */
  geo = myGH->geo_output[index];

  /* get the dimension of the variable */

  hsizes = (int*)malloc(geo.sdim*sizeof(int));

  data = NULL;

  /* TEMPORARY FIX DUE TO INCONSISTENT DIR SPECIFICATION */
  /* direction vector of 1d line in 3d volume */
  if (geo.sdim==1) {
    sdir[0] = (geo.direction[0]==0) ? 1:0;
    sdir[1] = (geo.direction[0]==1) ? 1:0;
    sdir[2] = (geo.direction[0]==2) ? 1:0;
  } 
  /* norm vector of 2d surface in 3d volume */
  else if (geo.sdim==2)
  {
    sdir[0] = (geo.direction[1]&&geo.direction[2]) ? 1:0;
    sdir[1] = (geo.direction[0]&&geo.direction[2]) ? 1:0;
    sdir[2] = (geo.direction[0]&&geo.direction[1]) ? 1:0;
  }
  /* spanning directions for 3d */
  else if (geo.sdim==3)
  {
    sdir[0] = geo.direction[0];
    sdir[1] = geo.direction[1];
    sdir[2] = geo.direction[2];
  }

  if (Hyperslab_GetHyperslab (GH, 0, index, timelevel, geo.sdim, geo.origin,
                              sdir, geo.length, geo.downs,
                              &data, hsizes) < 0)
  {
    char *fullname = CCTK_FullName (index);


    CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING,
                "Failed to extract hyperslab for variable '%s'", fullname);
    free (fullname);
    return (-1);
  }

  if (fid >= 0)
  {
    StreamedHDF5_Dump (GH, index, timelevel, data, geo.sdim, hsizes, hdf5_type, fid);
  }

  if (data)
    free (data);

  return (0);
}


/***************************** local functions ****************************/

static int GetHDF5type (StreamedHDF5GH *myGH, int vtype, hid_t *hdf5_type)
{
  int retval = 0;


  switch (vtype)
  {
    case CCTK_VARIABLE_CHAR:
      *hdf5_type = IOHDF5_CHAR;
      break;
    case CCTK_VARIABLE_INT:
      *hdf5_type = IOHDF5_INT;
      break;
    case CCTK_VARIABLE_REAL: 
      *hdf5_type = IOHDF5_REAL;
      break;
    case CCTK_VARIABLE_COMPLEX:
      *hdf5_type = myGH->IOHDF5_COMPLEX;
      break;
    default:
      retval = -1;
      break;
  }

  return (retval);
}


/*@@
  @routine    StreamedHDF5_AddCommonAttributes
  @date       May 21 1999
  @author     Thomas Radke
  @desc 
  Add "Common" attributes, these are:
  <ul>
    <li> the variable's groupname
    <li> the grouptype
    <li> number of timelevels
    <li> the current date
         Note that the datestamp should be turned of if you are byte 
         comparing two output files.
    <li> simulation time
    <li> origin
    <li> bounding box
    <li> gridspacings (both downsampled and evolution)
    <li> global grid size
  </ul>
  @enddesc 
  @calledby   StreamedHDF5_DumpGS, IOHDF5_collectiveDump, IOHDF5_procDump
  @history 
  @endhistory 
  @var        GH
  @vdesc      Pointer to CCTK grid hierarchy
  @vtype      cGH
  @vio        in
  @endvar
  @var        index
  @vdesc      global index of the variable to be dumped
  @vtype      int
  @vio        in
  @endvar
  @var        timelevel
  @vdesc      the timelevel to store
  @vtype      int
  @vio        in
  @endvar
  @var        dataset
  @vdesc      the dataset handle where the attributes should be attached to
  @vtype      hid_t
  @vio        in
  @endvar
@@*/
static void StreamedHDF5_AddCommonAttributes (cGH *GH, int index, int timelevel,
                                              hid_t dataset)
{
  DECLARE_CCTK_PARAMETERS
#if 0
  int dim;
  CCTK_INT intAttr;
  char *groupname;
#endif
  CCTK_REAL realAttr [6];
  StreamedHDF5GH *myGH;
  CCTK_REAL dummy;

  /* Get the handles for IOUtil and StreamedHDF5 extensions */
  myGH = (StreamedHDF5GH *) GH->extensions [CCTK_GHExtensionHandle ("StreamedHDF5")];

#if 0
  /* get the dimension of the variable */
  dim = CCTK_GroupDimI (CCTK_GroupIndexFromVarI (index));

  groupname = CCTK_GroupNameFromVarI (index);
  WRITE_ATTRIBUTE ("groupname", groupname,
                   dataset, myGH->scalarDataspace, 0, myGH->IOHDF5_STRING);
  free (groupname);
  intAttr = CCTK_GroupTypeFromVarI (index);
  WRITE_ATTRIBUTE ("grouptype", &intAttr, dataset, myGH->scalarDataspace, 0,
                   IOHDF5_INT);
  intAttr = CCTK_NumTimeLevelsFromVarI (index);
  WRITE_ATTRIBUTE ("ntimelevels", &intAttr, dataset, myGH->scalarDataspace, 0,
                   IOHDF5_INT);
#endif

  WRITE_ATTRIBUTE ("time", &GH->cctk_time, dataset, myGH->scalarDataspace, 0,
                   IOHDF5_REAL);

  /* NOTE: the attributes "origin", "min_ext", "max_ext", and "delta"
           are always stored as 3-dimensional points */
  CCTK_CoordRange (GH, &realAttr [0], &dummy, -1, "x", "cart3d");
  CCTK_CoordRange (GH, &realAttr [1], &dummy, -1, "y", "cart3d");
  CCTK_CoordRange (GH, &realAttr [2], &dummy, -1, "z", "cart3d");

  WRITE_ATTRIBUTE ("origin", realAttr, dataset, myGH->arrayDataspace, 3,
                   IOHDF5_REAL);

  CCTK_CoordRange (GH, &realAttr [0], &realAttr [3], -1, "x","cart3d");
  CCTK_CoordRange (GH, &realAttr [1], &realAttr [4], -1, "y","cart3d");
  CCTK_CoordRange (GH, &realAttr [2], &realAttr [5], -1, "z","cart3d");
  WRITE_ATTRIBUTE ("min_ext", realAttr, dataset, myGH->arrayDataspace, 3,
                   IOHDF5_REAL);
  WRITE_ATTRIBUTE ("max_ext", realAttr + 3, dataset, myGH->arrayDataspace, 3,
                   IOHDF5_REAL);
 
  WRITE_ATTRIBUTE ("delta", GH->cctk_delta_space, dataset, myGH->arrayDataspace,
                   3, IOHDF5_REAL);
}


/*@@
  @routine StreamedHDF5_procDump
  @author  Thomas Radke
  @date    May 21 1999
  @desc    All IO processors dump the data of their group into the file,
           either as one chunk per processor or unchunked
           (depending on parameter "unchunked").
  @enddesc
  @calledby   StreamedHDF5_DumpGA
  @history 
  @endhistory 
  @var        GH
  @vdesc      Pointer to CCTK grid hierarchy
  @vtype      cGH
  @vio        in
  @endvar
  @var        index
  @vdesc      global index of the variable to be dumped
  @vtype      int
  @vio        in
  @endvar
  @var        timelevel
  @vdesc      the timelevel to store
  @vtype      int
  @vio        in
  @endvar
  @var        outme
  @vdesc      pointer to the chunk to dump
  @vtype      void *
  @vio        in
  @endvar
  @var        geom
  @vdesc      bounds and sizes of the output
  @vtype      CCTK_INT [3*dim]
  @vio        in
  @vcomment   geom [0*dim..1*dim-1]: lower bounds
              geom [1*dim..2*dim-1]: (local) data sizes
              geom [2*dim..3*dim-1]: global space
  @endvar 
  @var        proc
  @vdesc      the processor which's chunk is to be dumped
  @vtype      int
  @vio        in
  @endvar
  @var        hdf5io_type
  @vdesc      the HDF5 datatype identifier
  @vtype      int
  @vio        in
  @endvar
  @var        fid
  @vdesc      the HDF5 file handle
  @vtype      hid_t
  @vio        in
  @endvar
@@*/
static void StreamedHDF5_Dump (cGH *GH, int index, int timelevel, void *outme,
                               int hdim, int *hsizes, int hdf5_type, hid_t fid)
{
  DECLARE_CCTK_PARAMETERS
  int i;
  hid_t dataset, memspace;
  char *name, *datasetname;
  hsize_t *dims;


  dims = (hsize_t *)  malloc (hdim * sizeof (hsize_t));

  /* HDF5 needs it in reverse order */
  for (i = 0; i < hdim; i++)
  {
    dims [i] = hsizes [hdim - 1 - i];
  }

  /* build the unique dataset name */
  name = CCTK_FullName (index);
  datasetname = (char *) malloc (strlen (name) + 30);  /* 30 chars should be
                                                          enough for 2 ints */
  sprintf (datasetname, "%s@%d@%d", name, GH->cctk_iteration, timelevel);
  free (name);

  /* create the memspace according to chunk dims */
  CACTUS_IOHDF5_ERROR (memspace = H5Screate_simple (hdim, dims, NULL));

  /* create the dataset */
  CACTUS_IOHDF5_ERROR (dataset = H5Dcreate (fid, datasetname, hdf5_type,
                                            memspace, H5P_DEFAULT));
  /* write the data */
  CACTUS_IOHDF5_ERROR (H5Dwrite (dataset, hdf5_type, H5S_ALL, H5S_ALL,
                                 H5P_DEFAULT, outme));

  StreamedHDF5_AddCommonAttributes (GH, index, timelevel, dataset);

  /* close the dataset and the memspace */
  CACTUS_IOHDF5_ERROR (H5Dclose (dataset));
  CACTUS_IOHDF5_ERROR (H5Sclose (memspace));

  free (datasetname);
  free (dims);
}