2
* ADIOS is freely available under the terms of the BSD license described
3
* in the COPYING file in the top level directory of this source distribution.
5
* Copyright (c) 2008 - 2009. UT-BATTELLE, LLC. All rights reserved.
8
/*=================================================================
9
* adiosopenc.c - Open an ADIOS file
11
* Input: File, Verbose
12
* File: string (name) or int64 (handler)
13
* Verbose: numeric (double)
15
* Output: Information structure
17
* FileHandler int64 file handler
18
* TimeStart First timestep in file (usually = 1)
19
* TimeSteps Number of timesteps in file, always at least 1
20
* Groups Adios groups in the file. Usually 1 group is in a file.
21
* This is a structure array of
24
* GroupHandler int64 group handler
25
* Variables structure array of variables
26
* Name path of variable
27
* Type Matlab type class of data
28
* Dims Array of dimensions
29
* Timedim The time dimension, 0 if there is no time varying
30
* part of the variable
31
* GlobalMin global minimum of the variable (1-by-1 mxArray)
32
* GlobalMax global maximum of the variable
34
* Attributes structure array of attributes
35
* Name path of attribute
36
* Type Matlab type class of data
37
* Value attribute value (mxArray)
41
* $Revision: 1.0 $ $Date: 2009/08/05 12:53:41 $
42
* Author: Norbert Podhorszki <pnorbert@ornl.gov>
43
*=================================================================*/
45
#include <string.h> /* memcpy */
47
#include "adios_types.h"
48
#include "adios_read.h"
49
#include "adios_types.h"
53
mxClassID adiostypeToMatlabClass(int type, mxComplexity *complexity );
54
mxArray* valueToMatlabValue( void * data, mxClassID mxtype, mxComplexity complexFlag);
55
void errorCheck(int nlhs, int nrhs, const mxArray *prhs[]);
56
char* getString(const mxArray *mxstr);
57
static void swap_order(int n, uint64_t *array);
60
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
61
char *fname; /* file name */
63
char msg[512]; /* error messages from function calls */
66
ADIOS_FILE *fp; /* File handler structure */
67
ADIOS_GROUP *gp; /* Group handler structure */
68
ADIOS_VARINFO *vinfo; /* Variable info structure */
69
int mpi_comm_dummy; /* ADIOS read API needs an MPI communicator */
70
int32_t timedim; /* time dimension is translated C 0.. -> Matlab 1.. */
71
int asize; /* Attribute size info */
72
enum ADIOS_DATATYPES adiostype; /* Attribute type info */
73
void *data; /* Attributes return their values */
74
mwSize mDims[] = {1}; /* dimensions to create a scalar mxArray */
76
int gi,vi,ai, i; /* loop variables for groups, vars and attrs */
77
mxArray *arr; /* temp array for constructions */
78
mxArray *groups, *vars, *attrs; /* struct arrays under top struct */
79
mxClassID mxtype; /* matlab type (of vars and attrs) */
80
mxComplexity complexFlag;
82
/* Output structure definition */
83
const char *top_field_names[] = {"Name", "FileHandler", "TimeStart", "TimeSteps", "Groups"}; /* top level struct fields */
84
mwSize ntopfields = 5;
85
mwSize top_struct_dims[] = {1,1}; /* dimensions for top level struct array: 1-by-1 */
87
int top_field_FileHandler;
88
int top_field_TimeStart;
89
int top_field_TimeSteps;
92
const char *group_field_names[] = {"Name", "GroupHandler", "Variables", "Attributes"}; /* group level struct fields */
93
mwSize ngroupfields = 4;
94
mwSize group_struct_dims[2]; /* dimensions for group level struct array: 1-by-sth */
96
int group_field_GroupHandler;
97
int group_field_Variables;
98
int group_field_Attributes;
100
const char *var_field_names[] = {"Name","Type","Dims", "Timedim", "GlobalMin", "GlobalMax"}; /* variable level struct fields */
101
mwSize nvarfields = 6;
102
mwSize var_struct_dims[2]; /* dimensions for variable level struct array: 1-by-sth */
106
int var_field_Timedim;
107
int var_field_GlobalMin;
108
int var_field_GlobalMax;
110
const char *attr_field_names[] = {"Name","Type","Value"}; /* attribute level struct fields */
111
mwSize nattrfields = 3;
112
mwSize attr_struct_dims[2]; /* dimensions for attribute level struct array: 1-by-sth */
115
int attr_field_Value;
117
errorCheck(nlhs, nrhs, prhs);
119
/*mexPrintf("nrhs=%d nlhs=%d\n", nrhs, nlhs);*/
121
/***********************/
122
/* 0. get verbose parameter first */
123
verbose = (int)mxGetScalar(prhs[1]);
124
if (verbose) mexPrintf("Verbosity level: %d\n", verbose);
126
/* 1. get file handler */
127
if (mxIsChar(prhs[0])) {
128
fname = getString( (mxArray *)prhs[0]);
129
if (verbose) mexPrintf("File name: \"%s\"\n", fname);
132
/**************************************/
133
/* Open ADIOS file now and get groups */
134
fp = adios_fopen (fname, mpi_comm_dummy);
136
mexErrMsgIdAndTxt("MATLAB:adiosopenc:open",adios_errmsg());
138
if (verbose) mexPrintf("Number of adios groups: %d, fp=%lld\n", fp->groups_count, (int64_t) fp);
140
/******************************/
141
/* Create top level structure */
142
if (verbose) mexPrintf("Create top struct array, 1-by-1\n");
143
plhs[0] = mxCreateStructArray(2, top_struct_dims, ntopfields, top_field_names);
144
top_field_Name = mxGetFieldNumber(plhs[0],"Name");
145
top_field_FileHandler = mxGetFieldNumber(plhs[0],"FileHandler");
146
top_field_TimeStart = mxGetFieldNumber(plhs[0],"TimeStart");
147
top_field_TimeSteps = mxGetFieldNumber(plhs[0],"TimeSteps");
148
top_field_Groups = mxGetFieldNumber(plhs[0],"Groups");
149
mxSetFieldByNumber(plhs[0],0,top_field_Name,mxCreateString(fname));
150
arr = valueToMatlabValue(&fp, mxINT64_CLASS, mxREAL);
151
mxSetFieldByNumber(plhs[0],0,top_field_FileHandler,arr);
152
arr = mxCreateNumericMatrix( 1, 1, mxINT32_CLASS, mxREAL);
153
*(int32_t *)mxGetData(arr) = fp->tidx_start;
154
mxSetFieldByNumber(plhs[0],0,top_field_TimeStart,arr);
155
arr = mxCreateNumericMatrix( 1, 1, mxINT32_CLASS, mxREAL);
156
*(int32_t *)mxGetData(arr) = fp->ntimesteps;
157
mxSetFieldByNumber(plhs[0],0,top_field_TimeSteps,arr);
158
/* Create top.Groups structure array */
159
if (verbose) mexPrintf("Create top.Groups struct array, 1-by-%d\n",fp->groups_count);
160
group_struct_dims[0] = 1;
161
group_struct_dims[1] = fp->groups_count;
162
groups = mxCreateStructArray(2, group_struct_dims, ngroupfields, group_field_names);
163
mxSetFieldByNumber(plhs[0],0,top_field_Groups,groups);
166
/****************************/
167
/* Fill in Groups structure */
168
group_field_Name = mxGetFieldNumber(groups,"Name");
169
group_field_GroupHandler = mxGetFieldNumber(groups,"GroupHandler");
170
group_field_Variables = mxGetFieldNumber(groups,"Variables");
171
group_field_Attributes = mxGetFieldNumber(groups,"Attributes");
173
for (gi = 0; gi < fp->groups_count; gi++) {
174
/* Get info of one group: handler, list of vars, list of attrs */
175
if (verbose) mexPrintf("Group %s: get info\n", fp->group_namelist[gi]);
176
gp = adios_gopen_byid(fp, gi);
178
mexErrMsgIdAndTxt("MATLAB:adiosopenc:groupinfo",adios_errmsg());
180
if (verbose) mexPrintf(" %d variables and %d attributes\n", gp->vars_count, gp->attrs_count);
181
/* Group fields for gi-th group */
182
mxSetFieldByNumber(groups,gi,group_field_Name,mxCreateString(fp->group_namelist[gi]));
183
mexPrintf("Group gp=%lld id=%d vcnt=%d\n", (int64_t)gp, gp->grpid, gp->vars_count);
184
arr = valueToMatlabValue(&gp, mxINT64_CLASS, mxREAL);
185
mxSetFieldByNumber(groups,gi,group_field_GroupHandler,arr);
186
/* Create top.Groups.Variables structure array */
187
var_struct_dims[0] = 1;
188
var_struct_dims[1] = gp->vars_count;
189
vars = mxCreateStructArray(2, var_struct_dims, nvarfields, var_field_names);
190
mxSetFieldByNumber(groups,gi,group_field_Variables,vars);
191
var_field_Name = mxGetFieldNumber(vars,"Name");
192
var_field_Type = mxGetFieldNumber(vars,"Type");
193
var_field_Dims = mxGetFieldNumber(vars,"Dims");
194
var_field_Timedim = mxGetFieldNumber(vars,"Timedim");
195
var_field_GlobalMin = mxGetFieldNumber(vars,"GlobalMin");
196
var_field_GlobalMax = mxGetFieldNumber(vars,"GlobalMax");
197
/* Create top.Groups.Attributes structure array */
198
attr_struct_dims[0] = 1;
199
attr_struct_dims[1] = gp->attrs_count;
200
attrs = mxCreateStructArray(2, attr_struct_dims, nattrfields, attr_field_names);
201
mxSetFieldByNumber(groups,gi,group_field_Attributes,attrs);
202
attr_field_Name = mxGetFieldNumber(attrs,"Name");
203
attr_field_Type = mxGetFieldNumber(attrs,"Type");
204
attr_field_Value = mxGetFieldNumber(attrs,"Value");
206
/******************************/
207
/* Add variables to the group */
209
if (verbose>1) mexPrintf(" Variables\n");
210
for (vi=0; vi < gp->vars_count; vi++) {
211
vinfo = adios_inq_var_byid( gp, vi);
213
mexErrMsgIdAndTxt("MATLAB:adiosopenc:varinfo",adios_errmsg());
215
/* Flip dimensions from ADIOS-read-api/C/row-major order to Matlab/Fortran/column-major order */
216
swap_order(vinfo->ndim, vinfo->dims);
219
mexPrintf(" %s: ndims=%d, adios type=%s, timedim=%d dimensions [",
220
gp->var_namelist[vi], vinfo->ndim, adios_type_to_string(vinfo->type), vinfo->timedim);
221
for (i=0; i<vinfo->ndim; i++)
222
mexPrintf("%lld ", vinfo->dims[i]);
226
mxSetFieldByNumber(vars,vi,var_field_Name,mxCreateString(gp->var_namelist[vi]));
228
mxtype = adiostypeToMatlabClass(vinfo->type, &complexFlag);
229
arr = mxCreateNumericMatrix( 1, 1, mxtype, complexFlag);
230
mxSetFieldByNumber(vars,vi,var_field_Type,mxCreateString(mxGetClassName(arr)));
233
if (vinfo->ndim > 0) {
234
arr = mxCreateNumericMatrix( 1, vinfo->ndim, mxINT32_CLASS, mxREAL);
235
int32p = (int32_t *)mxGetData(arr);
236
for (i=0; i<vinfo->ndim; i++)
237
int32p[i] = (int32_t) vinfo->dims[i];
239
arr = mxCreateNumericMatrix( 0, 0, mxINT32_CLASS, mxREAL);
241
mxSetFieldByNumber(vars,vi,var_field_Dims,arr);
244
/* Timedim is -1,0...ndim-1 in C, 0,1..ndim in Matlab */
245
timedim = vinfo->timedim + 1;
246
arr = valueToMatlabValue((void *)(&timedim), mxINT32_CLASS, mxREAL);
247
mxSetFieldByNumber(vars,vi,var_field_Timedim,arr);
249
/* field GLOBALMIN */
250
arr = valueToMatlabValue(vinfo->gmin, mxtype, complexFlag);
251
mxSetFieldByNumber(vars,vi,var_field_GlobalMin,arr);
253
/* field GLOBALMAX */
254
arr = valueToMatlabValue(vinfo->gmax, mxtype, complexFlag);
255
mxSetFieldByNumber(vars,vi,var_field_GlobalMax,arr);
257
adios_free_varinfo(vinfo);
262
/******************************/
263
/* Add attributes to the group */
265
if (verbose>1) mexPrintf(" Attributes\n");
266
for (ai=0; ai < gp->attrs_count; ai++) {
267
status = adios_get_attr_byid( gp, ai, &adiostype, &asize, &data);
269
mexErrMsgIdAndTxt("MATLAB:adiosopenc:varinfo",adios_errmsg());
272
mexPrintf(" %s: adios type=%s, size=%d\n",
273
gp->attr_namelist[ai], adios_type_to_string(adiostype), asize);
275
mxSetFieldByNumber(attrs,ai,attr_field_Name,mxCreateString(gp->attr_namelist[ai]));
277
mxtype = adiostypeToMatlabClass(adiostype, &complexFlag);
278
arr = mxCreateNumericMatrix( 1, 1, mxtype, complexFlag);
279
mxSetFieldByNumber(attrs,ai,attr_field_Type,mxCreateString(mxGetClassName(arr)));
282
arr = valueToMatlabValue(data, mxtype, complexFlag);
283
mxSetFieldByNumber(attrs,ai,attr_field_Value,arr);
285
free(data); /* we do not store attribute values yet */
289
if (verbose>1) mexPrintf(" finished defining group\n");
293
if (verbose) mexPrintf("return from adiosopenc\n");
296
mxArray * valueToMatlabValue( void * data, mxClassID mxtype, mxComplexity complexFlag)
298
/* copies values in all cases, so one can free(data) later */
301
arr = mxCreateString("undefined");
302
} else if (mxtype == mxCHAR_CLASS) {
303
arr = mxCreateString((char *)data);
304
} else if (complexFlag == mxCOMPLEX) {
305
arr = mxCreateDoubleMatrix( 1, 1, mxCOMPLEX);
306
if (mxtype == mxSINGLE_CLASS) {
307
*(double *)mxGetPr(arr) = ((float *)data)[0];
308
*(double *)mxGetPi(arr) = ((float *)data)[1];
310
*(double *)mxGetPr(arr) = ((double *)data)[0];
311
*(double *)mxGetPi(arr) = ((double *)data)[1];
314
arr = mxCreateNumericMatrix( 1, 1, mxtype, mxREAL);
315
memcpy( mxGetData(arr), data, mxGetElementSize(arr));
320
void errorCheck(int nlhs, int nrhs, const mxArray *prhs[]){
321
/* Assume that we are called from adiosread.m which checks the arguments already */
322
/* Check for proper number of arguments. */
325
mexErrMsgIdAndTxt("MATLAB:adiosopenc:rhs","This function needs exactly 2 arguments: File, Verbose");
328
if ( !mxIsChar(prhs[0]) ) {
329
mexErrMsgIdAndTxt("MATLAB:adiosopenc:rhs","First arg must be a string.");
332
if ( !mxIsNumeric(prhs[1]) ) {
333
mexErrMsgIdAndTxt("MATLAB:adiosopenc:rhs","Second arg must be a number.");
337
mexErrMsgIdAndTxt("MATLAB:adiosopenc:lhs","Too many output arguments.");
340
#if !defined(MX_COMPAT_32)
341
/* Make sure that it is safe to cast dim to mwSize when using largeArrayDims.*/
342
if ( dim > MWSIZE_MAX ) {
343
mexErrMsgIdAndTxt("MATLAB:adiosopenc:dimensionTooLarge",
344
"The input dimension, %.0f, is larger than the maximum value of mwSize, %u, when built with largeArrayDims.", dim, MWSIZE_MAX);
350
/** Make a C char* string from a Matlab string */
351
char* getString(const mxArray *mxstr)
355
/* Allocate enough memory to hold the converted string. */
356
buflen = mxGetNumberOfElements(mxstr) + 1;
357
str = mxCalloc(buflen, sizeof(char));
358
/* Copy the string data from string_array_ptr and place it into buf. */
359
if (mxGetString(mxstr, str, buflen) != 0)
360
mexErrMsgTxt("Could not convert string data from the file name.");
364
/** return the appropriate class for an adios type (and complexity too) */
365
mxClassID adiostypeToMatlabClass(enum ADIOS_DATATYPES type, mxComplexity *complexity )
367
*complexity = mxREAL;
369
case adios_unsigned_byte:
370
return mxUINT8_CLASS;
376
case adios_unsigned_short:
377
return mxUINT16_CLASS;
379
return mxINT16_CLASS;
381
case adios_unsigned_integer:
382
return mxUINT32_CLASS;
384
return mxINT32_CLASS;
386
case adios_unsigned_long:
387
return mxUINT64_CLASS;
389
return mxINT64_CLASS;
392
return mxSINGLE_CLASS;
394
return mxDOUBLE_CLASS;
396
case adios_complex: /* 8 bytes */
397
*complexity = mxCOMPLEX;
398
return mxSINGLE_CLASS;
399
case adios_double_complex: /* 16 bytes */
400
*complexity = mxCOMPLEX;
401
return mxDOUBLE_CLASS;
403
case adios_long_double: /* 16 bytes */
405
mexErrMsgIdAndTxt("MATLAB:adiosopenc.c:dimensionTooLarge",
406
"Adios type %d (%s) not supported in visit.\n",
407
type, adios_type_to_string(type));
410
return 0; /* just to avoid warnings. never executed */
414
/* Reverse the order in an array in place.
415
use swapping from Matlab/Fortran/column-major order to ADIOS-read-api/C/row-major order and back
417
static void swap_order(int n, uint64_t *array)
420
for (i=0; i<n/2; i++) {
422
array[i] = array[n-1-i];