1 /******************************************************************************
2  * Copyright 1998-2019 Lawrence Livermore National Security, LLC and other
3  * HYPRE Project Developers. See the top-level COPYRIGHT file for details.
4  *
5  * SPDX-License-Identifier: (Apache-2.0 OR MIT)
6  ******************************************************************************/
7 
8 /******************************************************************************
9  *
10  * Member functions for hypre_StructGrid class.
11  *
12  *****************************************************************************/
13 
14 #include "_hypre_struct_mv.h"
15 
16 #define DEBUG 0
17 
18 #if DEBUG
19 char       filename[255];
20 FILE      *file;
21 HYPRE_Int  my_rank;
22 #endif
23 
24 static HYPRE_Int time_index = 0;
25 
26 /*--------------------------------------------------------------------------
27  * hypre_StructGridCreate
28  *--------------------------------------------------------------------------*/
29 
30 HYPRE_Int
hypre_StructGridCreate(MPI_Comm comm,HYPRE_Int ndim,hypre_StructGrid ** grid_ptr)31 hypre_StructGridCreate( MPI_Comm           comm,
32                         HYPRE_Int          ndim,
33                         hypre_StructGrid **grid_ptr)
34 {
35    hypre_StructGrid    *grid;
36    HYPRE_Int           i;
37 
38    grid = hypre_TAlloc(hypre_StructGrid,  1, HYPRE_MEMORY_HOST);
39 
40    hypre_StructGridComm(grid)        = comm;
41    hypre_StructGridNDim(grid)        = ndim;
42    hypre_StructGridBoxes(grid)       = hypre_BoxArrayCreate(0, ndim);
43    hypre_StructGridIDs(grid)         = NULL;
44 
45    hypre_SetIndex(hypre_StructGridMaxDistance(grid),8);
46 
47    hypre_StructGridBoundingBox(grid) = NULL;
48    hypre_StructGridLocalSize(grid)   = 0;
49    hypre_StructGridGlobalSize(grid)  = 0;
50    hypre_SetIndex(hypre_StructGridPeriodic(grid), 0);
51    hypre_StructGridRefCount(grid)     = 1;
52    hypre_StructGridBoxMan(grid)       = NULL;
53 
54    hypre_StructGridNumPeriods(grid)   = 1;
55    hypre_StructGridPShifts(grid)     = NULL;
56 
57    hypre_StructGridGhlocalSize(grid)  = 0;
58    for (i = 0; i < 2*ndim; i++)
59    {
60       hypre_StructGridNumGhost(grid)[i] = 1;
61    }
62 
63 #if 0 //defined(HYPRE_USING_CUDA) || defined(HYPRE_USING_HIP)
64    hypre_StructGridDataLocation(grid) = HYPRE_MEMORY_DEVICE;
65 #endif
66    *grid_ptr = grid;
67 
68    return hypre_error_flag;
69 }
70 
71 /*--------------------------------------------------------------------------
72  * hypre_StructGridRef
73  *--------------------------------------------------------------------------*/
74 
75 HYPRE_Int
hypre_StructGridRef(hypre_StructGrid * grid,hypre_StructGrid ** grid_ref)76 hypre_StructGridRef( hypre_StructGrid  *grid,
77                      hypre_StructGrid **grid_ref)
78 {
79    hypre_StructGridRefCount(grid) ++;
80    *grid_ref = grid;
81 
82    return hypre_error_flag;
83 }
84 
85 /*--------------------------------------------------------------------------
86  * hypre_StructGridDestroy
87  *--------------------------------------------------------------------------*/
88 
89 HYPRE_Int
hypre_StructGridDestroy(hypre_StructGrid * grid)90 hypre_StructGridDestroy( hypre_StructGrid *grid )
91 {
92    if (grid)
93    {
94       hypre_StructGridRefCount(grid) --;
95       if (hypre_StructGridRefCount(grid) == 0)
96       {
97          hypre_BoxDestroy(hypre_StructGridBoundingBox(grid));
98          hypre_TFree(hypre_StructGridIDs(grid), HYPRE_MEMORY_HOST);
99          hypre_BoxArrayDestroy(hypre_StructGridBoxes(grid));
100 
101          hypre_BoxManDestroy(hypre_StructGridBoxMan(grid));
102          hypre_TFree( hypre_StructGridPShifts(grid), HYPRE_MEMORY_HOST);
103 
104          hypre_TFree(grid, HYPRE_MEMORY_HOST);
105       }
106    }
107 
108    return hypre_error_flag;
109 }
110 
111 
112 /*--------------------------------------------------------------------------
113  * hypre_StructGridSetPeriodic
114  *--------------------------------------------------------------------------*/
115 
116 HYPRE_Int
hypre_StructGridSetPeriodic(hypre_StructGrid * grid,hypre_Index periodic)117 hypre_StructGridSetPeriodic( hypre_StructGrid  *grid,
118                              hypre_Index        periodic)
119 {
120    hypre_CopyIndex(periodic, hypre_StructGridPeriodic(grid));
121 
122    return hypre_error_flag;
123 }
124 
125 /*--------------------------------------------------------------------------
126  * hypre_StructGridSetExtents
127  *--------------------------------------------------------------------------*/
128 
129 HYPRE_Int
hypre_StructGridSetExtents(hypre_StructGrid * grid,hypre_Index ilower,hypre_Index iupper)130 hypre_StructGridSetExtents( hypre_StructGrid  *grid,
131                             hypre_Index        ilower,
132                             hypre_Index        iupper )
133 {
134    hypre_Box   *box;
135 
136    box = hypre_BoxCreate(hypre_StructGridNDim(grid));
137    hypre_BoxSetExtents(box, ilower, iupper);
138    hypre_AppendBox(box, hypre_StructGridBoxes(grid));
139    hypre_BoxDestroy(box);
140 
141    return hypre_error_flag;
142 }
143 
144 /*--------------------------------------------------------------------------
145  * hypre_StructGridSetBoxes
146  *--------------------------------------------------------------------------*/
147 
148 HYPRE_Int
hypre_StructGridSetBoxes(hypre_StructGrid * grid,hypre_BoxArray * boxes)149 hypre_StructGridSetBoxes( hypre_StructGrid *grid,
150                           hypre_BoxArray   *boxes )
151 {
152 
153    hypre_TFree(hypre_StructGridBoxes(grid), HYPRE_MEMORY_HOST);
154    hypre_StructGridBoxes(grid) = boxes;
155 
156    return hypre_error_flag;
157 }
158 
159 /*--------------------------------------------------------------------------
160  * hypre_StructGridSetBoundingBox
161  *--------------------------------------------------------------------------*/
162 
163 HYPRE_Int
hypre_StructGridSetBoundingBox(hypre_StructGrid * grid,hypre_Box * new_bb)164 hypre_StructGridSetBoundingBox( hypre_StructGrid *grid,
165                                 hypre_Box   *new_bb )
166 {
167 
168    hypre_BoxDestroy(hypre_StructGridBoundingBox(grid));
169    hypre_StructGridBoundingBox(grid) = hypre_BoxDuplicate(new_bb);
170 
171    return hypre_error_flag;
172 }
173 
174 /*--------------------------------------------------------------------------
175  * hypre_StructGridSetIDs
176  *--------------------------------------------------------------------------*/
177 
178 HYPRE_Int
hypre_StructGridSetIDs(hypre_StructGrid * grid,HYPRE_Int * ids)179 hypre_StructGridSetIDs( hypre_StructGrid *grid,
180                         HYPRE_Int   *ids )
181 {
182    hypre_TFree(hypre_StructGridIDs(grid), HYPRE_MEMORY_HOST);
183    hypre_StructGridIDs(grid) = ids;
184 
185    return hypre_error_flag;
186 }
187 
188 /*--------------------------------------------------------------------------
189  * hypre_StructGridSetBoxManager
190  *--------------------------------------------------------------------------*/
191 
192 HYPRE_Int
hypre_StructGridSetBoxManager(hypre_StructGrid * grid,hypre_BoxManager * boxman)193 hypre_StructGridSetBoxManager( hypre_StructGrid *grid,
194                                hypre_BoxManager *boxman )
195 {
196 
197    hypre_TFree(hypre_StructGridBoxMan(grid), HYPRE_MEMORY_HOST);
198    hypre_StructGridBoxMan(grid) = boxman;
199 
200    return hypre_error_flag;
201 }
202 
203 /*--------------------------------------------------------------------------
204  * hypre_StructGridSetMaxDistance
205  *--------------------------------------------------------------------------*/
206 
207 HYPRE_Int
hypre_StructGridSetMaxDistance(hypre_StructGrid * grid,hypre_Index dist)208 hypre_StructGridSetMaxDistance( hypre_StructGrid *grid,
209                                 hypre_Index dist )
210 {
211    hypre_CopyIndex(dist, hypre_StructGridMaxDistance(grid));
212 
213    return hypre_error_flag;
214 }
215 
216 /*--------------------------------------------------------------------------
217  * New - hypre_StructGridAssemble
218  * AHB 9/06
219  * New assemble routine that uses the BoxManager structure
220  *
221  *   Notes:
222  *   1. No longer need a different assemble for the assumed partition case
223  *   2. if this is called from StructCoarsen, then the Box Manager has already
224  *   been created, and ids have been set
225  *
226  *--------------------------------------------------------------------------*/
227 
228 HYPRE_Int
hypre_StructGridAssemble(hypre_StructGrid * grid)229 hypre_StructGridAssemble( hypre_StructGrid *grid )
230 {
231 
232    HYPRE_Int d, k, p, i;
233 
234    HYPRE_Int is_boxman;
235    HYPRE_Int size, ghostsize;
236    HYPRE_Int num_local_boxes;
237    HYPRE_Int myid, num_procs;
238    HYPRE_BigInt global_size;
239    HYPRE_Int max_nentries;
240    HYPRE_Int info_size;
241    HYPRE_Int num_periods;
242 
243    HYPRE_Int *ids = NULL;
244    HYPRE_Int  iperiodic, notcenter;
245 
246    HYPRE_Int  sendbuf6[2*HYPRE_MAXDIM], recvbuf6[2*HYPRE_MAXDIM];
247 
248    hypre_Box  *box;
249    hypre_Box  *ghostbox;
250    hypre_Box  *grow_box;
251    hypre_Box  *periodic_box;
252    hypre_Box  *result_box;
253 
254    hypre_Index min_index, max_index, loop_size;
255    hypre_Index *pshifts;
256    hypre_IndexRef pshift;
257 
258    void *entry_info = NULL;
259 
260    /*  initialize info from the grid */
261    MPI_Comm             comm         = hypre_StructGridComm(grid);
262    HYPRE_Int            ndim         = hypre_StructGridNDim(grid);
263    hypre_BoxArray      *local_boxes  = hypre_StructGridBoxes(grid);
264    hypre_IndexRef       max_distance = hypre_StructGridMaxDistance(grid);
265    hypre_Box           *bounding_box = hypre_StructGridBoundingBox(grid);
266    hypre_IndexRef       periodic     = hypre_StructGridPeriodic(grid);
267    hypre_BoxManager    *boxman       = hypre_StructGridBoxMan(grid);
268    HYPRE_Int           *numghost     = hypre_StructGridNumGhost(grid);
269 
270    if (!time_index)
271       time_index = hypre_InitializeTiming("StructGridAssemble");
272 
273    hypre_BeginTiming(time_index);
274 
275    /* other initializations */
276    num_local_boxes = hypre_BoxArraySize(local_boxes);
277 
278    hypre_MPI_Comm_size(comm, &num_procs);
279    hypre_MPI_Comm_rank(comm, &myid);
280 
281    /* has the box manager been created? */
282    if (boxman == NULL)
283    {
284       is_boxman = 0;
285    }
286    else
287    {
288       is_boxman = 1;
289    }
290 
291    /* are the ids known? (these may have been set in coarsen)  - if not we need
292       to set them */
293    if (hypre_StructGridIDs(grid) == NULL)
294    {
295       ids = hypre_CTAlloc(HYPRE_Int,  num_local_boxes, HYPRE_MEMORY_HOST);
296       for (i=0; i< num_local_boxes; i++)
297       {
298          ids[i] = i;
299       }
300       hypre_StructGridIDs(grid) = ids;
301    }
302    else
303    {
304       ids = hypre_StructGridIDs(grid);
305    }
306 
307    /******** calculate the periodicity information ****************/
308 
309    box = hypre_BoxCreate(ndim);
310    for (d = 0; d < ndim; d++)
311    {
312       iperiodic = hypre_IndexD(periodic, d) ? 1 : 0;
313       hypre_BoxIMinD(box, d) = -iperiodic;
314       hypre_BoxIMaxD(box, d) =  iperiodic;
315    }
316    num_periods = hypre_BoxVolume(box);
317 
318    pshifts = hypre_CTAlloc(hypre_Index,  num_periods, HYPRE_MEMORY_HOST);
319    pshift = pshifts[0];
320    hypre_SetIndex(pshift, 0);
321    if (num_periods > 1)
322    {
323       p = 1;
324       hypre_BoxGetSize(box, loop_size);
325       hypre_SerialBoxLoop0Begin(ndim, loop_size);
326       {
327          pshift = pshifts[p];
328          zypre_BoxLoopGetIndex(pshift);
329          hypre_AddIndexes(pshift, hypre_BoxIMin(box), ndim, pshift);
330          notcenter = 0;
331          for (d = 0; d < ndim; d++)
332          {
333             hypre_IndexD(pshift, d) *= hypre_IndexD(periodic, d);
334             if (hypre_IndexD(pshift, d))
335             {
336                notcenter = 1;
337             }
338          }
339          if (notcenter)
340          {
341             p++;
342          }
343       }
344       hypre_SerialBoxLoop0End();
345    }
346    hypre_BoxDestroy(box);
347 
348    hypre_StructGridNumPeriods(grid) = num_periods;
349    hypre_StructGridPShifts(grid)    = pshifts;
350 
351    /********calculate local size and the ghost size **************/
352 
353    size = 0;
354    ghostsize = 0;
355    ghostbox = hypre_BoxCreate(ndim);
356 
357    hypre_ForBoxI(i, local_boxes)
358    {
359       box = hypre_BoxArrayBox(local_boxes, i);
360       size +=  hypre_BoxVolume(box);
361 
362       hypre_CopyBox(box, ghostbox);
363       hypre_BoxGrowByArray(ghostbox, numghost);
364       ghostsize += hypre_BoxVolume(ghostbox);
365    }
366 
367    hypre_StructGridLocalSize(grid) = size;
368    hypre_StructGridGhlocalSize(grid) = ghostsize;
369    hypre_BoxDestroy(ghostbox);
370 
371    /* if the box manager has been created then we don't need to do the
372     * following (because it was done through the coarsening routine) */
373    if (!is_boxman)
374    {
375       /*************** set the global size *****************/
376 
377       HYPRE_BigInt big_size = (HYPRE_BigInt)size;
378       hypre_MPI_Allreduce(&big_size, &global_size, 1, HYPRE_MPI_BIG_INT,
379                           hypre_MPI_SUM, comm);
380       hypre_StructGridGlobalSize(grid) = global_size; /* TO DO: this HYPRE_Int
381                                                        * could overflow! (used
382                                                        * to calc flops) */
383 
384       /*************** set bounding box ***********/
385 
386       bounding_box = hypre_BoxCreate(ndim);
387 
388       if (num_local_boxes)
389       {
390          /* initialize min and max index*/
391          box = hypre_BoxArrayBox(local_boxes, 0);
392          for (d = 0; d < ndim; d++)
393          {
394             hypre_IndexD(min_index, d) =  hypre_BoxIMinD(box, d);
395             hypre_IndexD(max_index, d) =  hypre_BoxIMaxD(box, d);
396          }
397 
398          hypre_ForBoxI(i, local_boxes)
399          {
400             box = hypre_BoxArrayBox(local_boxes, i);
401 
402 
403             /* find min and max box extents */
404             for (d = 0; d < ndim; d++)
405             {
406                hypre_IndexD(min_index, d) = hypre_min( hypre_IndexD(min_index, d),
407                                                        hypre_BoxIMinD(box, d));
408                hypre_IndexD(max_index, d) = hypre_max( hypre_IndexD(max_index, d),
409                                                        hypre_BoxIMaxD(box, d));
410             }
411          }
412          /*set bounding box (this is still based on local info only) */
413          hypre_BoxSetExtents(bounding_box, min_index, max_index);
414 
415       }
416       else /* no boxes owned*/
417       {
418          /* initialize min and max */
419          for (d = 0; d < ndim; d++)
420          {
421             hypre_BoxIMinD(bounding_box, d) =  hypre_pow2(30);
422             hypre_BoxIMaxD(bounding_box, d) = -hypre_pow2(30);
423          }
424       }
425       /* set the extra dimensions of the bounding box to zero */
426       for (d = ndim; d < HYPRE_MAXDIM; d++)
427       {
428          hypre_BoxIMinD(bounding_box, d) = 0;
429          hypre_BoxIMaxD(bounding_box, d) = 0;
430       }
431 
432       /* communication needed for the bounding box */
433       /* pack buffer */
434       for (d = 0; d < ndim; d++)
435       {
436          sendbuf6[d] = hypre_BoxIMinD(bounding_box, d);
437          sendbuf6[d+ndim] = -hypre_BoxIMaxD(bounding_box, d);
438       }
439       hypre_MPI_Allreduce(sendbuf6, recvbuf6, 2*ndim, HYPRE_MPI_INT,
440                           hypre_MPI_MIN, comm);
441       /* unpack buffer */
442       for (d = 0; d < ndim; d++)
443       {
444          hypre_BoxIMinD(bounding_box, d) = recvbuf6[d];
445          hypre_BoxIMaxD(bounding_box, d) = -recvbuf6[d+ndim];
446       }
447 
448       hypre_StructGridBoundingBox(grid) = bounding_box;
449 
450       /*************** create a box manager *****************/
451       max_nentries =  num_local_boxes + 20;
452       info_size = 0; /* we don't need an info object */
453       hypre_BoxManCreate(max_nentries, info_size, ndim, bounding_box,
454                          comm, &boxman);
455 
456       /******** populate the box manager with my local boxes and gather neighbor
457                 information  ******/
458 
459       grow_box = hypre_BoxCreate(ndim);
460       result_box = hypre_BoxCreate(ndim);
461       periodic_box = hypre_BoxCreate(ndim);
462 
463       /* now loop through each local box */
464       hypre_ForBoxI(i, local_boxes)
465       {
466          box = hypre_BoxArrayBox(local_boxes, i);
467          /* add entry for each local box (the id is the boxnum, and should be
468             sequential */
469          hypre_BoxManAddEntry( boxman, hypre_BoxIMin(box), hypre_BoxIMax(box),
470                                myid, i, entry_info );
471 
472          /* now expand box by max_distance or larger and gather entries */
473          hypre_CopyBox(box ,grow_box);
474          hypre_BoxGrowByIndex(grow_box, max_distance);
475          hypre_BoxManGatherEntries(boxman, hypre_BoxIMin(grow_box),
476                                    hypre_BoxIMax(grow_box));
477 
478          /* now repeat for any periodic boxes - by shifting the grow_box*/
479          for (k=1; k < num_periods; k++) /* k=0 is original box */
480          {
481             hypre_CopyBox(grow_box, periodic_box);
482             pshift = pshifts[k];
483             hypre_BoxShiftPos(periodic_box, pshift);
484 
485             /* see if the shifted box intersects the domain */
486             hypre_IntersectBoxes(periodic_box, bounding_box, result_box);
487             /* if so, call gather entries */
488             if (hypre_BoxVolume(result_box) > 0)
489             {
490                hypre_BoxManGatherEntries(boxman, hypre_BoxIMin(periodic_box),
491                                          hypre_BoxIMax(periodic_box));
492             }
493          }
494       }/* end of for each local box */
495 
496       hypre_BoxDestroy(periodic_box);
497       hypre_BoxDestroy(grow_box);
498       hypre_BoxDestroy(result_box);
499 
500    } /* end of if (!is_boxman) */
501 
502    /* boxman was created, but need to get additional neighbor info */
503    else if ( hypre_IndexEqual(max_distance, 0, ndim) )
504    {
505       /* pick a new max distance and set in grid*/
506       hypre_SetIndex(hypre_StructGridMaxDistance(grid), 2);
507       max_distance =  hypre_StructGridMaxDistance(grid);
508 
509       grow_box = hypre_BoxCreate(ndim);
510       result_box = hypre_BoxCreate(ndim);
511       periodic_box = hypre_BoxCreate(ndim);
512 
513       /* now loop through each local box */
514       hypre_ForBoxI(i, local_boxes)
515       {
516          box = hypre_BoxArrayBox(local_boxes, i);
517 
518          /* now expand box by max_distance or larger and gather entries */
519          hypre_CopyBox(box ,grow_box);
520          hypre_BoxGrowByIndex(grow_box, max_distance);
521          hypre_BoxManGatherEntries(boxman, hypre_BoxIMin(grow_box),
522                                    hypre_BoxIMax(grow_box));
523 
524          /* now repeat for any periodic boxes - by shifting the grow_box*/
525          for (k=1; k < num_periods; k++) /* k=0 is original box */
526          {
527             hypre_CopyBox(grow_box, periodic_box);
528             pshift = pshifts[k];
529             hypre_BoxShiftPos(periodic_box, pshift);
530 
531             /* see if the shifted box intersects the domain */
532             hypre_IntersectBoxes(periodic_box, bounding_box, result_box);
533             /* if so, call gather entries */
534             if (hypre_BoxVolume(result_box) > 0)
535             {
536                hypre_BoxManGatherEntries(boxman, hypre_BoxIMin(periodic_box),
537                                          hypre_BoxIMax(periodic_box));
538             }
539          }
540       }/* end of for each local box */
541 
542       hypre_BoxDestroy(periodic_box);
543       hypre_BoxDestroy(grow_box);
544       hypre_BoxDestroy(result_box);
545    }
546 
547    /***************Assemble the box manager *****************/
548 
549    hypre_BoxManAssemble(boxman);
550 
551    hypre_StructGridBoxMan(grid) = boxman;
552 
553    hypre_EndTiming(time_index);
554 
555    return hypre_error_flag;
556 }
557 
558 /*--------------------------------------------------------------------------
559  * hypre_GatherAllBoxes
560  *--------------------------------------------------------------------------*/
561 
562 HYPRE_Int
hypre_GatherAllBoxes(MPI_Comm comm,hypre_BoxArray * boxes,HYPRE_Int ndim,hypre_BoxArray ** all_boxes_ptr,HYPRE_Int ** all_procs_ptr,HYPRE_Int * first_local_ptr)563 hypre_GatherAllBoxes(MPI_Comm         comm,
564                      hypre_BoxArray  *boxes,
565                      HYPRE_Int        ndim,
566                      hypre_BoxArray **all_boxes_ptr,
567                      HYPRE_Int      **all_procs_ptr,
568                      HYPRE_Int       *first_local_ptr)
569 {
570    hypre_BoxArray    *all_boxes;
571    HYPRE_Int         *all_procs;
572    HYPRE_Int          first_local;
573    HYPRE_Int          all_boxes_size;
574 
575    hypre_Box         *box;
576    hypre_Index        imin;
577    hypre_Index        imax;
578 
579    HYPRE_Int          num_all_procs, my_rank;
580 
581    HYPRE_Int         *sendbuf;
582    HYPRE_Int          sendcount;
583    HYPRE_Int         *recvbuf;
584    HYPRE_Int         *recvcounts;
585    HYPRE_Int         *displs;
586    HYPRE_Int          recvbuf_size;
587    HYPRE_Int          item_size;
588 
589    HYPRE_Int          i, p, b, d;
590 
591    /*-----------------------------------------------------
592     * Accumulate the box info
593     *-----------------------------------------------------*/
594 
595    hypre_MPI_Comm_size(comm, &num_all_procs);
596    hypre_MPI_Comm_rank(comm, &my_rank);
597 
598    /* compute recvcounts and displs */
599    item_size = 2*ndim + 1;
600    sendcount = item_size*hypre_BoxArraySize(boxes);
601    recvcounts =  hypre_TAlloc(HYPRE_Int,  num_all_procs, HYPRE_MEMORY_HOST);
602    displs = hypre_TAlloc(HYPRE_Int,  num_all_procs, HYPRE_MEMORY_HOST);
603    hypre_MPI_Allgather(&sendcount, 1, HYPRE_MPI_INT,
604                        recvcounts, 1, HYPRE_MPI_INT, comm);
605    displs[0] = 0;
606    recvbuf_size = recvcounts[0];
607    for (p = 1; p < num_all_procs; p++)
608    {
609       displs[p] = displs[p-1] + recvcounts[p-1];
610       recvbuf_size += recvcounts[p];
611    }
612 
613    /* allocate sendbuf and recvbuf */
614    sendbuf = hypre_TAlloc(HYPRE_Int,  sendcount, HYPRE_MEMORY_HOST);
615    recvbuf =  hypre_TAlloc(HYPRE_Int,  recvbuf_size, HYPRE_MEMORY_HOST);
616 
617    /* put local box extents and process number into sendbuf */
618    i = 0;
619    for (b = 0; b < hypre_BoxArraySize(boxes); b++)
620    {
621       sendbuf[i++] = my_rank;
622 
623       box = hypre_BoxArrayBox(boxes, b);
624       for (d = 0; d < ndim; d++)
625       {
626          sendbuf[i++] = hypre_BoxIMinD(box, d);
627          sendbuf[i++] = hypre_BoxIMaxD(box, d);
628       }
629    }
630 
631    /* get global grid info */
632    hypre_MPI_Allgatherv(sendbuf, sendcount, HYPRE_MPI_INT,
633                         recvbuf, recvcounts, displs, HYPRE_MPI_INT, comm);
634 
635    /* sort recvbuf by process rank? */
636 
637    /*-----------------------------------------------------
638     * Create all_boxes, etc.
639     *-----------------------------------------------------*/
640 
641    /* unpack recvbuf box info */
642    all_boxes_size = recvbuf_size / item_size;
643    all_boxes   = hypre_BoxArrayCreate(all_boxes_size, ndim);
644    all_procs   = hypre_TAlloc(HYPRE_Int,  all_boxes_size, HYPRE_MEMORY_HOST);
645    first_local = -1;
646    i = 0;
647    b = 0;
648    box = hypre_BoxCreate(ndim);
649    while (i < recvbuf_size)
650    {
651       all_procs[b] = recvbuf[i++];
652       for (d = 0; d < ndim; d++)
653       {
654          hypre_IndexD(imin, d) = recvbuf[i++];
655          hypre_IndexD(imax, d) = recvbuf[i++];
656       }
657       hypre_BoxSetExtents(box, imin, imax);
658       hypre_CopyBox(box, hypre_BoxArrayBox(all_boxes, b));
659 
660       if ((first_local < 0) && (all_procs[b] == my_rank))
661       {
662          first_local = b;
663       }
664 
665       b++;
666    }
667    hypre_BoxDestroy(box);
668 
669    /*-----------------------------------------------------
670     * Return
671     *-----------------------------------------------------*/
672 
673    hypre_TFree(sendbuf, HYPRE_MEMORY_HOST);
674     hypre_TFree(recvbuf, HYPRE_MEMORY_HOST);
675     hypre_TFree(recvcounts, HYPRE_MEMORY_HOST);
676    hypre_TFree(displs, HYPRE_MEMORY_HOST);
677 
678    *all_boxes_ptr   = all_boxes;
679    *all_procs_ptr   = all_procs;
680    *first_local_ptr = first_local;
681 
682    return hypre_error_flag;
683 }
684 
685 /*--------------------------------------------------------------------------
686  * hypre_ComputeBoxnums
687  *
688  * It is assumed that, for any process number in 'procs', all of that
689  * processes local boxes appear in the 'boxes' array.
690  *
691  * It is assumed that the boxes in 'boxes' are ordered by associated
692  * process number then by their local ordering on that process.
693  *
694  *--------------------------------------------------------------------------*/
695 
696 HYPRE_Int
hypre_ComputeBoxnums(hypre_BoxArray * boxes,HYPRE_Int * procs,HYPRE_Int ** boxnums_ptr)697 hypre_ComputeBoxnums(hypre_BoxArray *boxes,
698                      HYPRE_Int      *procs,
699                      HYPRE_Int     **boxnums_ptr)
700 {
701 
702    HYPRE_Int         *boxnums;
703    HYPRE_Int          num_boxes;
704    HYPRE_Int          p, b, boxnum;
705 
706    /*-----------------------------------------------------
707     *-----------------------------------------------------*/
708 
709    num_boxes = hypre_BoxArraySize(boxes);
710    boxnums = hypre_TAlloc(HYPRE_Int,  num_boxes, HYPRE_MEMORY_HOST);
711 
712    p = -1;
713    for(b = 0; b < num_boxes; b++)
714    {
715       /* start boxnum count at zero for each new process */
716       if (procs[b] != p)
717       {
718          boxnum = 0;
719          p = procs[b];
720       }
721       boxnums[b] = boxnum;
722       boxnum++;
723    }
724 
725    *boxnums_ptr = boxnums;
726 
727    return hypre_error_flag;
728 }
729 
730 /*--------------------------------------------------------------------------
731  * hypre_StructGridPrint
732  *--------------------------------------------------------------------------*/
733 
734 HYPRE_Int
hypre_StructGridPrint(FILE * file,hypre_StructGrid * grid)735 hypre_StructGridPrint( FILE             *file,
736                        hypre_StructGrid *grid )
737 {
738 
739    hypre_BoxArray  *boxes;
740    hypre_Box       *box;
741 
742    HYPRE_Int        i, d, ndim;
743 
744    ndim = hypre_StructGridNDim(grid);
745    hypre_fprintf(file, "%d\n", ndim);
746 
747    boxes = hypre_StructGridBoxes(grid);
748    hypre_fprintf(file, "%d\n", hypre_BoxArraySize(boxes));
749 
750    /* Print lines of the form: "%d:  (%d, %d, %d)  x  (%d, %d, %d)\n" */
751    hypre_ForBoxI(i, boxes)
752    {
753       box = hypre_BoxArrayBox(boxes, i);
754       hypre_fprintf(file, "%d:  (%d", i, hypre_BoxIMinD(box, 0));
755       for (d = 1; d < ndim; d++)
756       {
757          hypre_fprintf(file, ", %d", hypre_BoxIMinD(box, d));
758       }
759       hypre_fprintf(file, ")  x  (%d", hypre_BoxIMaxD(box, 0));
760       for (d = 1; d < ndim; d++)
761       {
762          hypre_fprintf(file, ", %d", hypre_BoxIMaxD(box, d));
763       }
764       hypre_fprintf(file, ")\n");
765    }
766    /* Print line of the form: "Periodic: %d %d %d\n" */
767    hypre_fprintf(file, "\nPeriodic:");
768    for (d = 0; d < ndim; d++)
769    {
770       hypre_fprintf(file, " %d", hypre_StructGridPeriodic(grid)[d]);
771    }
772    hypre_fprintf(file, "\n");
773 
774    return hypre_error_flag;
775 }
776 
777 /*--------------------------------------------------------------------------
778  * hypre_StructGridRead
779  *--------------------------------------------------------------------------*/
780 
781 HYPRE_Int
hypre_StructGridRead(MPI_Comm comm,FILE * file,hypre_StructGrid ** grid_ptr)782 hypre_StructGridRead( MPI_Comm           comm,
783                       FILE              *file,
784                       hypre_StructGrid **grid_ptr )
785 {
786 
787    hypre_StructGrid *grid;
788 
789    hypre_Index       ilower;
790    hypre_Index       iupper;
791    hypre_IndexRef    periodic;
792 
793    HYPRE_Int         ndim;
794    HYPRE_Int         num_boxes;
795 
796    HYPRE_Int         i, d, idummy;
797 
798    hypre_fscanf(file, "%d\n", &ndim);
799    hypre_StructGridCreate(comm, ndim, &grid);
800 
801    hypre_fscanf(file, "%d\n", &num_boxes);
802 
803    /* Read lines of the form: "%d:  (%d, %d, %d)  x  (%d, %d, %d)\n" */
804    for (i = 0; i < num_boxes; i++)
805    {
806       hypre_fscanf(file, "%d:  (%d", &idummy, &hypre_IndexD(ilower, 0));
807       for (d = 1; d < ndim; d++)
808       {
809          hypre_fscanf(file, ", %d", &hypre_IndexD(ilower, d));
810       }
811       hypre_fscanf(file, ")  x  (%d", &hypre_IndexD(iupper, 0));
812       for (d = 1; d < ndim; d++)
813       {
814          hypre_fscanf(file, ", %d", &hypre_IndexD(iupper, d));
815       }
816       hypre_fscanf(file, ")\n");
817 
818       hypre_StructGridSetExtents(grid, ilower, iupper);
819    }
820 
821    periodic = hypre_StructGridPeriodic(grid);
822 
823    /* Read line of the form: "Periodic: %d %d %d\n" */
824    hypre_fscanf(file, "Periodic:");
825    for (d = 0; d < ndim; d++)
826    {
827       hypre_fscanf(file, " %d", &hypre_IndexD(periodic, d));
828    }
829    hypre_fscanf(file, "\n");
830 
831    hypre_StructGridAssemble(grid);
832 
833    *grid_ptr = grid;
834 
835    return hypre_error_flag;
836 }
837 
838 /*------------------------------------------------------------------------------
839  * GEC0902  hypre_StructGridSetNumGhost
840  *
841  * the purpose is to set num ghost in the structure grid. It is identical
842  * to the function that is used in the structure vector entity.
843  *-----------------------------------------------------------------------------*/
844 
845 HYPRE_Int
hypre_StructGridSetNumGhost(hypre_StructGrid * grid,HYPRE_Int * num_ghost)846 hypre_StructGridSetNumGhost( hypre_StructGrid *grid, HYPRE_Int  *num_ghost )
847 {
848    HYPRE_Int  i, ndim = hypre_StructGridNDim(grid);
849 
850    for (i = 0; i < 2*ndim; i++)
851    {
852       hypre_StructGridNumGhost(grid)[i] = num_ghost[i];
853    }
854 
855    return hypre_error_flag;
856 }
857 
858 
859 #if 0 //defined(HYPRE_USING_CUDA) || defined(HYPRE_USING_HIP)
860 HYPRE_Int
861 hypre_StructGridGetMaxBoxSize(hypre_StructGrid *grid)
862 {
863    hypre_Box  *box;
864    hypre_BoxArray  *boxes;
865    HYPRE_Int box_size;
866    HYPRE_Int i;
867    HYPRE_Int        max_box_size = 0;
868    boxes = hypre_StructGridBoxes(grid);
869    hypre_ForBoxI(i, boxes)
870    {
871       box = hypre_BoxArrayBox(hypre_StructGridBoxes(grid), i);
872       box_size = hypre_BoxVolume(box);
873       if (box_size > max_box_size)
874       {
875          max_box_size = box_size;
876       }
877    }
878    return max_box_size;
879 }
880 
881 HYPRE_Int
882 hypre_StructGridSetDataLocation( HYPRE_StructGrid grid, HYPRE_MemoryLocation data_location )
883 {
884    hypre_StructGridDataLocation(grid) = data_location;
885 
886    return hypre_error_flag;
887 }
888 
889 #endif
890