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.
9
/****************************/
10
/* Read method for BP files */
11
/****************************/
19
#include "adios_types.h"
20
#include "adios_read.h"
21
#include "adios_read_hooks.h"
22
#include "adios_error.h"
29
MPI_File * get_BP_file_handle(struct BP_file_handle * l, uint32_t file_index)
36
if (l->file_index == file_index)
45
void add_BP_file_handle (struct BP_file_handle ** l, struct BP_file_handle * n)
55
void close_all_BP_files (struct BP_file_handle * l)
57
struct BP_file_handle * n;
63
MPI_File_close (&l->fh);
70
/* Return 0: if file is little endian, 1 if file is big endian
71
* We know if it is different from the current system, so here
72
* we determine the current endianness and report accordingly.
74
static int adios_read_bp_get_endianness( uint32_t change_endianness )
79
char *p = (char *) &i;
80
int current_endianness;
81
if (p[0] == 1) // Lowest address contains the least significant byte
82
current_endianness = LE;
84
current_endianness = BE;
85
if (change_endianness == adios_flag_yes)
86
return !current_endianness;
88
return current_endianness;
91
int adios_read_bp_init (MPI_Comm comm) { return 0; }
92
int adios_read_bp_finalize () { return 0; }
94
ADIOS_FILE * adios_read_bp_fopen (const char * fname, MPI_Comm comm)
102
fh = (struct BP_FILE *) malloc (sizeof (struct BP_FILE));
104
adios_error ( err_no_memory, "Cannot allocate memory for file info.");
108
fh->fname = (fname ? strdup (fname) : 0L);
115
fh->b = malloc (sizeof (struct adios_bp_buffer_struct_v1));
117
adios_error ( err_no_memory, "Cannot allocate memory for file info.");
120
fp = (ADIOS_FILE *) malloc (sizeof (ADIOS_FILE));
122
adios_error ( err_no_memory, "Cannot allocate memory for file info.");
126
adios_buffer_struct_init (fh->b);
127
MPI_Comm_rank (comm, &rank);
128
if (bp_read_open (fname, comm, fh))
131
/* Only rank=0 process reads the footer and it broadcasts to all other processes */
133
if (bp_read_minifooter (fh))
136
MPI_Bcast (&fh->mfooter, sizeof(struct bp_minifooter),MPI_BYTE, 0, comm);
138
header_size = fh->mfooter.file_size-fh->mfooter.pgs_index_offset;
142
bp_alloc_aligned (fh->b, header_size);
145
memset (fh->b->buff, 0, header_size);
150
MPI_Bcast (fh->b->buff, fh->mfooter.file_size-fh->mfooter.pgs_index_offset, MPI_BYTE, 0 , comm);
152
/* Everyone parses the index on its own */
157
/* fill out ADIOS_FILE struct */
158
fp->fh = (uint64_t) fh;
159
fp->groups_count = fh->gvar_h->group_count;
160
fp->vars_count = fh->mfooter.vars_count;
161
fp->attrs_count = fh->mfooter.attrs_count;
162
fp->tidx_start = fh->tidx_start;
163
fp->ntimesteps = fh->tidx_stop - fh->tidx_start + 1;
164
fp->file_size = fh->mfooter.file_size;
165
fp->version = fh->mfooter.version;
166
fp->endianness = adios_read_bp_get_endianness(fh->mfooter.change_endianness);
167
alloc_namelist (&fp->group_namelist,fp->groups_count);
168
for (i=0;i<fp->groups_count;i++) {
169
if (!fp->group_namelist[i]) {
170
adios_error (err_no_memory, "Could not allocate buffer for %d strings in adios_fopen()", fp->groups_count);
171
adios_read_bp_fclose(fp);
175
strcpy(fp->group_namelist[i],fh->gvar_h->namelist[i]);
181
/* This function can be called if user places
182
the wrong sequences of dims for a var
184
void adios_read_bp_reset_dimension_order (ADIOS_FILE *fp, int is_fortran)
186
struct BP_FILE * fh = (struct BP_FILE *)(fp->fh);
187
struct bp_index_pg_struct_v1 ** root = &(fh->pgs_root);
188
struct bp_minifooter * mh = &(fh->mfooter);
191
for (i = 0; i < mh->pgs_count; i++) {
192
is_fortran ? ((*root)->adios_host_language_fortran = adios_flag_yes)
193
: ((*root)->adios_host_language_fortran = adios_flag_no);
194
root = &(*root)->next;
198
int adios_read_bp_fclose (ADIOS_FILE *fp)
200
struct BP_FILE * fh = (struct BP_FILE *) fp->fh;
201
struct BP_GROUP_VAR * gh = fh->gvar_h;
202
struct BP_GROUP_ATTR * ah = fh->gattr_h;
203
struct adios_index_var_struct_v1 * vars_root = fh->vars_root, *vr;
204
struct adios_index_attribute_struct_v1 * attrs_root = fh->attrs_root, *ar;
205
struct bp_index_pg_struct_v1 * pgs_root = fh->pgs_root, *pr;
207
MPI_File mpi_fh = fh->mpi_fh;
211
MPI_File_close (&mpi_fh);
214
close_all_BP_files (fh->sfh);
217
adios_posix_close_internal (fh->b);
221
/* Free variable structures */
222
/* alloc in bp_utils.c: bp_parse_vars() */
225
vars_root = vars_root->next;
226
for (j = 0; j < vr->characteristics_count; j++) {
227
// alloc in bp_utils.c:bp_parse_characteristics() <- bp_get_characteristics_data()
228
if (vr->characteristics[j].dims.dims)
229
free (vr->characteristics[j].dims.dims);
230
if (vr->characteristics[j].value)
231
free (vr->characteristics[j].value);
232
// NCSU - Clearing up statistics
233
if (vr->characteristics[j].stats)
235
uint8_t k = 0, idx = 0;
236
uint8_t i = 0, count = adios_get_stat_set_count(vr->type);
238
while (vr->characteristics[j].bitmap >> k)
240
if ((vr->characteristics[j].bitmap >> k) & 1)
242
for (i = 0; i < count; i ++)
244
if (k == adios_statistic_hist)
246
struct adios_index_characteristics_hist_struct * hist = (struct adios_index_characteristics_hist_struct *) (vr->characteristics [j].stats[i][idx].data);
248
free (hist->frequencies);
252
free (vr->characteristics[j].stats [i][idx].data);
259
for (i = 0; i < count; i ++)
260
free (vr->characteristics[j].stats [i]);
262
free (vr->characteristics[j].stats);
263
vr->characteristics[j].stats = 0;
266
if (vr->characteristics)
267
free (vr->characteristics);
269
free (vr->group_name);
277
/* Free attributes structures */
278
/* alloc in bp_utils.c bp_parse_attrs() */
281
attrs_root = attrs_root->next;
282
for (j = 0; j < ar->characteristics_count; j++) {
283
if (ar->characteristics[j].value)
284
free (ar->characteristics[j].value);
286
if (ar->characteristics)
287
free (ar->characteristics);
289
free (ar->group_name);
291
free (ar->attr_name);
293
free (ar->attr_path);
298
/* Free process group structures */
299
/* alloc in bp_utils.c bp_parse_pgs() first loop */
300
//printf ("pgs: %d\n", fh->mfooter.pgs_count);
303
pgs_root = pgs_root->next;
304
//printf("%d\tpg pid=%d addr=%x next=%x\n",i, pr->process_id, pr, pr->next);
306
free(pr->group_name);
307
if (pr->time_index_name)
308
free(pr->time_index_name);
312
/* Free variable structures in BP_GROUP_VAR */
315
for (i=0;i<gh->group_count;i++) {
316
if (gh->time_index[j][i])
317
free(gh->time_index[j][i]);
319
if (gh->time_index[j])
320
free(gh->time_index[j]);
322
free (gh->time_index);
324
for (i=0;i<gh->group_count;i++) {
326
free(gh->namelist[i]);
331
for (i=0;i<fh->mfooter.vars_count;i++) {
332
if (gh->var_namelist[i])
333
free(gh->var_namelist[i]);
334
if (gh->var_offsets[i])
335
free(gh->var_offsets[i]);
337
if (gh->var_namelist)
338
free (gh->var_namelist);
341
free(gh->var_offsets);
343
if (gh->var_counts_per_group)
344
free(gh->var_counts_per_group);
347
free (gh->pg_offsets);
352
/* Free attribute structures in BP_GROUP_ATTR */
354
for (i = 0; i < fh->mfooter.attrs_count; i++) {
355
if (ah->attr_offsets[i])
356
free(ah->attr_offsets[i]);
357
if (ah->attr_namelist[i])
358
free(ah->attr_namelist[i]);
360
if (ah->attr_offsets)
361
free(ah->attr_offsets);
362
if (ah->attr_namelist)
363
free(ah->attr_namelist);
364
if (ah->attr_counts_per_group)
365
free(ah->attr_counts_per_group);
376
free_namelist ((fp->group_namelist),fp->groups_count);
382
ADIOS_GROUP * adios_read_bp_gopen (ADIOS_FILE *fp, const char * grpname)
384
struct BP_FILE * fh = (struct BP_FILE *) fp->fh;
388
for (grpid=0;grpid<(fh->gvar_h->group_count);grpid++) {
389
if (!strcmp(fh->gvar_h->namelist[grpid], grpname))
392
if (grpid >= fh->gvar_h->group_count) {
393
adios_error ( err_invalid_group, "Invalid group name %s", grpname);
396
return adios_read_bp_gopen_byid(fp, grpid);
399
ADIOS_GROUP * adios_read_bp_gopen_byid (ADIOS_FILE *fp, int grpid)
401
struct BP_FILE * fh = (struct BP_FILE *) fp->fh;
402
struct BP_GROUP * gh;
407
if (grpid < 0 || grpid >= fh->gvar_h->group_count) {
408
adios_error ( err_invalid_group, "Invalid group index %d", grpid);
412
gh = (struct BP_GROUP *) malloc(sizeof(struct BP_GROUP));
414
adios_error ( err_no_memory, "Could not allocate memory for group info");
418
gp = (ADIOS_GROUP *) malloc(sizeof(ADIOS_GROUP));
420
adios_error ( err_no_memory, "Could not allocate memory for group info");
425
/* set offset index of variables (which is a long list of all vars in all groups) in this group */
427
for (i=0; i<grpid; i++)
428
offset += fh->gvar_h->var_counts_per_group[i];
430
/* gh->vars_root will point to the list of vars in this group */
431
gh->vars_root = fh->vars_root;
432
for (i=0; i<offset; i++)
433
gh->vars_root = gh->vars_root->next;
435
gh->group_id = grpid;
436
gh->vars_offset = offset;
437
gh->vars_count = fh->gvar_h->var_counts_per_group[grpid];
439
/* set offset of attributes in this group */
442
offset += fh->gattr_h->attr_counts_per_group[i];
444
/* gh->attrs_root will point to the list of vars in this group */
445
gh->attrs_root = fh->attrs_root;
446
for (i=0; i<offset; i++)
447
gh->attrs_root = gh->attrs_root->next;
449
gh->attrs_offset = offset;
450
gh->attrs_count = fh->gattr_h->attr_counts_per_group[grpid];
454
/* fill out ADIOS_GROUP struct */
456
gp->gh = (uint64_t) gh;
458
gp->vars_count = gh->vars_count;
459
gp->attrs_count = gh->attrs_count;
461
offset = gh->vars_offset;
462
alloc_namelist (&(gp->var_namelist), gp->vars_count);
463
for (i=0;i<gp->vars_count;i++) {
464
if (!gp->var_namelist[i]) {
465
adios_error (err_no_memory, "Could not allocate buffer for %d strings in adios_gopen()", gp->vars_count);
466
adios_read_bp_gclose(gp);
470
strcpy(gp->var_namelist[i], gh->fh->gvar_h->var_namelist[i+offset]);
473
offset = gh->attrs_offset;
474
alloc_namelist (&(gp->attr_namelist), gp->attrs_count);
475
for (i=0;i<gp->attrs_count;i++) {
476
if (!gp->attr_namelist[i]) {
477
adios_error (err_no_memory, "Could not allocate buffer for %d strings in adios_gopen()", gp->vars_count);
478
adios_read_bp_gclose(gp);
482
strcpy(gp->attr_namelist[i], gh->fh->gattr_h->attr_namelist[i+offset]);
489
int adios_read_bp_gclose (ADIOS_GROUP *gp)
491
struct BP_GROUP * gh = (struct BP_GROUP *) gp->gh;
495
adios_error (err_invalid_group_struct, "group handle is NULL!");
496
return err_invalid_group_struct;
501
free_namelist ((gp->var_namelist),gp->vars_count);
502
free_namelist ((gp->attr_namelist),gp->attrs_count);
509
int adios_read_bp_get_attr (ADIOS_GROUP * gp, const char * attrname, enum ADIOS_DATATYPES * type,
510
int * size, void ** data)
512
// Find the attribute: full path is stored with a starting /
513
// Like in HDF5, we need to match names given with or without the starting /
514
// startpos is 0 or 1 to indicate if the argument has starting / or not
516
int vstartpos = 0, fstartpos = 0;
517
struct BP_GROUP * gh = (struct BP_GROUP *)gp->gh;
522
adios_error (err_invalid_group_struct, "Null pointer passed as group to adios_get_attr()");
526
adios_error (err_invalid_attrname, "Null pointer passed as attribute name to adios_get_attr()!");
530
offset = gh->attrs_offset;
532
if (attrname[0] == '/')
534
for (attrid=0; attrid<(gp->attrs_count);attrid++) {
535
//if (gp->attr_namelist[attrid][0] == '/')
536
if (gh->fh->gattr_h->attr_namelist[attrid+offset][0] == '/')
538
//if (!strcmp(gp->attr_namelist[attrid]+fstartpos, attrname+vstartpos))
539
if (!strcmp(gh->fh->gattr_h->attr_namelist[attrid+offset]+fstartpos, attrname+vstartpos))
542
if (attrid >= gp->attrs_count) {
543
adios_error ( err_invalid_attrname, "Invalid attribute name %s", attrname);
547
return adios_read_bp_get_attr_byid(gp, attrid, type, size, data);
550
int adios_read_bp_get_attr_byid (ADIOS_GROUP * gp, int attrid,
551
enum ADIOS_DATATYPES * type, int * size, void ** data)
553
int i, offset, count;
554
struct BP_GROUP * gh;
556
struct adios_index_attribute_struct_v1 * attr_root;
557
struct adios_index_var_struct_v1 * var_root;
562
adios_error (err_invalid_group_struct, "Null pointer passed as group to adios_get_attr()");
565
gh = (struct BP_GROUP *) gp->gh;
567
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh group handle is NULL!");
572
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh->fh file handle is NULL!");
575
if (attrid < 0 || attrid >= gh->attrs_count) {
576
adios_error (err_invalid_attrid, "Invalid attribute id %d (allowed 0..%d)", attrid, gh->attrs_count);
580
attr_root = gh->attrs_root; /* need to traverse the attribute list of the group */
581
for (i = 0; i < attrid && attr_root; i++)
582
attr_root = attr_root->next;
584
adios_error (err_corrupted_attribute, "Attribute id=%d is valid but was not found in internal data structures!",attrid);
588
file_is_fortran = (fh->pgs_root->adios_host_language_fortran == adios_flag_yes);
590
if (attr_root->characteristics[0].value) {
591
/* Attribute has its own value */
592
*size = bp_get_type_size (attr_root->type, attr_root->characteristics[0].value);
593
*type = attr_root->type;
594
*data = (void *) malloc (*size);
596
memcpy(*data, attr_root->characteristics[0].value, *size);
598
else if (attr_root->characteristics[0].var_id) {
599
/* Attribute is a reference to a variable */
600
/* FIXME: var ids are not unique in BP. If a group of variables are written several
601
times under different path using adios_set_path(), the id of a variable is always
602
the same (should be different). As a temporary fix, we look first for a matching
603
id plus path between an attribute and a variable. If not found, then we look for
604
a match on the ids only.*/
605
var_root = gh->vars_root;
607
if (var_root->id == attr_root->characteristics[0].var_id &&
608
!strcmp(var_root->var_path, attr_root->attr_path))
610
var_root = var_root->next;
613
var_root = gh->vars_root;
615
if (var_root->id == attr_root->characteristics[0].var_id)
617
var_root = var_root->next;
622
adios_error (err_invalid_attribute_reference,
623
"Attribute %s/%s in group %s is a reference to variable ID %d, which is not found",
624
attr_root->attr_path, attr_root->attr_name, attr_root->group_name,
625
attr_root->characteristics[0].var_id);
629
/* default values in case of error */
632
*type = attr_root->type;
634
/* FIXME: variable and attribute type may not match, then a conversion is needed. */
636
1. attr has no type, var is byte array ==> string
637
2. attr has no type, var is not byte array ==> var type
638
3. attr is string, var is byte array ==> string
639
4. attr type == var type ==> var type
640
5. attr type != var type ==> attr type and conversion needed
642
/* Error check: attr cannot reference an array in general */
643
if (var_root->characteristics[0].dims.count > 0) {
644
if ( (var_root->type == adios_byte || var_root->type == adios_unsigned_byte) &&
645
(attr_root->type == adios_unknown || attr_root->type == adios_string) &&
646
(var_root->characteristics[0].dims.count == 1)) {
647
; // this conversions are allowed
649
adios_error (err_invalid_attribute_reference,
650
"Attribute %s/%s in group %s, typeid=%d is a reference to an %d-dimensional array variable "
651
"%s/%s of type %s, which is not supported in ADIOS",
652
attr_root->attr_path, attr_root->attr_name, attr_root->group_name, attr_root->type,
653
var_root->characteristics[0].dims.count,
654
var_root->var_path, var_root->var_name, common_read_type_to_string(var_root->type));
659
if ( (attr_root->type == adios_unknown || attr_root->type == adios_string) &&
660
(var_root->type == adios_byte || var_root->type == adios_unsigned_byte) &&
661
(var_root->characteristics[0].dims.count == 1) ) {
662
/* 1D byte arrays are converted to string */
663
/* 1. read in variable */
666
uint64_t start, count;
669
count = var_root->characteristics[0].dims.dims[0];
670
snprintf(varname, 512, "%s/%s", var_root->var_path, var_root->var_name);
671
tmpdata = (char *) malloc (count+1);
672
if (tmpdata == NULL) {
673
adios_error (err_no_memory,
674
"Cannot allocate memory of %lld bytes for reading in data for attribute %s/%s of group %s.",
675
count, attr_root->attr_path, attr_root->attr_name, attr_root->group_name);
679
status = adios_read_bp_read_var (gp, varname, &start, &count, tmpdata);
682
char *msg = strdup(adios_get_last_errmsg());
683
adios_error ((enum ADIOS_ERRCODES) status,
684
"Cannot read data of variable %s/%s for attribute %s/%s of group %s: %s",
685
var_root->var_path, var_root->var_name,
686
attr_root->attr_path, attr_root->attr_name, attr_root->group_name,
693
*type = adios_string;
694
if (file_is_fortran) {
695
/* Fortran byte array to C string */
696
*data = futils_fstr_to_cstr( tmpdata, (int)count); /* FIXME: supports only 2GB strings... */
697
*size = strlen( (char *)data );
700
/* C array to C string */
701
tmpdata[count] = '\0';
706
/* other types are inherited */
707
*type = var_root->type;
708
*size = bp_get_type_size (var_root->type, var_root->characteristics[0].value);
709
*data = (void *) malloc (*size);
711
memcpy(*data, var_root->characteristics[0].value, *size);
719
/* Reverse the order in an array in place.
720
use swapping from Fortran/column-major order to ADIOS-read-api/C/row-major order and back
722
static void swap_order(int n, uint64_t *array, int *timedim)
726
for (i=0; i<n/2; i++) {
728
array[i] = array[n-1-i];
732
*timedim = (n-1) - *timedim; // swap the time dimension too
735
/* Look up variable id based on variable name.
736
Return index 0..gp->vars_count-1 if found, -1 otherwise
738
static int adios_read_bp_find_var(ADIOS_GROUP *gp, const char *varname)
740
// Find the variable: full path is stored with a starting /
741
// Like in HDF5, we need to match names given with or without the starting /
742
// startpos is 0 or 1 to indicate if the argument has starting / or not
744
int vstartpos = 0, fstartpos;
745
struct BP_GROUP * gh = (struct BP_GROUP *)gp->gh;
750
adios_error (err_invalid_group_struct, "Null pointer passed as group");
754
adios_error (err_invalid_varname, "Null pointer passed as variable name!");
758
/* Search in gp->fh->gvar_h->var_namelist instead of gp->var_namelist, because that
759
one comes back from the user. One idiot (who writes this comment) sorted the
760
list in place after gopen and before inq_var.
762
offset = gh->vars_offset;
764
if (varname[0] == '/')
766
for (varid=0; varid<(gp->vars_count);varid++) {
768
/* if (gp->var_namelist[varid][0] == '/') */
770
if (gh->fh->gvar_h->var_namelist[varid+offset][0] == '/')
772
/*if (!strcmp(gp->var_namelist[varid]+fstartpos, varname+vstartpos))*/
773
if (!strcmp(gh->fh->gvar_h->var_namelist[varid+offset]+fstartpos, varname+vstartpos))
776
if (varid >= gp->vars_count) {
777
adios_error (err_invalid_varname, "Invalid variable name %s", varname);
783
// NCSU - For custom memory allocation
784
#define CALLOC(var, num, sz, comment)\
786
var = calloc (num, sz); \
788
adios_error_at_line (err_no_memory, __FILE__, __LINE__, "Could not allocate memory for ", comment, " in common_read_get_characteristics"); \
793
#define MALLOC(var,sz,comment)\
797
adios_error_at_line (err_no_memory, __FILE__, __LINE__, "Could not allocate memory for ", comment, " in common_read_get_characteristics"); \
802
// NCSU - Reading the statistics
803
/** Get value and statistics, allocate space for them too */
804
static void adios_read_bp_get_characteristics (struct adios_index_var_struct_v1 * var_root, ADIOS_VARINFO *vi)
806
int i, j, c, count = 1;
807
int size, sum_size, sum_type;
811
vi->gmin = vi->gmax = NULL;
813
vi->mins = vi->maxs = NULL;
819
// set value for scalars
820
if (var_root->characteristics [0].value) {
821
size = bp_get_type_size(var_root->type, var_root->characteristics [0].value);
822
vi->value = (void *) malloc (size);
825
memcpy(vi->value, var_root->characteristics [0].value, size);
827
adios_error_at_line (err_no_memory, __FILE__, __LINE__, "Could not allocate memory for value in common_read_get_characteristics");
834
int npgs = var_root->characteristics_count, timestep, ntimes = -1;
835
uint64_t gcnt = 0, * cnts;
837
double *gsum = NULL, *gsum_square = NULL;
838
double **sums = NULL, **sum_squares = NULL;
841
memset (map, -1, sizeof(map));
843
// Bitmap shows which statistical information has been calculated
845
while (var_root->characteristics[0].bitmap >> j)
847
if ((var_root->characteristics[0].bitmap >> j) & 1)
854
ntimes = vi->dims[0];
856
if (map[adios_statistic_min] != -1)
858
MALLOC(vi->mins, ntimes * sizeof(void *), "minimum per timestep");
859
for (i = 0; i < ntimes; i++)
863
if (map[adios_statistic_max] != -1)
865
MALLOC(vi->maxs, ntimes * sizeof(void *), "maximum per timestep");
866
for (i = 0; i < ntimes; i++)
870
if (map[adios_statistic_sum] != -1)
872
MALLOC(sums, ntimes * sizeof(double *), "summation per timestep");
873
MALLOC(vi->avgs, ntimes * sizeof(double *), "average per timestep");
875
for (i = 0; i < ntimes; i++)
876
sums[i] = vi->avgs[i] = 0;
878
CALLOC(cnts, ntimes, sizeof(uint64_t), "count of elements per timestep");
881
if (map[adios_statistic_sum_square] != -1)
883
MALLOC(sum_squares, ntimes * sizeof(double *), "summation per timestep");
884
MALLOC(vi->std_devs, ntimes * sizeof(double *), "standard deviation per timestep");
886
for (i = 0; i < ntimes; i++)
887
vi->std_devs[i] = sum_squares[i] = 0;
891
if (map[adios_statistic_hist] != -1 && (var_root->characteristics[0].stats[0][map[adios_statistic_hist]].data))
893
struct adios_index_characteristics_stat_struct * stats = var_root->characteristics[0].stats[0];
894
struct adios_index_characteristics_hist_struct * hist = stats[map[adios_statistic_hist]].data;
895
int num_breaks = hist->num_breaks;
897
MALLOC(vi->hist, sizeof(struct ADIOS_HIST), "histogram");
898
MALLOC(vi->hist->breaks, num_breaks * sizeof(double), "break points of histogram");
899
MALLOC(vi->hist->gfrequencies, (num_breaks + 1) * sizeof(uint32_t), "global frequencies of histogram");
901
vi->hist->num_breaks = hist->num_breaks;
902
vi->hist->min = hist->min;
903
vi->hist->max = hist->max;
905
memcpy(vi->hist->breaks, hist->breaks, num_breaks * sizeof(double));
906
CALLOC(vi->hist->gfrequencies, (num_breaks + 1), bp_get_type_size(adios_unsigned_integer, ""), "global frequency");
910
MALLOC(vi->hist->frequenciess, (ntimes * sizeof(int32_t *)), "frequencies for timesteps");
911
for(i = 0; i < ntimes; i++)
912
CALLOC(vi->hist->frequenciess[i], (num_breaks + 1), bp_get_type_size(adios_unsigned_integer, ""), "frequency at timestep");
916
size = bp_get_type_size (var_root->type, "");
917
sum_size = bp_get_type_size (adios_double, "");
919
if (var_root->type == adios_complex || var_root->type == adios_double_complex)
925
if (var_root->type == adios_complex)
928
type = adios_long_double;
930
// Only a double precision returned for all complex values
931
size = bp_get_type_size (adios_double, "");
933
for (i=0; i<var_root->characteristics_count; i++)
936
timestep = var_root->characteristics[i].time_index - 1;
938
if (!var_root->characteristics[i].stats)
941
struct adios_index_characteristics_stat_struct ** stats = var_root->characteristics[i].stats;
943
if ((map[adios_statistic_finite] != -1) && (* ((uint8_t *) stats[0][map[adios_statistic_finite]].data) == 0))
946
if (map[adios_statistic_min] != -1 && stats[0][map[adios_statistic_min]].data)
949
for (c = 0; c < count; c ++)
950
data[c] = bp_value_to_double(type, stats[c][map[adios_statistic_min]].data);
953
MALLOC (vi->gmin, count * size, "global minimum")
954
for (c = 0; c < count; c ++)
955
((double * ) vi->gmin)[c] = data[c];
958
for (c = 0; c < count; c ++)
959
if (data[c] < ((double *) vi->gmin)[c])
960
((double * ) vi->gmin)[c] = data[c];
964
if(!vi->mins[timestep]) {
965
MALLOC (vi->mins[timestep], count * size, "minimum per timestep")
966
for (c = 0; c < count; c ++)
967
((double **) vi->mins)[timestep][c] = data[c];
970
for (c = 0; c < count; c ++)
971
if (data[c] < ((double **) vi->mins)[timestep][c])
972
((double **) vi->mins)[timestep][c] = data[c];
977
if (map[adios_statistic_max] != -1 && stats[0][map[adios_statistic_max]].data)
980
for (c = 0; c < count; c ++)
981
data[c] = bp_value_to_double(type, stats[c][map[adios_statistic_max]].data);
984
MALLOC (vi->gmax, count * size, "global minimum")
985
for (c = 0; c < count; c ++)
986
((double * ) vi->gmax)[c] = data[c];
989
for (c = 0; c < count; c ++)
990
if (data[c] > ((double *) vi->gmax)[c])
991
((double * ) vi->gmax)[c] = data[c];
995
if(!vi->maxs[timestep]) {
996
MALLOC (vi->maxs[timestep], count * size, "minimum per timestep")
997
for (c = 0; c < count; c ++)
998
((double **) vi->maxs)[timestep][c] = data[c];
1001
for (c = 0; c < count; c ++)
1002
if (data[c] > ((double **) vi->maxs)[timestep][c])
1003
((double **) vi->maxs)[timestep][c] = data[c];
1008
if (map[adios_statistic_sum] != -1 && stats[0][map[adios_statistic_sum]].data)
1011
for (c = 0; c < count; c ++)
1012
data[c] = bp_value_to_double(type, stats[c][map[adios_statistic_sum]].data);
1015
MALLOC(gsum, count * sum_size, "global summation")
1016
for (c = 0; c < count; c ++)
1020
for (c = 0; c < count; c ++)
1021
gsum[c] = gsum[c] + data[c];
1025
if(!sums[timestep]) {
1026
MALLOC(sums[timestep], count * sum_size, "summation per timestep")
1027
for (c = 0; c < count; c ++)
1028
sums[timestep][c] = data[c];
1031
for (c = 0; c < count; c ++)
1032
sums[timestep][c] = sums[timestep][c] + data[c];
1037
if (map[adios_statistic_sum_square] != -1 && stats[0][map[adios_statistic_sum_square]].data)
1040
for (c = 0; c < count; c ++)
1041
data[c] = bp_value_to_double(type, stats[c][map[adios_statistic_sum_square]].data);
1044
MALLOC(gsum_square, count * sum_size, "global summation of squares")
1045
for (c = 0; c < count; c ++)
1046
gsum_square[c] = data[c];
1049
for (c = 0; c < count; c ++)
1050
gsum_square[c] = gsum_square[c] + data[c];
1054
if(!sum_squares[timestep]) {
1055
MALLOC(sum_squares[timestep], count * sum_size, "summation of square per timestep")
1056
for (c = 0; c < count; c ++)
1057
sum_squares[timestep][c] = data[c];
1060
for (c = 0; c < count; c ++)
1061
sum_squares[timestep][c] = sum_squares[timestep][c] + data[c];
1066
if (map[adios_statistic_cnt] != -1 && stats[0][map[adios_statistic_cnt]].data)
1069
cnts[timestep] += * ((uint32_t *) stats[0][map[adios_statistic_cnt]].data);
1070
gcnt += * (uint32_t *) stats[0][map[adios_statistic_cnt]].data;
1074
if(ntimes > 0 && vi->gmin && (map[adios_statistic_sum] != -1) && (map[adios_statistic_sum_square] != -1)) {
1075
// min, max, summation exists only for arrays
1076
// Calculate average / timestep
1078
for(timestep = 0; timestep < ntimes; timestep ++) {
1079
MALLOC(vi->avgs[timestep], count * sum_size, "average per timestep")
1080
for (c = 0; c < count; c ++)
1081
vi->avgs[timestep][c] = sums[timestep][c] / cnts[timestep];
1083
MALLOC(vi->std_devs[timestep], count * sum_size, "standard deviation per timestep")
1084
for (c = 0; c < count; c ++)
1085
vi->std_devs[timestep][c] = sqrt((sum_squares[timestep][c] / cnts[timestep]) - (vi->avgs[timestep][c] * vi->avgs[timestep][c]));
1087
free (sums[timestep]);
1088
free (sum_squares[timestep]);
1092
// Calculate global average
1093
if(vi->gmin && gsum && (map[adios_statistic_sum] != -1) && (map[adios_statistic_sum_square] != -1)) {
1094
MALLOC(vi->gavg, count * sum_size, "global average")
1097
for (c = 0; c < count; c ++)
1098
vi->gavg[c] = gsum[c] / gcnt;
1100
for (c = 0; c < count; c ++)
1101
vi->gavg[c] = gsum[c];
1103
MALLOC(vi->gstd_dev, count * sum_size, "global average")
1104
if(vi->gavg && gcnt > 0)
1105
for (c = 0; c < count; c ++)
1106
vi->gstd_dev[c] = sqrt(gsum_square[c] / gcnt - (vi->gavg[c] * vi->gavg[c]));
1108
for (c = 0; c < count; c ++)
1109
vi->gstd_dev[c] = 0;
1115
for (i=0; i<var_root->characteristics_count; i++)
1118
timestep = var_root->characteristics[i].time_index - 1;
1119
//timestep = i / (npgs / ntimes);
1121
if (!var_root->characteristics[i].stats)
1124
struct adios_index_characteristics_stat_struct * stats = var_root->characteristics[i].stats[0];
1125
struct adios_index_characteristics_hist_struct * hist = stats[map[adios_statistic_hist]].data;
1127
if (map[adios_statistic_finite] != -1 && (* ((uint8_t *) stats[map[adios_statistic_finite]].data) == 0))
1130
if (map[adios_statistic_min] != -1 && stats[map[adios_statistic_min]].data)
1133
MALLOC (vi->gmin, size, "global minimum")
1134
memcpy(vi->gmin, stats[map[adios_statistic_min]].data, size);
1136
} else if (adios_lt(var_root->type, stats[map[adios_statistic_min]].data, vi->gmin)){
1137
memcpy(vi->gmin, stats[map[adios_statistic_min]].data, size);
1141
if(!vi->mins[timestep]) {
1142
MALLOC (vi->mins[timestep], size, "minimum per timestep")
1143
memcpy(vi->mins[timestep], stats[map[adios_statistic_min]].data, size);
1145
} else if (adios_lt(var_root->type, stats[map[adios_statistic_min]].data, vi->mins[timestep])) {
1146
memcpy(vi->mins[timestep], stats[map[adios_statistic_min]].data, size);
1151
if (map[adios_statistic_max] != -1 && stats[map[adios_statistic_max]].data)
1154
MALLOC (vi->gmax, size, "global maximum")
1155
memcpy(vi->gmax, stats[map[adios_statistic_max]].data, size);
1157
} else if (adios_lt(var_root->type, vi->gmax, stats[map[adios_statistic_max]].data))
1158
memcpy(vi->gmax, stats[map[adios_statistic_max]].data, size);
1161
if(!vi->maxs[timestep]) {
1162
MALLOC (vi->maxs[timestep], size, "maximum per timestep")
1163
memcpy(vi->maxs[timestep], stats[map[adios_statistic_max]].data, size);
1165
} else if (adios_lt(var_root->type, vi->maxs[timestep], stats[map[adios_statistic_max]].data)) {
1166
memcpy(vi->maxs[timestep], stats[map[adios_statistic_max]].data, size);
1171
if (map[adios_statistic_sum] != -1 && stats[map[adios_statistic_sum]].data)
1174
MALLOC(gsum, sum_size, "global summation")
1175
memcpy(gsum, stats[map[adios_statistic_sum]].data, sum_size);
1178
*gsum = *gsum + * ((double *) stats[map[adios_statistic_sum]].data);
1182
if(!sums[timestep]) {
1183
MALLOC(sums[timestep], sum_size, "summation per timestep")
1184
memcpy(sums[timestep], stats[map[adios_statistic_sum]].data, sum_size);
1187
*sums[timestep] = *sums[timestep] + * ((double *) stats[map[adios_statistic_sum]].data);
1192
if (map[adios_statistic_sum_square] != -1 && stats[map[adios_statistic_sum_square]].data)
1195
MALLOC(gsum_square, sum_size, "global summation of squares")
1196
memcpy(gsum_square, stats[map[adios_statistic_sum_square]].data, sum_size);
1199
*gsum_square = *gsum_square + * ((double *) stats[map[adios_statistic_sum_square]].data);
1203
if(!sum_squares[timestep]) {
1204
MALLOC(sum_squares[timestep], sum_size, "summation of square per timestep")
1205
memcpy(sum_squares[timestep], stats[map[adios_statistic_sum_square]].data, sum_size);
1208
*sum_squares[timestep] = *sum_squares[timestep] + * ((double *) stats[map[adios_statistic_sum_square]].data);
1213
if(map[adios_statistic_hist] != -1 && stats[map[adios_statistic_hist]].data)
1215
for(j = 0; j <= vi->hist->num_breaks; j++)
1217
uint32_t freq = hist->frequencies[j];
1218
vi->hist->gfrequencies[j] += freq;
1220
vi->hist->frequenciess[timestep][j] += freq;
1224
if (map[adios_statistic_cnt] != -1 && stats[map[adios_statistic_cnt]].data)
1227
cnts[timestep] += * (uint32_t *) stats[map[adios_statistic_cnt]].data;
1228
gcnt += * (uint32_t *) stats[map[adios_statistic_cnt]].data;
1232
if(ntimes > 0 && vi->gmin && (map[adios_statistic_sum] != -1) && (map[adios_statistic_sum_square] != -1)) {
1233
// min, max, summation exists only for arrays
1234
// Calculate average / timestep
1236
for(timestep = 0; timestep < ntimes; timestep ++) {
1237
MALLOC(vi->avgs[timestep], sum_size, "average per timestep")
1238
*(vi->avgs[timestep]) = *(sums[timestep]) / cnts[timestep];
1240
MALLOC(vi->std_devs[timestep], sum_size, "standard deviation per timestep")
1241
*(vi->std_devs[timestep]) = sqrt(*(sum_squares[timestep]) / cnts[timestep] - ((*(vi->avgs[timestep]) * (*(vi->avgs[timestep])))));
1243
free (sums[timestep]);
1244
free (sum_squares[timestep]);
1248
// Calculate global average
1249
if(vi->gmin && gsum && (map[adios_statistic_sum] != -1) && (map[adios_statistic_sum_square] != -1)) {
1250
MALLOC(vi->gavg, sum_size, "global average")
1252
*vi->gavg = *gsum / gcnt;
1256
MALLOC(vi->gstd_dev, sum_size, "global average")
1257
if(vi->gavg && gcnt > 0)
1258
*vi->gstd_dev = sqrt(*gsum_square / gcnt - ((*(vi->gavg)) * (*(vi->gavg))));
1264
if (!vi->value && vi->gmin) {
1265
vi->value = vi->gmin; // arrays have no value but we assign here the minimum
1269
vi->gmin = vi->value; // scalars have value but not min
1272
vi->gmax = vi->value; // scalars have value but not max
1280
if (sum_squares && gsum_square) {
1286
/* get local and global dimensions and offsets from a variable characteristics
1287
return: 1 = it is a global array, 0 = local array
1289
static int adios_read_bp_get_dimensioncharacteristics(struct adios_index_characteristic_struct_v1 *ch,
1290
uint64_t *ldims, uint64_t *gdims, uint64_t *offsets)
1292
int is_global=0; // global array or just an array written by one process?
1293
int ndim = ch->dims.count;
1296
for (k=0; k < ndim; k++) {
1297
ldims[k] = ch->dims.dims[k*3];
1298
gdims[k] = ch->dims.dims[k*3+1];
1299
offsets[k] = ch->dims.dims[k*3+2];
1300
is_global = is_global || gdims[k];
1305
static void adios_read_bp_get_dimensions (struct adios_index_var_struct_v1 *var_root, int ntsteps, int file_is_fortran,
1306
int *ndim, uint64_t **dims, int *timedim)
1309
int is_global; // global array or just an array written by one process?
1312
uint64_t offsets[32];
1314
/* Get dimension information */
1315
*ndim = var_root->characteristics [0].dims.count;
1319
/* done with this scalar variable */
1323
*dims = (uint64_t *) malloc (sizeof(uint64_t) * (*ndim));
1324
memset(*dims,0,sizeof(uint64_t)*(*ndim));
1326
is_global = adios_read_bp_get_dimensioncharacteristics( &(var_root->characteristics[0]),
1327
ldims, gdims, offsets);
1331
for (i=0; i < *ndim; i++) {
1332
/* size of time dimension is always registered as 1 for an array */
1333
if (ldims[i] == 1 && var_root->characteristics_count > 1) {
1335
(*dims)[i] = ntsteps;
1337
(*dims)[i] = ldims[i];
1339
gdims[i] = ldims[i];
1344
time dimension: ldims=1, gdims=0
1345
in C array, it can only be the first dim
1346
in Fortran array, it can only be the last dim
1347
(always the slowest changing dim)
1349
if (gdims[*ndim-1] == 0)
1351
if (!file_is_fortran) {
1352
/* first dimension is the time (C array)
1353
* ldims[0] = 1 but gdims does not contain time info and
1354
* gdims[0] is 1st data dimension and
1355
* gdims is shorter by one value than ldims in case of C.
1356
* Therefore, gdims[*ndim-1] = 0 if there is a time dimension.
1360
if (*ndim > 1 && ldims[0] != 1) {
1361
fprintf(stderr,"ADIOS Error: this is a BP file with C ordering but we didn't find"
1362
"an array to have time dimension in the first dimension. l:g:o = (");
1363
for (i=0; i < *ndim; i++) {
1364
fprintf(stderr,"%llu:%llu:%llu%s", ldims[i], gdims[i], offsets[i], (i<*ndim-1 ? ", " : "") );
1366
fprintf(stderr, ")\n");
1368
(*dims)[0] = ntsteps;
1369
for (i=1; i < *ndim; i++)
1370
(*dims)[i]=gdims[i-1];
1372
// last dimension is the time (Fortran array)
1373
*timedim = *ndim - 1;
1375
if (*ndim > 1 && ldims[*ndim-1] != 1) {
1376
fprintf(stderr,"ADIOS Error: this is a BP file with Fortran array ordering but we didn't find"
1377
"an array to have time dimension in the last dimension. l:g:o = (");
1378
for (i=0; i < *ndim; i++) {
1379
fprintf(stderr,"%llu:%llu:%llu%s", ldims[i], gdims[i], offsets[i], (i<*ndim-1 ? ", " : "") );
1381
fprintf(stderr, ")\n");
1383
for (i=0; i < *ndim-1; i++)
1384
(*dims)[i]=gdims[i];
1385
(*dims)[*timedim] = ntsteps;
1388
// no time dimenstion
1389
for (i=0; i < *ndim; i++)
1390
(*dims)[i]=gdims[i];
1395
ADIOS_VARINFO * adios_read_bp_inq_var (ADIOS_GROUP *gp, const char * varname)
1397
int varid = adios_read_bp_find_var(gp, varname);
1400
return adios_read_bp_inq_var_byid(gp, varid);
1403
ADIOS_VARINFO * adios_read_bp_inq_var_byid (ADIOS_GROUP *gp, int varid)
1405
struct BP_GROUP * gh;
1406
struct BP_FILE * fh;
1408
int file_is_fortran;
1409
struct adios_index_var_struct_v1 * var_root;
1414
adios_error (err_invalid_group_struct, "Null pointer passed as group to adios_inq_var()");
1417
gh = (struct BP_GROUP *) gp->gh;
1419
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh group handle is NULL!");
1424
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh->fh file handle is NULL!");
1427
if (varid < 0 || varid >= gh->vars_count) {
1428
adios_error (err_invalid_varid, "Invalid variable id %d (allowed 0..%d)", varid, gh->vars_count);
1431
vi = (ADIOS_VARINFO *) malloc(sizeof(ADIOS_VARINFO));
1433
adios_error ( err_no_memory, "Could not allocate memory for variable info");
1438
file_is_fortran = (fh->pgs_root->adios_host_language_fortran == adios_flag_yes);
1440
var_root = gh->vars_root; /* first variable of this group. Need to traverse the list */
1441
for (i=0; i<varid && var_root; i++) {
1442
var_root = var_root->next;
1446
adios_error (err_corrupted_variable, "Variable id=%d is valid but was not found in internal data structures!",varid);
1453
vi->type = var_root->type;
1454
if (!var_root->characteristics_count) {
1455
adios_error (err_corrupted_variable, "Variable %s does not have information on dimensions",
1456
gp->var_namelist[varid]);
1460
vi->characteristics_count = var_root->characteristics_count;
1462
/* Get value or min/max */
1464
adios_read_bp_get_dimensions (var_root, fh->tidx_stop - fh->tidx_start + 1, file_is_fortran,
1465
&(vi->ndim), &(vi->dims), &(vi->timedim));
1467
if (file_is_fortran != futils_is_called_from_fortran()) {
1468
/* If this is a Fortran written file and this is called from C code/
1469
or this is a C written file and this is called from Fortran code ==>
1470
We need to reverse the order of the dimensions */
1471
swap_order(vi->ndim, vi->dims, &(vi->timedim));
1472
/*printf("File was written from %s and read now from %s, so we swap order of dimensions\n",
1473
(file_is_fortran ? "Fortran" : "C"), (futils_is_called_from_fortran() ? "Fortran" : "C"));*/
1476
adios_read_bp_get_characteristics (var_root, vi);
1481
void adios_read_bp_free_varinfo (ADIOS_VARINFO *vp)
1484
if (vp->dims) free(vp->dims);
1485
if (vp->value) free(vp->value);
1486
if (vp->gmin && vp->gmin != vp->value) free(vp->gmin);
1487
if (vp->gmax && vp->gmax != vp->value) free(vp->gmax);
1488
//if (vp->mins) free(vp->mins);
1489
//if (vp->maxs) free(vp->maxs);
1494
#define MPI_FILE_READ_OPS \
1495
bp_realloc_aligned(fh->b, slice_size); \
1496
fh->b->offset = 0; \
1498
MPI_File_seek (fh->mpi_fh \
1499
,(MPI_Offset)slice_offset \
1503
MPI_File_read (fh->mpi_fh \
1509
fh->b->offset = 0; \
1511
//We also need to be able to read old .bp which doesn't have 'payload_offset'
1512
#define MPI_FILE_READ_OPS1 \
1513
MPI_File_seek (fh->mpi_fh \
1514
,(MPI_Offset) var_root->characteristics[start_idx + idx].offset \
1516
MPI_File_read (fh->mpi_fh, fh->b->buff, 8, MPI_BYTE, &status); \
1517
tmpcount= *((uint64_t*)fh->b->buff); \
1519
bp_realloc_aligned(fh->b, tmpcount + 8); \
1520
fh->b->offset = 0; \
1522
MPI_File_seek (fh->mpi_fh \
1523
,(MPI_Offset) (var_root->characteristics[start_idx + idx].offset) \
1525
MPI_File_read (fh->mpi_fh, fh->b->buff, tmpcount + 8, MPI_BYTE, &status); \
1526
fh->b->offset = 0; \
1527
adios_parse_var_data_header_v1 (fh->b, &var_header); \
1531
#define MPI_FILE_READ_OPS2 \
1532
bp_realloc_aligned(fh->b, slice_size); \
1533
fh->b->offset = 0; \
1536
sfh = get_BP_file_handle (fh->sfh \
1537
,var_root->characteristics[start_idx + idx].file_index \
1542
char * ch, * name_no_path, * name; \
1543
struct BP_file_handle * new_h = \
1544
(struct BP_file_handle *) malloc (sizeof (struct BP_file_handle)); \
1545
new_h->file_index = var_root->characteristics[start_idx + idx].file_index; \
1547
if (ch = strrchr (fh->fname, '/')) \
1549
name_no_path = malloc (strlen (ch + 1) + 1); \
1550
strcpy (name_no_path, ch + 1); \
1554
name_no_path = malloc (strlen (fh->fname) + 1); \
1555
strcpy (name_no_path, fh->fname); \
1558
name = malloc (strlen (fh->fname) + 5 + strlen (name_no_path) + 1 + 10 + 1); \
1559
sprintf (name, "%s.dir/%s.%d", fh->fname, name_no_path, new_h->file_index); \
1561
err = MPI_File_open (fh->comm \
1564
,(MPI_Info)MPI_INFO_NULL \
1567
if (err != MPI_SUCCESS) \
1569
fprintf (stderr, "can not open file %S\n", name); \
1573
add_BP_file_handle (&fh->sfh \
1578
free (name_no_path); \
1582
MPI_File_seek (*sfh \
1583
,(MPI_Offset)slice_offset \
1586
MPI_File_read (*sfh \
1592
fh->b->offset = 0; \
1595
int64_t adios_read_bp_read_var (ADIOS_GROUP * gp, const char * varname,
1596
const uint64_t * start, const uint64_t * count,
1599
struct BP_GROUP * gh;
1600
struct BP_FILE * fh;
1601
int varid, has_subfile;
1605
adios_error (err_invalid_group_struct, "Null pointer passed as group to adios_read_var()");
1606
return -adios_errno;
1609
gh = (struct BP_GROUP *) gp->gh;
1611
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh group handle is NULL!");
1612
return -adios_errno;
1617
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh->fh file handle is NULL!");
1618
return -adios_errno;
1621
varid = adios_read_bp_find_var(gp, varname);
1622
if (varid < 0 || varid >= gh->vars_count) {
1623
adios_error (err_invalid_varid, "Invalid variable id %d (allowed 0..%d)", varid, gh->vars_count);
1624
return -adios_errno;
1627
return adios_read_bp_read_var_byid(gp, varid, start, count, data);
1630
/***********************************************
1631
* This routine is to read in data in a 'local *
1632
* array fashion (as opposed to global array) *
1634
***********************************************/
1635
int64_t adios_read_bp_read_local_var (ADIOS_GROUP * gp, const char * varname,
1636
int vidx, const uint64_t * start,
1637
const uint64_t * count, void * data)
1639
struct BP_GROUP * gh;
1640
struct BP_FILE * fh;
1641
struct adios_index_var_struct_v1 * var_root;
1642
struct adios_var_header_struct_v1 var_header;
1643
struct adios_var_payload_struct_v1 var_payload;
1644
int i,j,k, t, varid, start_idx, idx;
1645
int ndim, ndim_notime, has_subfile, file_is_fortran;
1646
uint64_t size, * dims;
1647
uint64_t ldims[32], gdims[32], offsets[32];
1648
uint64_t datasize, nloop, dset_stride,var_stride, total_size=0, items_read;
1649
uint64_t count_notime[32], start_notime[32];
1650
int timedim = -1, temp_timedim, is_global = 0, size_of_type;
1651
uint64_t slice_offset, slice_size, tmpcount = 0;
1652
uint64_t datatimeoffset = 0; // offset in data to write a given timestep
1658
adios_error (err_invalid_group_struct, "Null pointer passed as group to adios_read_var()");
1659
return -adios_errno;
1662
gh = (struct BP_GROUP *) gp->gh;
1665
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh group handle is NULL!");
1666
return -adios_errno;
1672
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh->fh file handle is NULL!");
1673
return -adios_errno;
1676
varid = adios_read_bp_find_var(gp, varname);
1677
if (varid < 0 || varid >= gh->vars_count)
1679
adios_error (err_invalid_varid, "Invalid variable id %d (allowed 0..%d)", varid, gh->vars_count);
1680
return -adios_errno;
1683
/* Check if file is written out by Fortran or C */
1684
file_is_fortran = (fh->pgs_root->adios_host_language_fortran == adios_flag_yes);
1686
/* Check whether we need to handle subfiles */
1687
has_subfile = fh->mfooter.version & ADIOS_VERSION_HAVE_SUBFILE;
1689
var_root = gh->vars_root; /* first variable of this group. Need to traverse the list */
1690
for (i = 0; i< varid && var_root; i++)
1692
var_root = var_root->next;
1697
adios_error (err_corrupted_variable,
1698
"Variable id=%d is valid but was not found in internal data structures!",
1700
return -adios_errno;
1703
if (vidx < 0 || vidx >= var_root->characteristics_count)
1705
adios_error (err_out_of_bound, "idx=%d is out of bound", vidx);
1708
ndim = var_root->characteristics [vidx].dims.count;
1710
/* count_notime/start_notime are working copies of count/start */
1711
for (i = 0; i < ndim; i++)
1713
count_notime[i] = count[i];
1714
start_notime[i] = start[i];
1719
/* Fortran reader was reported of Fortran dimension order so it gives counts and starts in that order.
1720
We need to swap them here to read correctly in C order */
1721
if (futils_is_called_from_fortran())
1724
swap_order(ndim_notime, count_notime, &timedim);
1725
swap_order(ndim_notime, start_notime, &timedim);
1728
/* items_read = how many data elements are we going to read in total */
1730
for (i = 0; i < ndim_notime; i++)
1731
items_read *= count_notime[i];
1733
size_of_type = bp_get_type_size (var_root->type, var_root->characteristics [vidx].value);
1735
/* READ A SCALAR VARIABLE */
1736
if (ndim_notime == 0)
1738
slice_size = size_of_type;
1739
start_idx = 0; // OPS macros below need it
1740
idx = vidx; // OPS macros below need it
1742
if (var_root->type == adios_string)
1744
// strings are stored without \0 in file
1745
// size_of_type here includes \0 so decrease by one
1749
/* Old BP files don't have payload_offset characteristic */
1750
if (var_root->characteristics[vidx].payload_offset > 0)
1752
slice_offset = var_root->characteristics[vidx].payload_offset;
1769
memcpy((char *)data + total_size, fh->b->buff + fh->b->offset, size_of_type);
1771
if (fh->mfooter.change_endianness == adios_flag_yes)
1772
change_endianness((char *)data + total_size
1777
if (var_root->type == adios_string)
1779
// add \0 to the end of string
1780
// size_of_type here is the length of string
1781
// FIXME: how would this work for strings written over time?
1782
((char*)data + total_size)[size_of_type] = '\0';
1785
total_size += size_of_type;
1788
} /* READ A SCALAR VARIABLE END HERE */
1790
/* READ AN ARRAY VARIABLE */
1791
uint64_t write_offset = 0;
1799
uint64_t payload_size = size_of_type;
1801
/* To get ldims for the index vidx */
1802
adios_read_bp_get_dimensioncharacteristics( &(var_root->characteristics[vidx]),
1803
ldims, gdims, offsets);
1805
/* Again, a Fortran written file has the dimensions in Fortran order we need to swap here */
1806
/* Only local dims are needed for reading local vars */
1807
if (file_is_fortran)
1810
swap_order(ndim, ldims, &(i));
1814
printf("ldims = "); for (j = 0; j < ndim; j++) printf("%d ",ldims[j]); printf("\n");
1815
printf("count_notime = "); for (j = 0; j < ndim_notime; j++) printf("%d ",count_notime[j]); printf("\n");
1816
printf("start_notime = "); for (j = 0; j < ndim_notime; j++) printf("%d ",start_notime[j]); printf("\n");
1819
for (j = 0; j < ndim_notime; j++)
1821
payload_size *= ldims [j];
1823
if ( (start_notime[j] > ldims[j])
1824
|| (start_notime[j] + count_notime[j] > ldims[j]))
1826
adios_error ( err_out_of_bound, "Error: Variable (id=%d) out of bound ("
1827
"the data in dimension %d to read is %llu elements from index %llu"
1828
" but the actual data is [0,%llu])",
1829
varid, j+1, count_notime[j], start_notime[j], ldims[j] - 1);
1830
return -adios_errno;
1834
/* determined how many (fastest changing) dimensions can we read in in one read */
1835
int break_dim = ndim_notime - 1;
1836
while (break_dim > -1)
1838
if (start_notime[break_dim] == 0 && ldims[break_dim] == count_notime[break_dim])
1840
datasize *= ldims[break_dim];
1850
/* Note: MPI_FILE_READ_OPS - for reading single BP file.
1851
* MPI_FILE_READ_OPS2 - for reading those with subfiles.
1852
* MPI_FILE_READ_OPS1 - for reading old version of BP files
1853
* which don't contain "payload_offset"
1854
* Whenever to use OPS macro, start_idx and idx variable needs to be
1863
/* The slowest changing dimensions should not be read completely but
1864
we still need to read only one block */
1866
uint64_t size_in_dset = count_notime[0];
1867
uint64_t offset_in_dset = start_notime[0];
1869
slice_size = (break_dim == -1 ? datasize * size_of_type : size_in_dset * datasize * size_of_type);
1871
if (var_root->characteristics[start_idx + idx].payload_offset > 0)
1873
slice_offset = var_root->characteristics[start_idx + idx].payload_offset
1874
+ offset_in_dset * datasize * size_of_type;
1891
memcpy ((char *)data, fh->b->buff + fh->b->offset, slice_size);
1892
if (fh->mfooter.change_endianness == adios_flag_yes)
1894
change_endianness((char *)data + write_offset, slice_size, var_root->type);
1899
uint64_t stride_offset = 0;
1900
uint64_t * size_in_dset, * offset_in_dset, * offset_in_var;
1901
uint64_t start_in_payload, end_in_payload, s;
1902
uint64_t var_offset;
1903
uint64_t dset_offset;
1905
size_in_dset = (uint64_t *) malloc (8 * ndim_notime);
1906
offset_in_dset = (uint64_t *) malloc (8 * ndim_notime);
1907
offset_in_var = (uint64_t *) malloc (8 * ndim_notime);
1909
if (size_in_dset == 0 || offset_in_dset == 0 || offset_in_var == 0)
1911
adios_error (err_no_memory, "Malloc failed in %s at %d\n"
1912
, __FILE__, __LINE__
1914
return -adios_errno;
1917
for (i = 0; i < ndim_notime ; i++)
1919
size_in_dset[i] = count_notime[i];
1920
offset_in_dset[i] = start_notime[i];
1921
offset_in_var[i] = 0;
1926
for (i = ndim_notime - 1; i >= break_dim; i--)
1928
datasize *= size_in_dset[i];
1929
dset_stride *= ldims[i];
1930
var_stride *= count_notime[i];
1933
/* Calculate the size of the chunk we are trying to read in */
1934
start_in_payload = 0;
1937
for (i = ndim_notime - 1; i >= 0; i--)
1939
start_in_payload += s * offset_in_dset[i] * size_of_type;
1940
end_in_payload += s * (offset_in_dset[i] + size_in_dset[i] - 1) * size_of_type;
1943
slice_size = end_in_payload - start_in_payload + 1 * size_of_type;
1945
if (var_root->characteristics[start_idx + idx].payload_offset > 0)
1947
slice_offset = var_root->characteristics[start_idx + idx].payload_offset
1958
for ( i = 0; i < ndim_notime ; i++)
1960
offset_in_dset[i] = 0;
1965
slice_offset = start_in_payload;
1971
for (i = 0; i < ndim_notime ; i++)
1973
var_offset = offset_in_var[i] + var_offset * count_notime[i];
1974
dset_offset = offset_in_dset[i] + dset_offset * ldims[i];
1978
,fh->b->buff + fh->b->offset
1992
free (size_in_dset);
1993
free (offset_in_dset);
1994
free (offset_in_var);
1997
total_size += items_read * size_of_type;
2002
// The purpose of keeping this function is to be able
2003
// to read in old BP files. Can be deleted later on.
2004
int64_t adios_read_bp_read_var_byid1 (ADIOS_GROUP * gp,
2006
const uint64_t * start,
2007
const uint64_t * count,
2010
struct BP_GROUP * gh;
2011
struct BP_FILE * fh;
2012
int file_is_fortran;
2013
struct adios_index_var_struct_v1 * var_root;
2014
struct adios_var_header_struct_v1 var_header;
2015
struct adios_var_payload_struct_v1 var_payload;
2016
int i,j,k, idx, timestep;
2017
int start_time, stop_time;
2018
int pgoffset, pgcount, next_pgoffset,start_idx, stop_idx;
2019
int ndim, ndim_notime;
2024
uint64_t offsets[32];
2025
uint64_t datasize, nloop, dset_stride,var_stride, total_size=0, items_read;
2026
uint64_t count_notime[32], start_notime[32];
2028
int timedim = -1, temp_timedim, timedim_c;
2032
uint64_t slice_offset;
2033
uint64_t slice_size;
2034
uint64_t tmpcount = 0;
2035
uint64_t datatimeoffset = 0; // offset in data to write a given timestep
2039
adios_error (err_invalid_group_struct, "Null pointer passed as group to adios_read_var()");
2040
return -adios_errno;
2042
gh = (struct BP_GROUP *) gp->gh;
2044
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh group handle is NULL!");
2045
return -adios_errno;
2049
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh->fh file handle is NULL!");
2050
return -adios_errno;
2052
if (varid < 0 || varid >= gh->vars_count) {
2053
adios_error (err_invalid_varid, "Invalid variable id %d (allowed 0..%d)", varid, gh->vars_count);
2054
return -adios_errno;
2057
file_is_fortran = (fh->pgs_root->adios_host_language_fortran == adios_flag_yes);
2059
var_root = gh->vars_root; /* first variable of this group. Need to traverse the list */
2060
for (i=0; i<varid && var_root; i++) {
2061
var_root = var_root->next;
2065
adios_error (err_corrupted_variable, "Variable id=%d is valid but was not found in internal data structures!",varid);
2066
return -adios_errno;
2069
/* Get dimensions and flip if caller != writer language */
2070
adios_read_bp_get_dimensions (var_root, fh->tidx_stop - fh->tidx_start + 1, file_is_fortran,
2071
&ndim, &dims, &timedim);
2073
/* Here the cases in which .bp written from Fortran and C are considered separately.
2074
1) bp written from Fortran */
2075
if (file_is_fortran)
2077
/* Get the timesteps we need to read */
2080
if (timedim != ndim - 1)
2082
adios_error (err_no_data_at_timestep,"Variable (id=%d) has wrong time dimension index",
2084
return -adios_errno;
2086
if (futils_is_called_from_fortran())
2088
start_time = start[timedim] + fh->tidx_start;
2089
stop_time = start_time + count[timedim] - 1;
2093
start_time = start[0] + fh->tidx_start;
2094
stop_time = start_time + count[0] - 1;
2099
/* timeless variable, but we still need to handle the case that
2100
var is not written in the first few timesteps.
2101
This happens in Pixie3D. */
2102
for (i = 0; i < fh->mfooter.time_steps; i++)
2104
pgoffset = fh->gvar_h->time_index[0][gh->group_id][i];
2105
if (i < fh->mfooter.time_steps - 1)
2106
next_pgoffset = fh->gvar_h->time_index[0][gh->group_id][i + 1];
2110
if (fh->gvar_h->pg_offsets[pgoffset] < var_root->characteristics[0].offset
2111
&& (i == fh->mfooter.time_steps - 1
2112
||fh->gvar_h->pg_offsets[next_pgoffset] > var_root->characteristics[0].offset)
2115
start_time = fh->tidx_start + i;
2116
stop_time = start_time;
2122
/* flip dims and timedim to C order */
2123
swap_order(ndim, dims, &timedim);
2125
/* Take out the time dimension from start[] and count[] */
2126
/* if we have time dimension */
2130
if (futils_is_called_from_fortran())
2131
temp_timedim = ndim - 1;
2135
for (i = 0; i < temp_timedim; i++)
2137
count_notime[j] = count[i];
2138
start_notime[j] = start[i];
2141
i++; // skip timedim
2142
for (; i < ndim; i++)
2144
count_notime[j] = count[i];
2145
start_notime[j] = start[i];
2148
ndim_notime = ndim-1;
2151
/* if we don't have time dimension */
2153
for (i = 0; i < ndim; i++)
2155
count_notime[i] = count[i];
2156
start_notime[i] = start[i];
2161
/* 2) .bp written by C */
2164
/* Get the timesteps we need to read */
2167
/* timedim has to be the 1st dimension. To be extended to handle
2168
the cases timedim at any dimension */
2171
adios_error (err_no_data_at_timestep,"Variable (id=%d) has wrong time dimension",
2173
return -adios_errno;
2176
if (futils_is_called_from_fortran())
2178
start_time = start[ndim - 1] + fh->tidx_start;
2179
stop_time = start_time + count[ndim -1] - 1;
2183
start_time = start[0] + fh->tidx_start;
2184
stop_time = start_time + count[0] - 1;
2187
start_time = start[timedim] + fh->tidx_start;
2188
stop_time = start_time + count[timedim] - 1;
2192
/* timeless variable */
2193
start_time = fh->tidx_start;
2194
stop_time = fh->tidx_start;
2197
/* No need to flip dims, timedim as they are already in C order. */
2198
//swap_order(ndim, dims, &timedim);
2200
/* Take out the time dimension from start[] and count[] */
2201
if (timedim == -1) /* timeless variable */
2203
for (i = 0; i < ndim; i++)
2205
count_notime[i] = count[i];
2206
start_notime[i] = start[i];
2210
/* if we have time dimension */
2214
if (futils_is_called_from_fortran())
2215
temp_timedim = ndim - 1;
2219
for (i = 0; i < temp_timedim; i++)
2221
count_notime[j] = count[i];
2222
start_notime[j] = start[i];
2225
i++; // skip timedim
2226
for (; i < ndim; i++)
2228
count_notime[j] = count[i];
2229
start_notime[j] = start[i];
2232
ndim_notime = ndim - 1;
2236
/* Fortran reader was reported of Fortran dimension order so it gives counts and starts in that order.
2237
We need to swap them here to read correctly in C order */
2238
if ( futils_is_called_from_fortran()) {
2239
swap_order(ndim_notime, count_notime, &timedim);
2240
swap_order(ndim_notime, start_notime, &timedim);
2243
/* items_read = how many data elements are we going to read in total (per timestep) */
2245
for (i = 0; i < ndim_notime; i++)
2246
items_read *= count_notime[i];
2248
MPI_Comm_rank(gh->fh->comm, &rank);
2250
size_of_type = bp_get_type_size (var_root->type, var_root->characteristics [0].value);
2252
/* For each timestep, do reading separately (they are stored in different sets of process groups */
2253
for (timestep = start_time; timestep <= stop_time; timestep++) {
2255
// pgoffset = the starting offset for the given time step
2256
// pgcount = number of process groups of that time step
2257
pgoffset = fh->gvar_h->time_index[0][gh->group_id][timestep - fh->tidx_start];
2258
pgcount = fh->gvar_h->time_index[1][gh->group_id][timestep - fh->tidx_start];
2261
for (i=0;i<var_root->characteristics_count;i++) {
2262
if ( ( var_root->characteristics[i].offset > fh->gvar_h->pg_offsets[pgoffset])
2263
&& ( (pgoffset + pgcount == fh->mfooter.pgs_count)
2264
||( var_root->characteristics[i].offset < fh->gvar_h->pg_offsets[pgoffset + 1]))
2272
printf ("var_root->characteristics_count = %d\n", var_root->characteristics_count);
2273
printf ("pg offset 0 = %lld\n", fh->gvar_h->pg_offsets[pgoffset]);
2274
printf ("pg offset 1 = %lld\n", fh->gvar_h->pg_offsets[pgoffset + 1]);
2275
printf ("var offset 3 = %lld\n", var_root->characteristics[3].offset);
2276
printf ("var offset 2 = %lld\n", var_root->characteristics[2].offset);
2277
printf ("var offset 1 = %lld\n", var_root->characteristics[1].offset);
2278
printf ("pgcount = %lld\n", pgcount);
2280
for (i=var_root->characteristics_count-1;i>-1;i--) {
2281
if ( ( var_root->characteristics[i].offset > fh->gvar_h->pg_offsets[pgoffset])
2282
&& ( (pgoffset + pgcount == fh->mfooter.pgs_count)
2283
||( var_root->characteristics[i].offset < fh->gvar_h->pg_offsets[pgoffset + pgcount]))
2292
adios_error (err_no_data_at_timestep,"Variable (id=%d) has no data at %d time step",
2294
return -adios_errno;
2297
if (ndim_notime == 0) {
2298
/* READ A SCALAR VARIABLE */
2300
slice_size = size_of_type;
2301
idx = 0; // macros below need it
2303
if (var_root->type == adios_string) {
2304
// strings are stored without \0 in file
2305
// size_of_type here includes \0 so decrease by one
2309
if (var_root->characteristics[start_idx+idx].payload_offset > 0) {
2310
slice_offset = var_root->characteristics[start_idx+idx].payload_offset;
2317
memcpy((char *)data+total_size, fh->b->buff + fh->b->offset, size_of_type);
2318
if (fh->mfooter.change_endianness == adios_flag_yes) {
2319
change_endianness((char *)data+total_size, size_of_type, var_root->type);
2322
if (var_root->type == adios_string) {
2323
// add \0 to the end of string
2324
// size_of_type here is the length of string
2325
// FIXME: how would this work for strings written over time?
2326
((char*)data+total_size)[size_of_type] = '\0';
2329
total_size += size_of_type;
2333
/* READ AN ARRAY VARIABLE */
2334
//int * idx_table = (int *) malloc (sizeof(int) * pgcount);
2335
//int * idx_table = (int *) malloc (sizeof(int) * (var_root->characteristics_count - start_idx));
2336
int * idx_table = (int *) malloc (sizeof(int) * (stop_idx - start_idx + 1));
2338
uint64_t write_offset = 0;
2341
if (pgcount > var_root->characteristics_count)
2342
pgcount = var_root->characteristics_count;
2344
// loop over the list of pgs to read from one-by-one
2345
for (idx = 0; idx < stop_idx - start_idx + 1; idx++) {
2352
uint64_t payload_size = size_of_type;
2354
/* Each pg can have a different sized array, so we need the actual dimensions from it */
2355
is_global = adios_read_bp_get_dimensioncharacteristics( &(var_root->characteristics[start_idx + idx]),
2356
ldims, gdims, offsets);
2358
// we use gdims below, which is 0 for a local array; set to ldims here
2359
for (j = 0; j< ndim; j++) {
2364
/* Again, a Fortran written file has the dimensions in Fortran order we need to swap here */
2365
//if (file_is_fortran != futils_is_called_from_fortran()) {
2366
if (file_is_fortran ) {
2368
swap_order(ndim, gdims, &(i)); // i is dummy
2369
swap_order(ndim, ldims, &(i));
2370
swap_order(ndim, offsets, &(i));
2373
/* take out the time dimension */
2374
/* For C, gdims and offset are one size shorter because the timedim part is missing,
2375
so we take it out only for fortran files
2378
for (i = timedim; i < ndim-1; i++) {
2379
ldims[i] = ldims[i+1];
2380
if (file_is_fortran) {
2381
gdims[i] = gdims[i+1];
2382
offsets[i] = offsets[i+1];
2387
printf("ldims = "); for (j = 0; j<ndim; j++) printf("%d ",ldims[j]); printf("\n");
2388
printf("gdims = "); for (j = 0; j<ndim; j++) printf("%d ",gdims[j]); printf("\n");
2389
printf("offsets = "); for (j = 0; j<ndim; j++) printf("%d ",offsets[j]); printf("\n");
2390
printf("count_notime = "); for (j = 0; j<ndim_notime; j++) printf("%d ",count_notime[j]); printf("\n");
2391
printf("start_notime = "); for (j = 0; j<ndim_notime; j++) printf("%d ",start_notime[j]); printf("\n");
2393
for (j = 0; j < ndim_notime; j++) {
2395
payload_size *= ldims [j];
2397
if ( (count_notime[j] > gdims[j])
2398
|| (start_notime[j] > gdims[j])
2399
|| (start_notime[j] + count_notime[j] > gdims[j])){
2400
adios_error ( err_out_of_bound, "Error: Variable (id=%d) out of bound ("
2401
"the data in dimension %d to read is %llu elements from index %llu"
2402
" but the actual data is [0,%llu])",
2403
varid, j+1, count_notime[j], start_notime[j], gdims[j] - 1);
2404
return -adios_errno;
2407
/* check if there is any data in this pg and this dimension to read in */
2408
flag = (offsets[j] >= start_notime[j]
2409
&& offsets[j] < start_notime[j] + count_notime[j])
2410
|| (offsets[j] < start_notime[j]
2411
&& offsets[j] + ldims[j] > start_notime[j] + count_notime[j])
2412
|| (offsets[j] + ldims[j] > start_notime[j]
2413
&& offsets[j] + ldims[j] <= start_notime[j] + count_notime[j]);
2414
idx_table [idx] = idx_table[idx] && flag;
2417
if ( !idx_table[idx] ) {
2422
/* determined how many (fastest changing) dimensions can we read in in one read */
2424
for (i = ndim_notime - 1; i > -1; i--) {
2425
if (offsets[i] == start_notime[i] && ldims[i] == count_notime[i]) {
2426
datasize *= ldims[i];
2436
if (hole_break == -1) {
2437
/* The complete read happens to be exactly one pg, and the entire pg */
2438
/* This means we enter this only once, and npg=1 at the end */
2439
/* This is a rare case. FIXME: cannot eliminate this? */
2440
slice_size = payload_size;
2442
if (var_root->characteristics[start_idx + idx].payload_offset > 0) {
2443
slice_offset = var_root->characteristics[start_idx + idx].payload_offset;
2450
memcpy( (char *)data, fh->b->buff + fh->b->offset, slice_size);
2451
if (fh->mfooter.change_endianness == adios_flag_yes) {
2452
change_endianness(data, slice_size, var_root->type);
2455
else if (hole_break == 0)
2457
/* The slowest changing dimensions should not be read completely but
2458
we still need to read only one block */
2460
uint64_t size_in_dset = 0;
2461
uint64_t offset_in_dset = 0;
2462
uint64_t offset_in_var = 0;
2464
isize = offsets[0] + ldims[0];
2465
if (start_notime[0] >= offsets[0]) {
2467
if (start_notime[0]<isize) {
2468
if (start_notime[0] + count_notime[0] > isize)
2469
size_in_dset = isize - start_notime[0];
2471
size_in_dset = count_notime[0];
2472
offset_in_dset = start_notime[0] - offsets[0];
2478
if (isize < start_notime[0] + count_notime[0])
2479
size_in_dset = ldims[0];
2482
size_in_dset = count_notime[0] + start_notime[0] - offsets[0];
2484
offset_in_var = offsets[0] - start_notime[0];
2487
slice_size = size_in_dset * datasize * size_of_type;
2488
write_offset = offset_in_var * datasize * size_of_type;
2490
if (var_root->characteristics[start_idx + idx].payload_offset > 0) {
2491
slice_offset = var_root->characteristics[start_idx + idx].payload_offset
2492
+ offset_in_dset * datasize * size_of_type;
2499
memcpy ((char *)data + write_offset, fh->b->buff + fh->b->offset, slice_size);
2500
if (fh->mfooter.change_endianness == adios_flag_yes) {
2501
change_endianness((char *)data + write_offset, slice_size, var_root->type);
2504
//write_offset += slice_size;
2509
uint64_t stride_offset = 0;
2511
uint64_t size_in_dset[10];
2512
uint64_t offset_in_dset[10];
2513
uint64_t offset_in_var[10];
2514
memset(size_in_dset, 0 , 10 * 8);
2515
memset(offset_in_dset, 0 , 10 * 8);
2516
memset(offset_in_var, 0 , 10 * 8);
2518
for ( i = 0; i < ndim_notime ; i++) {
2519
isize = offsets[i] + ldims[i];
2520
if (start_notime[i] >= offsets[i]) {
2522
if (start_notime[i]<isize) {
2523
if (start_notime[i] + count_notime[i] > isize)
2524
size_in_dset[i] = isize - start_notime[i];
2526
size_in_dset[i] = count_notime[i];
2527
offset_in_dset[i] = start_notime[i] - offsets[i];
2528
offset_in_var[i] = 0;
2536
if (isize < start_notime[i] + count_notime[i]) {
2537
size_in_dset[i] = ldims[i];
2542
size_in_dset[i] = count_notime[i] + start_notime[i] - offsets[i];
2545
offset_in_dset[i] = 0;
2546
offset_in_var[i] = offsets[i] - start_notime[i];
2553
for ( i = ndim_notime-1; i >= hole_break; i--) {
2554
datasize *= size_in_dset[i];
2555
dset_stride *= ldims[i];
2556
var_stride *= count_notime[i];
2559
uint64_t start_in_payload = 0, end_in_payload = 0, s = 1;
2560
for (i = ndim_notime - 1; i > -1; i--) {
2561
start_in_payload += s * offset_in_dset[i] * size_of_type;
2562
end_in_payload += s * (offset_in_dset[i] + size_in_dset[i] - 1) * size_of_type;
2566
slice_size = end_in_payload - start_in_payload + 1 * size_of_type;
2568
if (var_root->characteristics[start_idx + idx].payload_offset > 0) {
2569
slice_offset = var_root->characteristics[start_idx + idx].payload_offset
2573
for ( i = 0; i < ndim_notime ; i++) {
2574
offset_in_dset[i] = 0;
2577
slice_offset = start_in_payload;
2581
uint64_t var_offset = 0;
2582
uint64_t dset_offset = 0;
2583
for ( i = 0; i < hole_break; i++) {
2584
nloop *= size_in_dset[i];
2587
for ( i = 0; i < ndim_notime ; i++) {
2588
var_offset = offset_in_var[i] + var_offset * count_notime[i];
2589
dset_offset = offset_in_dset[i] + dset_offset * ldims[i];
2593
,fh->b->buff + fh->b->offset
2608
} // end for (idx ... loop over pgs
2612
total_size += items_read * size_of_type;
2613
// shift target pointer for next read in
2614
data = (char *)data + (items_read * size_of_type);
2616
} // end for (timestep ... loop over timesteps
2623
// Search for the start var index.
2624
static int get_var_start_index (struct adios_index_var_struct_v1 * v, int t)
2628
while (i < v->characteristics_count) {
2629
if (v->characteristics[i].time_index == t) {
2639
// Search for the stop var index
2640
static int get_var_stop_index (struct adios_index_var_struct_v1 * v, int t)
2642
int i = v->characteristics_count - 1;
2645
if (v->characteristics[i].time_index == t) {
2655
int64_t adios_read_bp_read_var_byid2 (ADIOS_GROUP * gp,
2657
const uint64_t * start,
2658
const uint64_t * count,
2661
struct BP_GROUP * gh;
2662
struct BP_FILE * fh;
2663
struct adios_index_var_struct_v1 * var_root;
2664
struct adios_var_header_struct_v1 var_header;
2665
struct adios_var_payload_struct_v1 var_payload;
2667
int start_time, stop_time;
2668
int start_idx, stop_idx;
2669
int ndim, ndim_notime, has_subfile, file_is_fortran;
2670
uint64_t size, * dims;
2671
uint64_t ldims[32], gdims[32], offsets[32];
2672
uint64_t datasize, nloop, dset_stride,var_stride, total_size=0, items_read;
2673
uint64_t count_notime[32], start_notime[32];
2674
int timedim = -1, temp_timedim, is_global = 0, size_of_type;
2675
uint64_t slice_offset, slice_size, tmpcount = 0;
2676
uint64_t datatimeoffset = 0; // offset in data to write a given timestep
2679
gh = (struct BP_GROUP *) gp->gh;
2682
file_is_fortran = (fh->pgs_root->adios_host_language_fortran == adios_flag_yes);
2683
has_subfile = fh->mfooter.version & ADIOS_VERSION_HAVE_SUBFILE;
2685
var_root = gh->vars_root; /* first variable of this group. Need to traverse the list */
2686
for (i = 0; i< varid && var_root; i++) {
2687
var_root = var_root->next;
2691
adios_error (err_corrupted_variable,
2692
"Variable id=%d is valid but was not found in internal data structures!",
2694
return -adios_errno;
2697
/* Get dimensions and flip if caller != writer language */
2698
adios_read_bp_get_dimensions (var_root, fh->tidx_stop - fh->tidx_start + 1, file_is_fortran,
2699
&ndim, &dims, &timedim);
2701
/* In a Fortran written files, dimensions are in reversed order for C */
2702
//if ( file_is_fortran != futils_is_called_from_fortran() )
2703
if (file_is_fortran)
2704
swap_order(ndim, dims, &timedim);
2706
/* Take out the time dimension from start[] and count[] */
2707
if (timedim == -1) {
2708
/* For timeless var, we still search from fh->tidx_start to fh->tidx_stop
2709
to handle the situation that some variables are dumped out in selected timesteps
2711
start_time = fh->tidx_start;
2712
stop_time = fh->tidx_stop;
2714
for (i = 0; i < ndim; i++) {
2715
count_notime[i] = count[i];
2716
start_notime[i] = start[i];
2721
if (futils_is_called_from_fortran())
2722
temp_timedim = ndim - 1;
2726
start_time = start[temp_timedim] + fh->tidx_start;
2727
stop_time = start_time + count[temp_timedim] - 1;
2729
for (i = 0; i < temp_timedim; i++) {
2730
count_notime[j] = count[i];
2731
start_notime[j] = start[i];
2734
i++; // skip timedim
2735
for (; i < ndim; i++) {
2736
count_notime[j] = count[i];
2737
start_notime[j] = start[i];
2740
ndim_notime = ndim-1;
2743
/* Fortran reader was reported of Fortran dimension order so it gives counts and starts in that order.
2744
We need to swap them here to read correctly in C order */
2745
if ( futils_is_called_from_fortran()) {
2746
swap_order(ndim_notime, count_notime, &timedim);
2747
swap_order(ndim_notime, start_notime, &timedim);
2750
/* items_read = how many data elements are we going to read in total (per timestep) */
2752
for (i = 0; i < ndim_notime; i++)
2753
items_read *= count_notime[i];
2755
size_of_type = bp_get_type_size (var_root->type, var_root->characteristics [0].value);
2757
/* For each timestep, do reading separately (they are stored in different sets of process groups */
2758
for (t = start_time; t <= stop_time; t++) {
2759
start_idx = get_var_start_index(var_root, t);
2760
stop_idx = get_var_stop_index(var_root, t);
2762
if (start_idx < 0 || stop_idx < 0) {
2763
adios_error (err_no_data_at_timestep,"Variable (id=%d) has no data at %d time step",
2765
// return -adios_errno;
2769
if (ndim_notime == 0) {
2770
/* READ A SCALAR VARIABLE */
2771
slice_size = size_of_type;
2772
idx = 0; // macros below need it
2774
if (var_root->type == adios_string) {
2775
// strings are stored without \0 in file
2776
// size_of_type here includes \0 so decrease by one
2780
if (var_root->characteristics[start_idx+idx].payload_offset > 0) {
2781
slice_offset = var_root->characteristics[start_idx+idx].payload_offset;
2792
memcpy((char *)data+total_size, fh->b->buff + fh->b->offset, size_of_type);
2793
if (fh->mfooter.change_endianness == adios_flag_yes) {
2794
change_endianness((char *)data+total_size, size_of_type, var_root->type);
2797
if (var_root->type == adios_string) {
2798
// add \0 to the end of string
2799
// size_of_type here is the length of string
2800
// FIXME: how would this work for strings written over time?
2801
((char*)data+total_size)[size_of_type] = '\0';
2804
total_size += size_of_type;
2812
/* READ AN ARRAY VARIABLE */
2813
int * idx_table = (int *) malloc (sizeof(int) * (stop_idx - start_idx + 1));
2815
uint64_t write_offset = 0;
2818
// loop over the list of pgs to read from one-by-one
2819
for (idx = 0; idx < stop_idx - start_idx + 1; idx++) {
2826
uint64_t payload_size = size_of_type;
2828
/* Each pg can have a different sized array, so we need the actual dimensions from it */
2829
is_global = adios_read_bp_get_dimensioncharacteristics( &(var_root->characteristics[start_idx + idx]),
2830
ldims, gdims, offsets);
2832
// we use gdims below, which is 0 for a local array; set to ldims here
2833
for (j = 0; j< ndim; j++) {
2836
// we need to read only the first PG, not all, so let's prevent a second loop
2837
stop_idx = start_idx;
2840
/* Again, a Fortran written file has the dimensions in Fortran order we need to swap here */
2841
//if (file_is_fortran != futils_is_called_from_fortran()) {
2842
if (file_is_fortran) {
2844
swap_order(ndim, gdims, &(i)); // i is dummy
2845
swap_order(ndim, ldims, &(i));
2846
swap_order(ndim, offsets, &(i));
2849
/* take out the time dimension */
2850
/* For C, gdims and offset are one size shorter because the timedim part is missing,
2851
so we take it out only for fortran files
2854
for (i = timedim; i < ndim-1; i++) {
2855
ldims[i] = ldims[i+1];
2856
if (file_is_fortran) {
2857
gdims[i] = gdims[i+1];
2858
offsets[i] = offsets[i+1];
2864
printf("ldims = "); for (j = 0; j<ndim; j++) printf("%d ",ldims[j]); printf("\n");
2865
printf("gdims = "); for (j = 0; j<ndim; j++) printf("%d ",gdims[j]); printf("\n");
2866
printf("offsets = "); for (j = 0; j<ndim; j++) printf("%d ",offsets[j]); printf("\n");
2867
printf("count_notime = "); for (j = 0; j<ndim_notime; j++) printf("%d ",count_notime[j]); printf("\n");
2868
printf("start_notime = "); for (j = 0; j<ndim_notime; j++) printf("%d ",start_notime[j]); printf("\n");
2871
for (j = 0; j < ndim_notime; j++) {
2873
payload_size *= ldims [j];
2875
if ( (count_notime[j] > gdims[j])
2876
|| (start_notime[j] > gdims[j])
2877
|| (start_notime[j] + count_notime[j] > gdims[j])){
2878
adios_error ( err_out_of_bound, "Error: Variable (id=%d) out of bound ("
2879
"the data in dimension %d to read is %llu elements from index %llu"
2880
" but the actual data is [0,%llu])",
2881
varid, j+1, count_notime[j], start_notime[j], gdims[j] - 1);
2882
return -adios_errno;
2885
/* check if there is any data in this pg and this dimension to read in */
2886
flag = (offsets[j] >= start_notime[j]
2887
&& offsets[j] < start_notime[j] + count_notime[j])
2888
|| (offsets[j] < start_notime[j]
2889
&& offsets[j] + ldims[j] > start_notime[j] + count_notime[j])
2890
|| (offsets[j] + ldims[j] > start_notime[j]
2891
&& offsets[j] + ldims[j] <= start_notime[j] + count_notime[j]);
2892
idx_table [idx] = idx_table[idx] && flag;
2895
if ( !idx_table[idx] ) {
2900
/* determined how many (fastest changing) dimensions can we read in in one read */
2902
for (i = ndim_notime - 1; i > -1; i--) {
2903
if (offsets[i] == start_notime[i] && ldims[i] == count_notime[i]) {
2904
datasize *= ldims[i];
2913
if (hole_break == -1) {
2914
/* The complete read happens to be exactly one pg, and the entire pg */
2915
/* This means we enter this only once, and npg=1 at the end */
2916
/* This is a rare case. FIXME: cannot eliminate this? */
2917
slice_size = payload_size;
2919
if (var_root->characteristics[start_idx + idx].payload_offset > 0) {
2920
slice_offset = var_root->characteristics[start_idx + idx].payload_offset;
2931
memcpy( (char *)data, fh->b->buff + fh->b->offset, slice_size);
2932
if (fh->mfooter.change_endianness == adios_flag_yes) {
2933
change_endianness(data, slice_size, var_root->type);
2936
else if (hole_break == 0)
2938
/* The slowest changing dimensions should not be read completely but
2939
we still need to read only one block */
2941
uint64_t size_in_dset = 0;
2942
uint64_t offset_in_dset = 0;
2943
uint64_t offset_in_var = 0;
2945
isize = offsets[0] + ldims[0];
2946
if (start_notime[0] >= offsets[0]) {
2948
if (start_notime[0]<isize) {
2949
if (start_notime[0] + count_notime[0] > isize)
2950
size_in_dset = isize - start_notime[0];
2952
size_in_dset = count_notime[0];
2953
offset_in_dset = start_notime[0] - offsets[0];
2959
if (isize < start_notime[0] + count_notime[0])
2960
size_in_dset = ldims[0];
2963
size_in_dset = count_notime[0] + start_notime[0] - offsets[0];
2965
offset_in_var = offsets[0] - start_notime[0];
2968
slice_size = size_in_dset * datasize * size_of_type;
2969
write_offset = offset_in_var * datasize * size_of_type;
2971
if (var_root->characteristics[start_idx + idx].payload_offset > 0) {
2972
slice_offset = var_root->characteristics[start_idx + idx].payload_offset
2973
+ offset_in_dset * datasize * size_of_type;
2985
memcpy ((char *)data + write_offset, fh->b->buff + fh->b->offset, slice_size);
2986
if (fh->mfooter.change_endianness == adios_flag_yes) {
2987
change_endianness((char *)data + write_offset, slice_size, var_root->type);
2990
//write_offset += slice_size;
2995
uint64_t stride_offset = 0;
2997
uint64_t size_in_dset[10];
2998
uint64_t offset_in_dset[10];
2999
uint64_t offset_in_var[10];
3000
memset(size_in_dset, 0 , 10 * 8);
3001
memset(offset_in_dset, 0 , 10 * 8);
3002
memset(offset_in_var, 0 , 10 * 8);
3004
for ( i = 0; i < ndim_notime ; i++) {
3005
isize = offsets[i] + ldims[i];
3006
if (start_notime[i] >= offsets[i]) {
3008
if (start_notime[i]<isize) {
3009
if (start_notime[i] + count_notime[i] > isize)
3010
size_in_dset[i] = isize - start_notime[i];
3012
size_in_dset[i] = count_notime[i];
3013
offset_in_dset[i] = start_notime[i] - offsets[i];
3014
offset_in_var[i] = 0;
3022
if (isize < start_notime[i] + count_notime[i]) {
3023
size_in_dset[i] = ldims[i];
3028
size_in_dset[i] = count_notime[i] + start_notime[i] - offsets[i];
3031
offset_in_dset[i] = 0;
3032
offset_in_var[i] = offsets[i] - start_notime[i];
3039
for ( i = ndim_notime-1; i >= hole_break; i--) {
3040
datasize *= size_in_dset[i];
3041
dset_stride *= ldims[i];
3042
var_stride *= count_notime[i];
3045
uint64_t start_in_payload = 0, end_in_payload = 0, s = 1;
3046
for (i = ndim_notime - 1; i > -1; i--) {
3047
start_in_payload += s * offset_in_dset[i] * size_of_type;
3048
end_in_payload += s * (offset_in_dset[i] + size_in_dset[i] - 1) * size_of_type;
3052
slice_size = end_in_payload - start_in_payload + 1 * size_of_type;
3054
if (var_root->characteristics[start_idx + idx].payload_offset > 0) {
3055
slice_offset = var_root->characteristics[start_idx + idx].payload_offset
3063
for ( i = 0; i < ndim_notime ; i++) {
3064
offset_in_dset[i] = 0;
3067
slice_offset = start_in_payload;
3071
uint64_t var_offset = 0;
3072
uint64_t dset_offset = 0;
3073
for ( i = 0; i < hole_break; i++) {
3074
nloop *= size_in_dset[i];
3077
for ( i = 0; i < ndim_notime ; i++) {
3078
var_offset = offset_in_var[i] + var_offset * count_notime[i];
3079
dset_offset = offset_in_dset[i] + dset_offset * ldims[i];
3083
,fh->b->buff + fh->b->offset
3097
} // end for (idx ... loop over pgs
3101
total_size += items_read * size_of_type;
3102
// shift target pointer for next read in
3103
data = (char *)data + (items_read * size_of_type);
3107
} // end for (timestep ... loop over timesteps
3114
int64_t adios_read_bp_read_var_byid (ADIOS_GROUP * gp,
3116
const uint64_t * start,
3117
const uint64_t * count,
3120
struct BP_GROUP * gh;
3121
struct BP_FILE * fh;
3122
int has_time_index_characteristic;
3126
adios_error (err_invalid_group_struct, "Null pointer passed as group to adios_read_var()");
3127
return -adios_errno;
3130
gh = (struct BP_GROUP *) gp->gh;
3132
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh group handle is NULL!");
3133
return -adios_errno;
3138
adios_error (err_invalid_group_struct, "Invalid ADIOS_GROUP struct: .gh->fh file handle is NULL!");
3139
return -adios_errno;
3142
has_time_index_characteristic = fh->mfooter.version & ADIOS_VERSION_HAVE_TIME_INDEX_CHARACTERISTIC;
3143
if (!has_time_index_characteristic) {
3144
// read older file format. Can be deleted later on.
3145
return adios_read_bp_read_var_byid1(gp, varid, start, count, data);
3147
return adios_read_bp_read_var_byid2(gp, varid, start, count, data);
3151
// NCSU - Timer series analysis, correlation
3152
double adios_stat_cor (ADIOS_VARINFO * vix, ADIOS_VARINFO * viy, char * characteristic, uint32_t time_start, uint32_t time_end, uint32_t lag)
3156
double avg_x = 0.0, avg_y = 0.0, avg_lag = 0.0;
3157
double var_x = 0.0, var_y = 0.0, var_lag = 0.0;
3162
fprintf(stderr, "Variable not defined\n");
3166
// If the vix and viy are not time series objects, return.
3167
if ((vix->timedim < 0) && (viy->timedim < 0))
3169
fprintf(stderr, "Covariance must involve timeseries data\n");
3173
uint32_t min = vix->dims[0] - 1;
3174
if (viy && (min > viy->dims[0] - 1))
3175
min = viy->dims[0] - 1;
3177
if(time_start == 0 && time_end == 0)
3178
{ //global covariance
3180
fprintf(stderr, "Must have two variables for global covariance\n");
3184
// Assign vix to viy, and calculate covariance
3189
// Check the bounds of time
3190
if ( (time_start >= 0) && (time_start <= min)
3191
&& (time_end >= 0) && (time_end <= min)
3192
&& (time_start <= time_end))
3194
if(viy == NULL) //user must want to run covariance against itself
3196
if(! (time_end+lag) > min)
3198
fprintf(stderr, "Must leave enough timesteps for lag\n");
3202
if (strcmp(characteristic, "average") == 0 || strcmp(characteristic, "avg") == 0)
3204
for (i = time_start; i <= time_end; i ++)
3206
avg_x += bp_value_to_double (adios_double, vix->avgs[i]) / (time_end - time_start + 1);
3207
avg_lag += bp_value_to_double (adios_double, vix->avgs[i + lag]) / (time_end - time_start + 1);
3210
for (i = time_start; i <= time_end; i ++)
3212
double val_x = bp_value_to_double (adios_double, vix->avgs[i]);
3213
double val_lag = bp_value_to_double (adios_double, vix->avgs[i + lag]);
3214
var_x += (val_x - avg_x) * (val_x - avg_x) / (time_end - time_start + 1);
3215
var_lag += (val_lag - avg_lag) * (val_lag - avg_lag) / (time_end - time_start + 1);
3216
cov += (val_x - avg_x) * (val_lag - avg_lag) / (time_end - time_start + 1);
3219
else if (strcmp(characteristic, "standard deviation") == 0 || strcmp(characteristic, "std_dev") == 0)
3221
for (i = time_start; i <= time_end; i ++)
3223
avg_x += bp_value_to_double (adios_double, vix->std_devs[i]) / (time_end - time_start + 1);
3224
avg_lag += bp_value_to_double (adios_double, vix->std_devs[i + lag]) / (time_end - time_start + 1);
3227
for (i = time_start; i <= time_end; i ++)
3229
double val_x = bp_value_to_double (adios_double, vix->std_devs[i]);
3230
double val_lag = bp_value_to_double (adios_double, vix->std_devs[i + lag]);
3231
var_x += (val_x - avg_x) * (val_x - avg_x) / (time_end - time_start + 1);
3232
var_lag += (val_lag - avg_lag) * (val_lag - avg_lag) / (time_end - time_start + 1);
3233
cov += (val_x - avg_x) * (val_lag - avg_lag) / (time_end - time_start + 1);
3236
else if (strcmp(characteristic, "minimum") == 0 || strcmp(characteristic, "min") == 0)
3238
for (i = time_start; i <= time_end; i ++)
3240
avg_x += bp_value_to_double (vix->type, vix->mins[i]) / (time_end - time_start + 1);
3241
avg_lag += bp_value_to_double (vix->type, vix->mins[i + lag]) / (time_end - time_start + 1);
3244
for (i = time_start; i <= time_end; i ++)
3246
double val_x = bp_value_to_double (vix->type, vix->mins[i]);
3247
double val_lag = bp_value_to_double (vix->type, vix->mins[i + lag]);
3248
var_x += (val_x - avg_x) * (val_x - avg_x) / (time_end - time_start + 1);
3249
var_lag += (val_lag - avg_lag) * (val_lag - avg_lag) / (time_end - time_start + 1);
3250
cov += (val_x - avg_x) * (val_lag - avg_lag) / (time_end - time_start + 1);
3253
else if (strcmp(characteristic, "maximum") == 0 || strcmp(characteristic, "max") == 0)
3255
for (i = time_start; i <= time_end; i ++)
3257
avg_x += bp_value_to_double (vix->type, vix->maxs[i]) / (time_end - time_start + 1);
3258
avg_lag += bp_value_to_double (vix->type, vix->maxs[i]) / (time_end - time_start + 1);
3261
for (i = time_start; i <= time_end; i ++)
3263
double val_x = bp_value_to_double (vix->type, vix->maxs[i]);
3264
double val_lag = bp_value_to_double (vix->type, vix->maxs[i + lag]);
3265
var_x += (val_x - avg_x) * (val_x - avg_x) / (time_end - time_start + 1);
3266
var_lag += (val_lag - avg_lag) * (val_lag - avg_lag) / (time_end - time_start + 1);
3267
cov += (val_x - avg_x) * (val_lag - avg_lag) / (time_end - time_start + 1);
3272
fprintf (stderr, "Unknown characteristic\n");
3275
return cov / (sqrt (var_x) * sqrt (var_lag));
3279
if (strcmp(characteristic, "average") == 0 || strcmp(characteristic, "avg") == 0)
3281
for (i = time_start; i <= time_end; i ++)
3283
avg_x += bp_value_to_double(adios_double, vix->avgs[i]) / (time_end - time_start + 1);
3284
avg_y += bp_value_to_double(adios_double, viy->avgs[i]) / (time_end - time_start + 1);
3286
for (i = time_start; i <= time_end; i ++)
3288
double val_x = bp_value_to_double (adios_double, vix->avgs[i]);
3289
double val_y = bp_value_to_double (adios_double, viy->avgs[i]);
3290
var_x += (val_x - avg_x) * (val_x - avg_x) / (time_end - time_start + 1);
3291
var_y += (val_y - avg_y) * (val_y - avg_y) / (time_end - time_start + 1);
3292
cov += (val_x - avg_x) * (val_y - avg_y) / (time_end - time_start + 1);
3295
else if (strcmp(characteristic, "standard deviation") == 0 || strcmp(characteristic, "std_dev") == 0)
3297
for (i = time_start; i <= time_end; i ++)
3299
avg_x += bp_value_to_double(adios_double, vix->std_devs[i]) / (time_end - time_start + 1);
3300
avg_y += bp_value_to_double(adios_double, viy->std_devs[i]) / (time_end - time_start + 1);
3302
for (i = time_start; i <= time_end; i ++)
3304
double val_x = bp_value_to_double (adios_double, vix->std_devs[i]);
3305
double val_y = bp_value_to_double (adios_double, viy->std_devs[i]);
3306
var_x += (val_x - avg_x) * (val_x - avg_x) / (time_end - time_start + 1);
3307
var_y += (val_y - avg_y) * (val_y - avg_y) / (time_end - time_start + 1);
3308
cov += (val_x - avg_x) * (val_y - avg_y) / (time_end - time_start + 1);
3311
else if (strcmp(characteristic, "minimum") == 0 || strcmp(characteristic, "min") == 0)
3313
for (i = time_start; i <= time_end; i ++)
3315
avg_x += bp_value_to_double(vix->type, vix->mins[i]) / (time_end - time_start + 1);
3316
avg_y += bp_value_to_double(viy->type, viy->mins[i]) / (time_end - time_start + 1);
3318
for (i = time_start; i <= time_end; i ++)
3320
double val_x = bp_value_to_double (vix->type, vix->mins[i]);
3321
double val_y = bp_value_to_double (viy->type, viy->mins[i]);
3322
var_x += (val_x - avg_x) * (val_x - avg_x) / (time_end - time_start + 1);
3323
var_y += (val_y - avg_y) * (val_y - avg_y) / (time_end - time_start + 1);
3324
cov += (val_x - avg_x) * (val_y - avg_y) / (time_end - time_start + 1);
3327
else if (strcmp(characteristic, "maximum") == 0 || strcmp(characteristic, "max") == 0)
3329
for (i = time_start; i <= time_end; i ++)
3331
avg_x += bp_value_to_double(vix->type, vix->maxs[i]) / (time_end - time_start + 1);
3332
avg_y += bp_value_to_double(vix->type, viy->maxs[i]) / (time_end - time_start + 1);
3334
for (i = time_start; i <= time_end; i ++)
3336
double val_x = bp_value_to_double (vix->type, vix->maxs[i]);
3337
double val_y = bp_value_to_double (viy->type, viy->maxs[i]);
3338
var_x += (val_x - avg_x) * (val_x - avg_x) / (time_end - time_start + 1);
3339
var_y += (val_y - avg_y) * (val_y - avg_y) / (time_end - time_start + 1);
3340
cov += (val_x - avg_x) * (val_y - avg_y) / (time_end - time_start + 1);
3345
fprintf (stderr, "Unknown characteristic\n");
3348
return cov / (sqrt (var_x) * sqrt (var_y));
3353
fprintf (stderr, "Time values out of bounds\n");
3358
// NCSU - Time series analysis, covariance
3359
//covariance(x,y) = sum(i=1,..N) [(x_1 - x_mean)(y_i - y_mean)]/N
3360
double adios_stat_cov (ADIOS_VARINFO * vix, ADIOS_VARINFO * viy, char * characteristic, uint32_t time_start, uint32_t time_end, uint32_t lag)
3364
double avg_x = 0.0, avg_y = 0.0, avg_lag = 0.0;
3369
fprintf(stderr, "Variable not defined\n");
3373
// If the vix and viy are not time series objects, return.
3374
if ((vix->timedim < 0) && (viy->timedim < 0))
3376
fprintf(stderr, "Covariance must involve timeseries data\n");
3380
uint32_t min = vix->dims[0] - 1;
3381
if (viy && (min > viy->dims[0] - 1))
3382
min = viy->dims[0] - 1;
3384
if(time_start == 0 && time_end == 0)
3385
{ //global covariance
3387
fprintf(stderr, "Must have two variables for global covariance\n");
3391
// Assign vix to viy, and calculate covariance
3396
// Check the bounds of time
3397
if ( (time_start >= 0) && (time_start <= min)
3398
&& (time_end >= 0) && (time_end <= min)
3399
&& (time_start <= time_end))
3401
if(viy == NULL) //user must want to run covariance against itself
3403
if(! (time_end+lag) > min)
3405
fprintf(stderr, "Must leave enough timesteps for lag\n");
3409
if (strcmp(characteristic, "average") == 0 || strcmp(characteristic, "avg") == 0)
3411
for (i = time_start; i <= time_end; i ++)
3413
avg_x += bp_value_to_double (adios_double, vix->avgs[i]) / (time_end - time_start + 1);
3414
avg_lag += bp_value_to_double (adios_double, vix->avgs[i + lag]) / (time_end - time_start + 1);
3417
for (i = time_start; i <= time_end; i ++)
3418
cov += (bp_value_to_double (adios_double, vix->avgs[i]) - avg_x) * (bp_value_to_double (adios_double, vix->avgs[i+lag]) - avg_lag) / (time_end - time_start + 1);
3420
else if (strcmp(characteristic, "standard deviation") == 0 || strcmp(characteristic, "std_dev") == 0)
3422
for (i = time_start; i <= time_end; i ++)
3424
avg_x += bp_value_to_double (adios_double, vix->std_devs[i]) / (time_end - time_start + 1);
3425
avg_lag += bp_value_to_double (adios_double, vix->std_devs[i + lag]) / (time_end - time_start + 1);
3428
for (i = time_start; i <= time_end; i ++)
3429
cov += (bp_value_to_double (adios_double, vix->std_devs[i]) - avg_x) * (bp_value_to_double (adios_double, vix->std_devs[i+lag]) - avg_lag) / (time_end - time_start + 1);
3431
else if (strcmp(characteristic, "minimum") == 0 || strcmp(characteristic, "min") == 0)
3433
for (i = time_start; i <= time_end; i ++)
3435
avg_x += bp_value_to_double (vix->type, vix->mins[i]) / (time_end - time_start + 1);
3436
avg_lag += bp_value_to_double (vix->type, vix->mins[i + lag]) / (time_end - time_start + 1);
3439
for (i = time_start; i <= time_end; i ++)
3440
cov += (bp_value_to_double (vix->type, vix->mins[i]) - avg_x) * (bp_value_to_double (vix->type, vix->mins[i+lag]) - avg_lag) / (time_end - time_start + 1);
3442
else if (strcmp(characteristic, "maximum") == 0 || strcmp(characteristic, "max") == 0)
3444
for (i = time_start; i <= time_end; i ++)
3446
avg_x += bp_value_to_double (vix->type, vix->maxs[i]) / (time_end - time_start + 1);
3447
avg_lag += bp_value_to_double (vix->type, vix->maxs[i + lag]) / (time_end - time_start + 1);
3450
for (i = time_start; i <= time_end; i ++)
3451
cov += (bp_value_to_double (vix->type, vix->maxs[i]) - avg_x) * (bp_value_to_double (vix->type, vix->maxs[i+lag]) - avg_lag) / (time_end - time_start + 1);
3455
fprintf (stderr, "Unknown characteristic\n");
3461
if (strcmp(characteristic, "average") == 0 || strcmp(characteristic, "avg") == 0)
3463
for (i = time_start; i <= time_end; i ++)
3465
avg_x += bp_value_to_double(adios_double, vix->avgs[i]) / (time_end - time_start + 1);
3466
avg_y += bp_value_to_double(adios_double, viy->avgs[i]) / (time_end - time_start + 1);
3468
for (i = time_start; i <= time_end; i ++)
3470
cov += (bp_value_to_double(adios_double, vix->avgs[i]) - avg_x) * (bp_value_to_double(adios_double, viy->avgs[i]) - avg_y) / (time_end - time_start + 1);
3473
else if (strcmp(characteristic, "standard deviation") == 0 || strcmp(characteristic, "std_dev") == 0)
3475
for (i = time_start; i <= time_end; i ++)
3477
avg_x += bp_value_to_double(adios_double, vix->std_devs[i]) / (time_end - time_start + 1);
3478
avg_y += bp_value_to_double(adios_double, viy->std_devs[i]) / (time_end - time_start + 1);
3480
for (i = time_start; i <= time_end; i ++)
3482
cov += (bp_value_to_double(adios_double, vix->std_devs[i]) - avg_x) * (bp_value_to_double(adios_double, viy->std_devs[i]) - avg_y) / (time_end - time_start + 1);
3485
else if (strcmp(characteristic, "minimum") == 0 || strcmp(characteristic, "min") == 0)
3487
for (i = time_start; i <= time_end; i ++)
3489
avg_x += bp_value_to_double(vix->type, vix->mins[i]) / (time_end - time_start + 1);
3490
avg_y += bp_value_to_double(viy->type, viy->mins[i]) / (time_end - time_start + 1);
3492
for (i = time_start; i <= time_end; i ++)
3494
cov += (bp_value_to_double(vix->type, vix->mins[i]) - avg_x) * (bp_value_to_double(viy->type, viy->mins[i]) - avg_y) / (time_end - time_start + 1);
3497
else if (strcmp(characteristic, "maximum") == 0 || strcmp(characteristic, "max") == 0)
3499
for (i = time_start; i <= time_end; i ++)
3501
avg_x += bp_value_to_double(vix->type, vix->maxs[i]) / (time_end - time_start + 1);
3502
avg_y += bp_value_to_double(vix->type, viy->maxs[i]) / (time_end - time_start + 1);
3504
for (i = time_start; i <= time_end; i ++)
3506
cov += (bp_value_to_double(vix->type, vix->maxs[i]) - avg_x) * (bp_value_to_double(viy->type, viy->maxs[i]) - avg_y) / (time_end - time_start + 1);
3511
fprintf (stderr, "Unknown characteristic\n");
3518
fprintf (stderr, "Time values out of bounds\n");