| /*BHEADER********************************************************************** |
| * (c) 1997 The Regents of the University of California |
| * |
| * See the file COPYRIGHT_and_DISCLAIMER for a complete copyright |
| * notice, contact person, and disclaimer. |
| * |
| * $Revision$ |
| *********************************************************************EHEADER*/ |
| /****************************************************************************** |
| * |
| * Member functions for hypre_Box class: |
| * Box algebra functions. |
| * |
| *****************************************************************************/ |
| |
| #include "headers.h" |
| |
| /*-------------------------------------------------------------------------- |
| * hypre_IntersectBoxes: |
| * Intersect box1 and box2. |
| * If the boxes do not intersect, the result is a box with zero volume. |
| *--------------------------------------------------------------------------*/ |
| |
| int |
| hypre_IntersectBoxes( hypre_Box *box1, |
| hypre_Box *box2, |
| hypre_Box *ibox ) |
| { |
| int ierr = 0; |
| int d; |
| |
| /* find x, y, and z bounds */ |
| for (d = 0; d < 3; d++) |
| { |
| hypre_BoxIMinD(ibox, d) = |
| hypre_max(hypre_BoxIMinD(box1, d), hypre_BoxIMinD(box2, d)); |
| hypre_BoxIMaxD(ibox, d) = |
| hypre_min(hypre_BoxIMaxD(box1, d), hypre_BoxIMaxD(box2, d)); |
| } |
| |
| return ierr; |
| } |
| |
| /*-------------------------------------------------------------------------- |
| * hypre_SubtractBoxes: |
| * Compute box1 - box2. |
| *--------------------------------------------------------------------------*/ |
| |
| int |
| hypre_SubtractBoxes( hypre_Box *box1, |
| hypre_Box *box2, |
| hypre_BoxArray *box_array ) |
| { |
| int ierr = 0; |
| |
| hypre_Box *box; |
| hypre_Box *rembox; |
| int d, size; |
| |
| /*------------------------------------------------------ |
| * Set the box array size to the maximum possible, |
| * plus one, to have space for the remainder box. |
| *------------------------------------------------------*/ |
| |
| hypre_BoxArraySetSize(box_array, 7); |
| |
| /*------------------------------------------------------ |
| * Subtract the boxes by cutting box1 in x, y, then z |
| *------------------------------------------------------*/ |
| |
| rembox = hypre_BoxArrayBox(box_array, 6); |
| hypre_CopyBox(box1, rembox); |
| |
| size = 0; |
| for (d = 0; d < 3; d++) |
| { |
| /* if the boxes do not intersect, the subtraction is trivial */ |
| if ( (hypre_BoxIMinD(box2, d) > hypre_BoxIMaxD(rembox, d)) || |
| (hypre_BoxIMaxD(box2, d) < hypre_BoxIMinD(rembox, d)) ) |
| { |
| hypre_CopyBox(box1, hypre_BoxArrayBox(box_array, 0)); |
| size = 1; |
| break; |
| } |
| |
| /* update the box array */ |
| else |
| { |
| if ( hypre_BoxIMinD(box2, d) > hypre_BoxIMinD(rembox, d) ) |
| { |
| box = hypre_BoxArrayBox(box_array, size); |
| hypre_CopyBox(rembox, box); |
| hypre_BoxIMaxD(box, d) = hypre_BoxIMinD(box2, d) - 1; |
| hypre_BoxIMinD(rembox, d) = hypre_BoxIMinD(box2, d); |
| size++; |
| } |
| if ( hypre_BoxIMaxD(box2, d) < hypre_BoxIMaxD(rembox, d) ) |
| { |
| box = hypre_BoxArrayBox(box_array, size); |
| hypre_CopyBox(rembox, box); |
| hypre_BoxIMinD(box, d) = hypre_BoxIMaxD(box2, d) + 1; |
| hypre_BoxIMaxD(rembox, d) = hypre_BoxIMaxD(box2, d); |
| size++; |
| } |
| } |
| } |
| hypre_BoxArraySetSize(box_array, size); |
| |
| return ierr; |
| } |
| |
| /*-------------------------------------------------------------------------- |
| * hypre_UnionBoxes: |
| * Compute the union of all boxes. |
| * |
| * To compute the union, we first construct a logically rectangular, |
| * variably spaced, 3D grid called block. Each cell (i,j,k) of block |
| * corresponds to a box with extents given by |
| * |
| * iminx = block_index[0][i] |
| * iminy = block_index[1][j] |
| * iminz = block_index[2][k] |
| * imaxx = block_index[0][i+1] - 1 |
| * imaxy = block_index[1][j+1] - 1 |
| * imaxz = block_index[2][k+1] - 1 |
| * |
| * The size of block is given by |
| * |
| * sizex = block_sz[0] |
| * sizey = block_sz[1] |
| * sizez = block_sz[2] |
| * |
| * We initially set all cells of block that are part of the union to |
| * |
| * factor[2] + factor[1] + factor[0] |
| * |
| * where |
| * |
| * factor[0] = 1; |
| * factor[1] = (block_sz[0] + 1); |
| * factor[2] = (block_sz[1] + 1) * factor[1]; |
| * |
| * The cells of block are then "joined" in x first, then y, then z. |
| * The result is that each nonzero entry of block corresponds to a |
| * box in the union with extents defined by factoring the entry, then |
| * indexing into the block_index array. |
| * |
| * Note: Special care has to be taken for boxes of size 0. |
| * |
| *--------------------------------------------------------------------------*/ |
| |
| int |
| hypre_UnionBoxes( hypre_BoxArray *boxes ) |
| { |
| int ierr = 0; |
| |
| hypre_Box *box; |
| |
| int *block_index[3]; |
| int block_sz[3], block_volume; |
| int *block; |
| int index; |
| int size; |
| int factor[3]; |
| |
| int iminmax[2], imin[3], imax[3]; |
| int ii[3], dd[3]; |
| int join; |
| int i_tmp0, i_tmp1; |
| int ioff, joff, koff; |
| int bi, d, i, j, k; |
| |
| int index_not_there; |
| |
| /*------------------------------------------------------ |
| * If the size of boxes is less than 2, return |
| *------------------------------------------------------*/ |
| |
| if (hypre_BoxArraySize(boxes) < 2) |
| { |
| return ierr; |
| } |
| |
| /*------------------------------------------------------ |
| * Set up the block_index array |
| *------------------------------------------------------*/ |
| |
| i_tmp0 = 2 * hypre_BoxArraySize(boxes); |
| block_index[0] = hypre_TAlloc(int, 3 * i_tmp0); |
| block_sz[0] = 0; |
| for (d = 1; d < 3; d++) |
| { |
| block_index[d] = block_index[d-1] + i_tmp0; |
| block_sz[d] = 0; |
| } |
| |
| hypre_ForBoxI(bi, boxes) |
| { |
| box = hypre_BoxArrayBox(boxes, bi); |
| |
| for (d = 0; d < 3; d++) |
| { |
| iminmax[0] = hypre_BoxIMinD(box, d); |
| iminmax[1] = hypre_BoxIMaxD(box, d) + 1; |
| |
| for (i = 0; i < 2; i++) |
| { |
| /* find the new index position in the block_index array */ |
| index_not_there = 1; |
| for (j = 0; j < block_sz[d]; j++) |
| { |
| if (iminmax[i] <= block_index[d][j]) |
| { |
| if (iminmax[i] == block_index[d][j]) |
| index_not_there = 0; |
| break; |
| } |
| } |
| |
| /* if the index is already there, don't add it again */ |
| if (index_not_there) |
| { |
| for (k = block_sz[d]; k > j; k--) |
| block_index[d][k] = block_index[d][k-1]; |
| block_index[d][j] = iminmax[i]; |
| block_sz[d]++; |
| } |
| } |
| } |
| } |
| |
| for (d = 0; d < 3; d++) |
| block_sz[d]--; |
| block_volume = block_sz[0] * block_sz[1] * block_sz[2]; |
| |
| /*------------------------------------------------------ |
| * Set factor values |
| *------------------------------------------------------*/ |
| |
| factor[0] = 1; |
| factor[1] = (block_sz[0] + 1); |
| factor[2] = (block_sz[1] + 1) * factor[1]; |
| |
| /*------------------------------------------------------ |
| * Set up the block array |
| *------------------------------------------------------*/ |
| |
| block = hypre_CTAlloc(int, block_volume); |
| |
| hypre_ForBoxI(bi, boxes) |
| { |
| box = hypre_BoxArrayBox(boxes, bi); |
| |
| /* find the block_index indices corresponding to the current box */ |
| for (d = 0; d < 3; d++) |
| { |
| j = 0; |
| |
| while (hypre_BoxIMinD(box, d) != block_index[d][j]) |
| j++; |
| imin[d] = j; |
| |
| while (hypre_BoxIMaxD(box, d) + 1 != block_index[d][j]) |
| j++; |
| imax[d] = j; |
| } |
| |
| /* note: boxes of size zero will not be added to block */ |
| for (k = imin[2]; k < imax[2]; k++) |
| { |
| for (j = imin[1]; j < imax[1]; j++) |
| { |
| for (i = imin[0]; i < imax[0]; i++) |
| { |
| index = ((k) * block_sz[1] + j) * block_sz[0] + i; |
| |
| block[index] = factor[2] + factor[1] + factor[0]; |
| } |
| } |
| } |
| } |
| |
| /*------------------------------------------------------ |
| * Join block array in x, then y, then z |
| * |
| * Notes: |
| * - ii[0], ii[1], and ii[2] correspond to indices |
| * in x, y, and z respectively. |
| * - dd specifies the order in which to loop over |
| * the three dimensions. |
| *------------------------------------------------------*/ |
| |
| for (d = 0; d < 3; d++) |
| { |
| switch(d) |
| { |
| case 0: /* join in x */ |
| dd[0] = 0; |
| dd[1] = 1; |
| dd[2] = 2; |
| break; |
| |
| case 1: /* join in y */ |
| dd[0] = 1; |
| dd[1] = 0; |
| dd[2] = 2; |
| break; |
| |
| case 2: /* join in z */ |
| dd[0] = 2; |
| dd[1] = 1; |
| dd[2] = 0; |
| break; |
| } |
| |
| for (ii[dd[2]] = 0; ii[dd[2]] < block_sz[dd[2]]; ii[dd[2]]++) |
| { |
| for (ii[dd[1]] = 0; ii[dd[1]] < block_sz[dd[1]]; ii[dd[1]]++) |
| { |
| join = 0; |
| for (ii[dd[0]] = 0; ii[dd[0]] < block_sz[dd[0]]; ii[dd[0]]++) |
| { |
| index = ((ii[2]) * block_sz[1] + ii[1]) * block_sz[0] + ii[0]; |
| |
| if ((join) && (block[index] == i_tmp1)) |
| { |
| block[index] = 0; |
| block[i_tmp0] += factor[dd[0]]; |
| } |
| else |
| { |
| if (block[index]) |
| { |
| i_tmp0 = index; |
| i_tmp1 = block[index]; |
| join = 1; |
| } |
| else |
| join = 0; |
| } |
| } |
| } |
| } |
| } |
| |
| /*------------------------------------------------------ |
| * Set up the boxes BoxArray |
| *------------------------------------------------------*/ |
| |
| size = 0; |
| for (index = 0; index < block_volume; index++) |
| { |
| if (block[index]) |
| size++; |
| } |
| hypre_BoxArraySetSize(boxes, size); |
| |
| index = 0; |
| size = 0; |
| for (k = 0; k < block_sz[2]; k++) |
| { |
| for (j = 0; j < block_sz[1]; j++) |
| { |
| for (i = 0; i < block_sz[0]; i++) |
| { |
| if (block[index]) |
| { |
| ioff = (block[index] % factor[1]) ; |
| joff = (block[index] % factor[2]) / factor[1]; |
| koff = (block[index] ) / factor[2]; |
| |
| box = hypre_BoxArrayBox(boxes, size); |
| hypre_BoxIMinD(box, 0) = block_index[0][i]; |
| hypre_BoxIMinD(box, 1) = block_index[1][j]; |
| hypre_BoxIMinD(box, 2) = block_index[2][k]; |
| hypre_BoxIMaxD(box, 0) = block_index[0][i + ioff] - 1; |
| hypre_BoxIMaxD(box, 1) = block_index[1][j + joff] - 1; |
| hypre_BoxIMaxD(box, 2) = block_index[2][k + koff] - 1; |
| |
| size++; |
| } |
| |
| index++; |
| } |
| } |
| } |
| |
| /*--------------------------------------------------------- |
| * Clean up and return |
| *---------------------------------------------------------*/ |
| |
| hypre_TFree(block_index[0]); |
| hypre_TFree(block); |
| |
| return ierr; |
| } |
| |