int adios_inq_var_blockinfo (ADIOS_FILE *fp, ADIOS_VARINFO * varinfo) { return common_read_inq_var_blockinfo (fp, varinfo); }
static int getTotalByteSize (ADIOS_FILE* f, ADIOS_VARINFO* v, ADIOS_SELECTION* sel, uint64_t* total_byte_size, uint64_t* dataSize, int timestep) { *total_byte_size = common_read_type_size (v->type, v->value); *dataSize = 1; if (sel == 0) { uint64_t s = 0; for (s=0; s<v->ndim; s++) { *total_byte_size *=v->dims[s]; *dataSize *= v->dims[s]; // log_debug(" dim %" PRIu64 "default count %" PRIu64 "\n", s, v->dims[s]); } return 0; } switch (sel->type) { case ADIOS_SELECTION_BOUNDINGBOX: { const ADIOS_SELECTION_BOUNDINGBOX_STRUCT *bb = &(sel->u.bb); uint64_t* count = bb->count; uint64_t* start = bb->start; int s=0; for (s=0; s<v->ndim; s++) { if (start[s]+count[s] > v->dims[s]) { log_error(" Invalid bounding box at %dth dim: start %" PRIu64 " + count %" PRIu64 " exceeds dim size: %" PRIu64 "\n", s, start[s], count[s], v->dims[s]); return -1; } *total_byte_size *=count[s]; *dataSize *= count[s]; // log_debug(" dim %" PRIu64 "count %" PRIu64 " \n", s, count[s]); } // log_debug("\tThe data size is = %" PRIu64 " \n", *dataSize); break; } case ADIOS_SELECTION_POINTS: { const ADIOS_SELECTION_POINTS_STRUCT *pts = &(sel->u.points); *total_byte_size *= pts->npoints; *dataSize = pts->npoints; break; } case ADIOS_SELECTION_WRITEBLOCK: { const ADIOS_SELECTION_WRITEBLOCK_STRUCT *wb = &(sel->u.block); common_read_inq_var_blockinfo(f, v); int i=0; int min = v->nblocks[0]; int absBlockCounter = wb->index; if (v->nsteps > 1) { // all timesteps are known, can get abs for (i=0; i<v->nsteps; i++) { int nBlocksAtStep = v->nblocks[i]; if (nBlocksAtStep < min) { min = nBlocksAtStep; } log_debug("\t\t currstep=%d nblocks=%d\n", i, nBlocksAtStep); if (i < timestep) { absBlockCounter += nBlocksAtStep; } } } if (wb->index > min) { log_error("Error: Unable to handle this block index %d over all the timesteps. Stop.\n", wb->index); return -1; } int j=0; for (j=0; j<v->ndim; j++) { *total_byte_size *= v->blockinfo[absBlockCounter].count[j]; *dataSize *= v->blockinfo[absBlockCounter].count[j]; } log_debug("\t\t block %d, abs id:%d, bytes: %" PRIu64 ", size = %" PRIu64 " \n", wb->index, absBlockCounter, *total_byte_size, *dataSize); break; } default: break; } return 0; }
/* static int checkCompatibility(ADIOS_QUERY* q) { if ((q->left != NULL) && (q->right != NULL)) { return isCompatible(q->left, q->right); } return 0; // ok, no need to check } */ static ADIOS_VARBLOCK * computePGBounds(ADIOS_QUERY *q, int wbindex, int timestep, int *out_ndim) { if (!q->left && !q->right) { // In this case, we have reached a leaf query node, so directly // retrieve the varblock from the varinfo assert(q->varinfo); // Read the blockinfo if not already present if (!q->varinfo->blockinfo) { adios_read_set_data_view(q->file, LOGICAL_DATA_VIEW); common_read_inq_var_blockinfo(q->file, q->varinfo); } // Note: adios_get_absolute_writeblock_index ensures that timestep and wbindex // are both in bounds, signalling an adios_error if not. However, there will be // no variable name cited in the error, so perhaps better error handling would // be desirable in the future //const int abs_wbindex = adios_get_absolute_writeblock_index(q->varinfo, wbindex, timestep); int abs_wbindex = wbindex; if (q->varinfo->nsteps > 1) { // varinfo contains ALL timesteps, not just one step, so streaming mode files will not need call this func abs_wbindex = adios_get_absolute_writeblock_index(q->varinfo, wbindex, timestep); } // Finally, return ndim and the varblock *out_ndim = q->varinfo->ndim; return &q->varinfo->blockinfo[abs_wbindex]; } else if (!q->left || !q->right) { // In this case, we have only one subtree, so just return the // ndim and varblock from that subtree directly, since there's // nothing to compare against ADIOS_QUERY *present_subtree = q->left ? (ADIOS_QUERY*)q->left : (ADIOS_QUERY*)q->right; return computePGBounds(present_subtree, wbindex, timestep, out_ndim); } else { // In this final case, we have two subtrees, and we must compare // the resultant varblock from each one to ensure they are equal // before returning ADIOS_QUERY *left = (ADIOS_QUERY *)q->left; ADIOS_QUERY *right = (ADIOS_QUERY *)q->right; // Next, retrieve the ndim and varblock for each subtree int left_ndim, right_ndim; ADIOS_VARBLOCK *left_vb = computePGBounds(left, wbindex, timestep, &left_ndim); ADIOS_VARBLOCK *right_vb = computePGBounds(right, wbindex, timestep, &right_ndim); // If either subtree returns an invalid (NULL) varblock, fail immediately if (!left_vb || !right_vb) { return NULL; } // Check that the ndims are equal, failing if not int ndim; if (left_ndim != right_ndim) { return NULL; } else { ndim = left_ndim; } // Check the start/count coordinate in each dimension for equality, // failing if any coordinate is not equal between the subtrees int i; for (i = 0; i < ndim; i++) { if (left_vb->start[i] != right_vb->start[i] || left_vb->count[i] != right_vb->count[i]) { return NULL; } } // Finally, we have ensured that both subtrees yield valid and equal // varblocks, so return the common ndim and varblock (arbitrarily use // left_vb, since right and left equal) *out_ndim = ndim; return left_vb; } }
ADIOS_PG_INTERSECTIONS * adios_find_intersecting_pgs(const ADIOS_FILE *fp, int varid, const ADIOS_SELECTION *sel, const int from_step, const int nsteps) { // Declares adios_transform_read_request *new_reqgroup; int blockidx, timestep, timestep_blockidx; int curblocks, start_blockidx, end_blockidx; int intersects; ADIOS_VARBLOCK *raw_vb, *vb; enum ADIOS_FLAG swap_endianness = (fp->endianness == get_system_endianness()) ? adios_flag_no : adios_flag_yes; int to_steps = from_step + nsteps; // As long as we don't free/destroy it, using the infocache from the file will have no effect on future // operations using the file (except possibly speeding them up, so "constness" is still respected adios_infocache *infocache = common_read_get_file_infocache((ADIOS_FILE*)fp); ADIOS_PG_INTERSECTIONS *resulting_intersections = (ADIOS_PG_INTERSECTIONS *)calloc(1, sizeof(ADIOS_PG_INTERSECTIONS)); resulting_intersections->npg = 0; int intersection_capacity = INITIAL_INTERSECTION_CAPACITY; resulting_intersections->intersections = (ADIOS_PG_INTERSECTION *)calloc(intersection_capacity, sizeof(ADIOS_PG_INTERSECTION)); // Precondition checking if (sel->type != ADIOS_SELECTION_BOUNDINGBOX && sel->type != ADIOS_SELECTION_POINTS) { adios_error(err_operation_not_supported, "Only bounding box and point selections are currently supported during read on transformed variables."); } // Still respecting constness, since we're going to undo this const data_view_t old_view = adios_read_set_data_view((ADIOS_FILE*)fp, LOGICAL_DATA_VIEW); // Temporarily go to logical data view const ADIOS_VARINFO *varinfo = adios_infocache_inq_varinfo(fp, infocache, varid); assert(from_step >= 0 && to_steps <= varinfo->nsteps); // Compute the blockidx range, given the timesteps compute_blockidx_range(varinfo, from_step, to_steps, &start_blockidx, &end_blockidx); // Retrieve blockinfos, if they haven't been done retrieved if (!varinfo->blockinfo) common_read_inq_var_blockinfo(fp, (ADIOS_VARINFO *)varinfo); // Undoing view set (returning to const state) adios_read_set_data_view((ADIOS_FILE*)fp, old_view); // Reset the data view to whatever it was before // Assemble read requests for each varblock blockidx = start_blockidx; timestep = from_step; timestep_blockidx = 0; while (blockidx != end_blockidx) { //for (blockidx = startblock_idx; blockidx != endblock_idx; blockidx++) { ADIOS_SELECTION *pg_bounds_sel; ADIOS_SELECTION *pg_intersection_sel; vb = &varinfo->blockinfo[blockidx]; pg_bounds_sel = create_pg_bounds(varinfo->ndim, vb); // Find the intersection, if any pg_intersection_sel = adios_selection_intersect_global(pg_bounds_sel, sel); if (pg_intersection_sel) { // Expand the PG intersection array, if needed if (resulting_intersections->npg == intersection_capacity) { intersection_capacity *= 2; resulting_intersections->intersections = (ADIOS_PG_INTERSECTION *)realloc(resulting_intersections->intersections, intersection_capacity * sizeof(ADIOS_PG_INTERSECTION)); if (!resulting_intersections->intersections) { adios_error (err_no_memory, "Cannot allocate buffer for PG intersection results in adios_find_intersecting_pgs (required %llu bytes)\n", intersection_capacity * sizeof(ADIOS_PG_INTERSECTION)); return NULL; } } ADIOS_PG_INTERSECTION *intersection = &resulting_intersections->intersections[resulting_intersections->npg]; intersection->timestep = timestep; intersection->blockidx = blockidx; intersection->blockidx_in_timestep = timestep_blockidx; intersection->intersection_sel = pg_intersection_sel; intersection->pg_bounds_sel = pg_bounds_sel; resulting_intersections->npg++; } else { // Cleanup common_read_selection_delete(pg_bounds_sel); // OK to delete, because this function only frees the outer struct, not the arrays within } // Increment block indexes blockidx++; timestep_blockidx++; if (timestep_blockidx == varinfo->nblocks[timestep]) { timestep_blockidx = 0; timestep++; } } return resulting_intersections; }