// // One-on-one global intersection functions // ADIOS_SELECTION * adios_selection_intersect_wb_wb(const ADIOS_SELECTION_WRITEBLOCK_STRUCT *wb1, const ADIOS_SELECTION_WRITEBLOCK_STRUCT *wb2, int timestep, const ADIOS_VARINFO *raw_varinfo, const ADIOS_TRANSINFO *transinfo) { int is_abs_idx; int wbindex; if (wb1->is_absolute_index == wb2->is_absolute_index) { const int index1 = wb1->index; const int index2 = wb2->index; if (index1 != index2) return NULL; wbindex = index1; is_abs_idx = wb1->is_absolute_index; } else { const int index1 = wb1->is_absolute_index ? wb1->index : adios_get_absolute_writeblock_index(raw_varinfo, wb1->index, timestep); const int index2 = wb2->is_absolute_index ? wb2->index : adios_get_absolute_writeblock_index(raw_varinfo, wb2->index, timestep); if (index1 != index2) return NULL; wbindex = index1; is_abs_idx = 1; } if (!wb1->is_sub_pg_selection && !wb2->is_sub_pg_selection) { // If neither selection is a sub-PG selection, the result is easy, and we can return immediately ADIOS_SELECTION *inter_sel = common_read_selection_writeblock(wbindex); inter_sel->u.block.is_absolute_index = is_abs_idx; return inter_sel; } else if (wb1->is_sub_pg_selection && wb2->is_sub_pg_selection) { // Else, if both selections are sub-PG selections, take the overlapping portion (if any) uint64_t inter_elem_offset, inter_nelems; int intersects = intersect_segments( wb1->element_offset, wb1->nelements, wb2->element_offset, wb2->nelements, &inter_elem_offset, &inter_nelems ); if (intersects) { ADIOS_SELECTION *inter_sel = common_read_selection_writeblock(wbindex); inter_sel->u.block.is_absolute_index = is_abs_idx; inter_sel->u.block.is_sub_pg_selection = 1; inter_sel->u.block.element_offset = inter_elem_offset; inter_sel->u.block.nelements = inter_nelems; return inter_sel; } else { return NULL; } } else if (wb1->is_sub_pg_selection) { // Else, if only the first selection is sub-PG, so just use its range ADIOS_SELECTION *newwb = common_read_selection_writeblock(wb1->index); newwb->u.block = *wb1; return newwb; } else if (wb2->is_sub_pg_selection) { // Else, only the second selection is sub-PG, so just use its range ADIOS_SELECTION *newwb = common_read_selection_writeblock(wb2->index); newwb->u.block = *wb2; return newwb; } else { abort(); // Should not be possible' return NULL; } }
/* 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; } }