source: CIVL/examples/mpi-omp/AMG2013/struct_mv/assumed_part.c

main
Last change on this file was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5704 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 69.9 KB
Line 
1/*BHEADER**********************************************************************
2 * Copyright (c) 2008, Lawrence Livermore National Security, LLC.
3 * Produced at the Lawrence Livermore National Laboratory.
4 * This file is part of HYPRE. See file COPYRIGHT for details.
5 *
6 * HYPRE is free software; you can redistribute it and/or modify it under the
7 * terms of the GNU Lesser General Public License (as published by the Free
8 * Software Foundation) version 2.1 dated February 1999.
9 *
10 * $Revision: 2.4 $
11 ***********************************************************************EHEADER*/
12
13
14/* This is code for the struct assumed partition
15 AHB 6/05 */
16
17#include "headers.h"
18
19
20#define REGION_STAT 0
21#define NO_REFINE 0
22#define REFINE_INFO 0
23
24
25/* functions used in this file to determine the partition - not elsewhere -
26have names that start with AP */
27
28#if 0
29int hypre_APFillResponseStructAssumedPart(void *, int, int, void *,MPI_Comm,
30 void **, int *);
31int hypre_APSubdivideRegion(hypre_Box*, int, int, hypre_BoxArray*, int*);
32int hypre_APFindMyBoxesInRegions( hypre_BoxArray*, hypre_BoxArray*, int**,
33 double**);
34int hypre_APGetAllBoxesInRegions( hypre_BoxArray*, hypre_BoxArray *, int**,
35 double**, MPI_Comm);
36int hypre_APPruneRegions( hypre_BoxArray*, int** , double**);
37int hypre_APShrinkRegions( hypre_BoxArray*, hypre_BoxArray*, MPI_Comm );
38int hypre_APRefineRegionsByVol( hypre_BoxArray*, double*, int, double,
39 int, int *, MPI_Comm);
40
41#endif
42
43/******************************************************************************
44 *
45 * Given a region, subdivide the region equally a specified number of times.
46 * For dimension d, each "level" is a subdivison of 2^d. The box_array
47 * is adjusted to have space for l(2^d)^level boxes
48 * We are bisecting each dimension (level) times.
49 *
50 * We may want to add min. size parameter for dimension of results
51 * regions (currently 2) - i.e., don't bisect a dimention if it will
52 * be smaller than 2 grid points, for example
53 *****************************************************************************/
54
55int hypre_APSubdivideRegion( hypre_Box *region, int dim, int level,
56 hypre_BoxArray *box_array, int *num_new_boxes)
57{
58
59 int i, j, k, width, sz;
60 int total, start, div[3];
61 int extra, points, count;
62 int *partition[3];
63 int *xpart,*ypart, *zpart;
64
65 int min_gridpts; /* this should probably be an input parameter */
66
67
68 hypre_Index isize, imin, imax;
69 hypre_Box *box;
70
71
72
73 /* if level = 0 then no dividing */
74 if (!level)
75 {
76 hypre_BoxArraySetSize(box_array, 1);
77 hypre_CopyBox(region, hypre_BoxArrayBox(box_array, 0));
78 *num_new_boxes = 1;
79 return hypre_error_flag;
80 }
81
82 /* get the size of the box in each dimension */
83 /* size = # of grid points, =1 for un-used dimensions.
84 note: cell-centered! */
85
86 hypre_BoxGetSize(region , isize);
87
88
89 /* div = num of regions in each dimension */
90
91 /* figure out the number of regions - make sure
92 the sizes will contain the min
93 number of gridpoints - or divide less in that dimension
94 -we are requiring at least min_gridpts in
95 a region dimension */
96
97 min_gridpts = 4;
98
99
100 for (i=0; i < 3; i++)
101 {
102 div[i] = 1;
103 sz = hypre_IndexD(isize, i);
104 for (j = 0; j< level; j++)
105 {
106 if ( sz >= 2*div[i]*min_gridpts) /* each division cuts in half */
107 {
108 div[i] = div[i]*2;
109 }
110 }
111 }
112
113 /* space for each partition - aliasing makes debugging with tv easier :)*/
114 xpart = hypre_TAlloc(int, div[0]+1);
115 ypart = hypre_TAlloc(int, div[1]+1);
116 zpart = hypre_TAlloc(int, div[2]+1);
117 partition[0] = xpart;
118 partition[1] = ypart;
119 partition[2] = zpart;
120
121 /* total number of regions to create*/
122 total = 1;
123 for (i=0; i < 3; i++)
124 {
125 total = total*(div[i]);
126 }
127
128 *num_new_boxes = total;
129
130 /*prepare box array*/
131 hypre_BoxArraySetSize(box_array, total);
132
133 /*divide each dimension */
134
135 for (j=0; j < 3; j++)
136 {
137 start = hypre_BoxIMinD(region, j);
138 partition[j][0] = start;
139 /* we want to count grid points (these are cell-centered)*/
140 points = hypre_IndexD(isize, j);
141 width = points/div[j];
142 extra = points - width*div[j];
143 for (i = 1; i < div[j]; i++)
144 {
145 partition[j][i] = partition[j][i-1] + width;
146 if (i <= extra) partition[j][i]++;
147 }
148 partition[j][div[j]] = hypre_BoxIMaxD(region, j) + 1;
149 }
150
151 /* now create the new regions */
152 count = 0;
153
154 for (i = 0; i < (div[0]); i++)
155 {
156 for (j = 0; j < (div[1]); j++)
157 {
158 for (k = 0; k < (div[2]); k++)
159 {
160 hypre_SetIndex(imin, partition[0][i], partition[1][j],
161 partition[2][k]);
162 hypre_SetIndex(imax, partition[0][i+1]-1, partition[1][j+1]-1,
163 partition[2][k+1]-1);
164 box = hypre_BoxArrayBox(box_array, count);
165 hypre_BoxSetExtents( box, imin, imax );
166 count++;
167
168 }
169 }
170 }
171
172
173 /* clean up */
174 hypre_TFree(xpart);
175 hypre_TFree(ypart);
176 hypre_TFree(zpart);
177
178 return hypre_error_flag;
179
180
181}
182
183
184/******************************************************************************
185 *
186 * Given a list of regions, find out how many of *my* boxes are contained
187 * in each region
188 *
189 *****************************************************************************/
190
191int hypre_APFindMyBoxesInRegions( hypre_BoxArray *region_array,
192 hypre_BoxArray *my_box_array,
193 int **p_count_array, double **p_vol_array)
194{
195
196 int i,j, d, grow;
197 int myid;
198 int num_boxes, num_regions;
199 int *count_array;
200 double *vol_array;
201 int grow_array[6];
202
203 hypre_Box *my_box, *result_box, *grow_box;
204 hypre_Box *region;
205
206
207 /* this is just for debuugging - need myid for print statement */
208 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
209
210 num_boxes = hypre_BoxArraySize(my_box_array);
211 num_regions = hypre_BoxArraySize(region_array);
212
213 count_array = *p_count_array;
214 vol_array = *p_vol_array;
215
216
217 /* may need to add some sort of sorting to make this
218 more efficient - though we shouldn't have many regions*/
219
220 /* note: a box can be in more than one region */
221
222 result_box = hypre_BoxCreate();
223 grow_box = hypre_BoxCreate();
224
225 for (i=0; i< num_regions; i++)
226 {
227 count_array[i] = 0;
228 vol_array[i] = 0.0;
229
230 region = hypre_BoxArrayBox(region_array, i);
231
232 for (j = 0; j< num_boxes; j++)
233 {
234 my_box = hypre_BoxArrayBox(my_box_array, j);
235 /* check if its a zero volume box - if so it still need to be counted - so
236 expand till vol. is non-zero then intersect */
237 if (hypre_BoxVolume(my_box) == 0)
238 {
239 hypre_CopyBox(my_box, grow_box);
240 for (d = 0; d < 3; d++)
241 {
242 if(!hypre_BoxSizeD(my_box, d))
243 {
244 grow = (hypre_BoxIMinD(my_box, d) - hypre_BoxIMaxD(my_box, d) + 1)/2;
245 grow_array[2*d] = grow;
246 grow_array[2*d+1] = grow;
247 }
248 else
249 {
250 grow_array[2*d] = 0;
251 grow_array[2*d+1] = 0;
252 }
253 }
254 /* expand the grow box (leave our box untouched)*/
255 hypre_BoxExpand(grow_box, grow_array);
256 /* do they intersect?*/
257 hypre_IntersectBoxes( grow_box, region, result_box);
258 }
259 else
260 {
261 /* do they intersect?*/
262 hypre_IntersectBoxes( my_box, region, result_box);
263 }
264 if ( hypre_BoxVolume(result_box) > 0 )
265 {
266 count_array[i]++;
267 vol_array[i] += (double) hypre_BoxVolume(result_box);
268 }
269 }
270 }
271
272
273 /* clean up */
274 hypre_BoxDestroy(result_box);
275 hypre_BoxDestroy(grow_box);
276
277 /* output */
278 *p_count_array = count_array;
279 *p_vol_array = vol_array;
280
281
282 return hypre_error_flag;
283
284}
285
286/******************************************************************************
287 *
288 * Given a list of regions, find out how many global boxes are contained
289 * in each region.
290 *
291 * assumes that p_count_array and p_vol_array have already been allocated
292 *
293 *****************************************************************************/
294
295int hypre_APGetAllBoxesInRegions( hypre_BoxArray *region_array,
296 hypre_BoxArray *my_box_array,
297 int **p_count_array, double **p_vol_array,
298 MPI_Comm comm )
299{
300
301 int i;
302 int *count_array;
303 int num_regions;
304 int *send_buf_count;
305 double *send_buf_vol;
306 double *vol_array;
307 double *dbl_vol_and_count;
308
309
310 count_array = *p_count_array;
311 vol_array = *p_vol_array;
312
313
314 /*first get a count and volume of my boxes in each region */
315 num_regions = hypre_BoxArraySize(region_array);
316
317 send_buf_count = hypre_CTAlloc(int, num_regions);
318 send_buf_vol = hypre_CTAlloc(double, num_regions*2); /*allocate double*/
319
320 dbl_vol_and_count = hypre_CTAlloc(double, num_regions*2); /*allocate double*/
321
322 hypre_APFindMyBoxesInRegions( region_array, my_box_array, &send_buf_count,
323 &send_buf_vol);
324
325
326 /* copy ints to doubles so we can do one all_reduce */
327 for (i=0; i< num_regions; i++)
328 {
329 send_buf_vol[num_regions+i] = (double) send_buf_count[i];
330 }
331
332 MPI_Allreduce(send_buf_vol, dbl_vol_and_count, num_regions*2, MPI_DOUBLE,
333 MPI_SUM, comm);
334
335 /*unpack*/
336 for (i=0; i< num_regions; i++)
337 {
338 vol_array[i] = dbl_vol_and_count[i];
339 count_array[i] = (int) dbl_vol_and_count[num_regions+i];
340 }
341
342
343 /* clean up*/
344 hypre_TFree(send_buf_count);
345 hypre_TFree(send_buf_vol);
346 hypre_TFree(dbl_vol_and_count);
347
348
349 /* output */
350 *p_count_array = count_array;
351 *p_vol_array = vol_array;
352
353 return hypre_error_flag;
354
355}
356
357
358/******************************************************************************
359 *
360 * Given a list of regions, shrink regions according to min and max extents
361 *
362 *****************************************************************************/
363
364int hypre_APShrinkRegions( hypre_BoxArray *region_array,
365 hypre_BoxArray *my_box_array, MPI_Comm comm )
366{
367
368 /* These regions should all be non-empty at the global level*/
369
370
371 int i,j, d;
372 int myid;
373 int num_boxes, num_regions;
374 int *indices, *recvbuf;
375 int count = 0;
376 int grow, grow_array[6];
377
378
379 hypre_Box *my_box, *result_box, *grow_box;
380 hypre_Box *region;
381 hypre_Index imin, imax;
382
383
384 /* printf("SHRINKING!\n"); */
385
386
387 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
388
389 num_boxes = hypre_BoxArraySize(my_box_array);
390 num_regions = hypre_BoxArraySize(region_array);
391
392 indices = hypre_CTAlloc(int, num_regions*6);
393 recvbuf = hypre_CTAlloc(int, num_regions*6);
394
395 result_box = hypre_BoxCreate();
396
397 /* allocate for a grow box */
398 grow_box = hypre_BoxCreate();
399
400 /* Look locally at my boxes */
401 /* for each region*/
402 for (i=0; i< num_regions; i++)
403 {
404 count = 0; /*number of my boxes in this region */
405
406 /* get the region box*/
407 region = hypre_BoxArrayBox(region_array, i);
408
409
410 /*go through each of my local boxes */
411 for (j = 0; j< num_boxes; j++)
412 {
413 my_box = hypre_BoxArrayBox(my_box_array, j);
414
415 /* check if its a zero volume box - if so it still need to be checked - so
416 expand till vol. is non-zero then intersect */
417 if (hypre_BoxVolume(my_box) == 0)
418 {
419 hypre_CopyBox(my_box, grow_box);
420 for (d = 0; d < 3; d++)
421 {
422 if(!hypre_BoxSizeD(my_box, d))
423 {
424 grow = (hypre_BoxIMinD(my_box, d) -
425 hypre_BoxIMaxD(my_box, d) + 1)/2;
426 grow_array[2*d] = grow;
427 grow_array[2*d+1] = grow;
428 }
429 else
430 {
431 grow_array[2*d] = 0;
432 grow_array[2*d+1] = 0;
433 }
434 }
435 /* expand the grow box (leave our box untouched)*/
436 hypre_BoxExpand(grow_box, grow_array);
437 /* do they intersect?*/
438 hypre_IntersectBoxes( grow_box, region, result_box);
439 }
440 else
441 {
442 /* do they intersect?*/
443 hypre_IntersectBoxes( my_box, region, result_box);
444 }
445
446 if ( hypre_BoxVolume(result_box) > 0 ) /* they intersect*/
447 {
448
449 if (!count) /* set min and max for first box */
450 {
451 for (d = 0; d < 3; d++)
452 {
453 indices[i*6+d] = hypre_BoxIMinD(result_box, d);
454 indices[i*6+3+d] = hypre_BoxIMaxD(result_box, d);
455 }
456
457 }
458
459 count++;
460
461 /* boxes intersect - so get max and min extents
462 of the result box (this keeps the bounds inside
463 the region */
464 for (d = 0; d < 3; d++)
465 {
466 indices[i*6+d] = hypre_min(indices[i*6+d],
467 hypre_BoxIMinD(result_box, d));
468 indices[i*6+3+d] = hypre_max(indices[i*6+3+d],
469 hypre_BoxIMaxD(result_box, d));
470 }
471 }
472 }
473 /* now if we had no boxes in that region, set the min to the max
474 extents of the region and the max to the min! */
475
476 if (!count)
477 {
478 for (d = 0; d < 3; d++)
479 {
480 indices[i*6+d] = hypre_BoxIMaxD(region, d);
481 indices[i*6+3+d] = hypre_BoxIMinD(region, d);
482 }
483 }
484
485 /*negate max indices for the allreduce */
486 /* note: min(x)= -max(-x) */
487
488 for (d = 0; d < 3; d++)
489 {
490 indices[i*6+3+d] = -indices[i*6+3+d];
491 }
492
493
494 }
495
496 /* Now do an allreduce to get the global information */
497
498 /* now do an all reduce on the size and volume */
499 MPI_Allreduce(indices, recvbuf, num_regions*6, MPI_INT, MPI_MIN, comm);
500
501 /*now unpack the "shrunk" regions */
502 /* for each region*/
503 for (i=0; i< num_regions; i++)
504 {
505 /* get the region box*/
506 region = hypre_BoxArrayBox(region_array, i);
507
508 /*resize the box*/
509 hypre_SetIndex(imin, recvbuf[i*6], recvbuf[i*6+1], recvbuf[i*6+2]);
510 hypre_SetIndex(imax, -recvbuf[i*6+3], -recvbuf[i*6+4], -recvbuf[i*6+5]);
511
512 hypre_BoxSetExtents(region, imin, imax );
513
514 /*add: check to see whether any shrinking is actually occuring*/
515
516 }
517
518
519 /* clean up */
520 hypre_TFree(recvbuf);
521 hypre_TFree(indices);
522 hypre_BoxDestroy(result_box);
523 hypre_BoxDestroy(grow_box);
524
525
526 return hypre_error_flag;
527
528
529
530}
531
532
533
534/******************************************************************************
535 *
536 * Given a list of regions, eliminate empty regions
537 *
538 *****************************************************************************/
539
540
541
542int hypre_APPruneRegions( hypre_BoxArray *region_array, int **p_count_array,
543 double **p_vol_array )
544{
545
546
547 /*-------------------------------------------
548 * parameters:
549 *
550 * region_array = assumed partition regions
551 * count_array = number of global boxes in each region
552 *-------------------------------------------*/
553
554
555 int i, j;
556 int num_regions;
557 int count;
558 int *delete_indices;
559
560 int *count_array;
561 double *vol_array;
562
563
564 count_array = *p_count_array;
565 vol_array = *p_vol_array;
566
567
568 num_regions = hypre_BoxArraySize(region_array);
569 delete_indices = hypre_CTAlloc(int, num_regions);
570 count = 0;
571
572
573 /* delete regions with zero elements */
574 for (i=0; i< num_regions; i++)
575 {
576 if (count_array[i] == 0)
577 {
578 delete_indices[count++] = i;
579 }
580
581 }
582
583 hypre_DeleteMultipleBoxes( region_array, delete_indices, count );
584
585 /* adjust count and volume arrays */
586 if (count > 0)
587 {
588 j=0;
589 for (i = delete_indices[0]; (i + j) < num_regions; i++)
590 {
591 if (j < count)
592 {
593 while ((i+j) == delete_indices[j])
594 {
595 j++; /*increase the shift*/
596 if (j == count) break;
597 }
598 }
599 vol_array[i] = vol_array[i+j];
600 count_array[i] = count_array[i+j];
601 }
602 }
603
604 /* clean up */
605 hypre_TFree(delete_indices);
606
607 /* return variables */
608 *p_count_array = count_array;
609 *p_vol_array = vol_array;
610
611 return hypre_error_flag;
612
613}
614
615
616/******************************************************************************
617 *
618 * Given a list of regions, and corresponding volumes contained in regions
619 * subdivide some of the regions that are not full enough
620 *
621 *****************************************************************************/
622
623
624
625int hypre_APRefineRegionsByVol( hypre_BoxArray *region_array, double *vol_array,
626 int max_regions, double gamma, int dim, int *return_code,
627 MPI_Comm comm)
628{
629
630
631 int i, count, loop;
632 int num_regions, init_num_regions;
633 int *delete_indices;
634
635 double *fraction_full;
636 int *order;
637 int myid, num_procs, est_size;
638 int new;
639 /* int regions_intact; */
640
641
642 hypre_BoxArray *tmp_array;
643 hypre_Box *box;
644
645 MPI_Comm_rank(comm, &myid);
646 MPI_Comm_size(comm, &num_procs);
647
648 num_regions = hypre_BoxArraySize(region_array);
649
650 if (!num_regions)
651 {
652 *return_code = 1; /* no regions - so no subdividing*/
653 return hypre_error_flag;
654
655 }
656
657 fraction_full = hypre_CTAlloc(double, num_regions);
658 order = hypre_CTAlloc(int, num_regions);
659 delete_indices = hypre_CTAlloc(int, num_regions);
660
661 for (i= 0; i< num_regions; i++)
662 {
663 box = hypre_BoxArrayBox(region_array, i);
664 fraction_full[i] = (vol_array[i])/((double) hypre_doubleBoxVolume(box));
665 order[i] = i; /*this is what order to access the boxes */
666 }
667
668 /* want to refine the regions starting with those that are the least full*/
669 /* sort the fraction AND the index */
670 hypre_qsort2(order, fraction_full, 0, num_regions-1);
671
672
673 /*now we can subdivide any that are not full enough*/
674 /* when this is called, we know that size < max_regions */
675 /* it is ok to subdivde such that we have slightly more
676 regions that max_region, but we do not want more regions
677 than processors */
678
679 tmp_array = hypre_BoxArrayCreate(0);
680 count = 0; /*how many regions subdivided */
681 loop = 0; /* counts the loop number */
682 init_num_regions = num_regions;
683 *return_code = 1; /* indicates all regions are at least gamma full -
684 and no subdividing occured*/
685
686 while (fraction_full[loop] < gamma)
687 {
688
689 /*some subdividing occurred*/
690 *return_code = 2;
691
692 /*we can't let the number of regions exceed the number
693 of processors - only an issue for small proc numbers */
694 est_size = num_regions + pow(2, dim) - 1;
695 if (est_size > num_procs)
696 {
697 if (loop==0)
698 {
699 *return_code = 4; /* some are less than gamma full, but we cannot
700 further subdivide due to max *processors*
701 limit (no subdividing occured)*/
702 }
703
704 else
705 {
706 *return_code = 3;/* some subdividing occured, but there are some
707 regions less than gamma full (max reached)
708 that were not subdivided */
709 }
710
711 break;
712 }
713
714 box = hypre_BoxArrayBox(region_array, order[loop]);
715 hypre_APSubdivideRegion(box, dim, 1, tmp_array, &new);
716
717 if (new > 1) /* if new =1 then no subdividing occured */
718 {
719 num_regions = num_regions + new - 1; /* the orginal will be deleted*/
720
721 delete_indices[count] = order[loop];
722 count++; /* number of regions subdivided */
723
724 /*append tmp_array to region array*/
725 hypre_AppendBoxArray( tmp_array, region_array);
726
727 }
728
729
730
731 /* if we are on the last region */
732 if ((loop+1) == init_num_regions)
733 {
734 break;
735 }
736
737 /* clear tmp_array for next loop */
738 hypre_BoxArraySetSize(tmp_array, 0);
739
740
741 /* if we now have too many regions - don't want to subdivide anymore*/
742 if (num_regions >= max_regions)
743 {
744 /* see if next regions satifies gamma */
745 if (fraction_full[order[loop+1]] > gamma)
746 {
747 *return_code = 5;/* all regions less than gamma full have been
748 subdivided (and we have reached max)*/
749 }
750 else
751 {
752 *return_code = 3; /* there are some regions less than gamma
753 full (but max is reached) */
754 }
755 break;
756 }
757
758 loop++; /* increment to repeat loop */
759 }
760
761
762 if (count ==0 )
763 {
764 *return_code = 1;
765 /* no refining occured so don't do any more*/
766 }
767 else
768 {
769
770 /* so we subdivided count regions */
771
772 /*delete the old regions*/
773 qsort0(delete_indices, 0, count-1); /* put delete indices in asc. order */
774 hypre_DeleteMultipleBoxes( region_array, delete_indices, count );
775
776 }
777
778 /* TO DO: number of regions intact (beginning of region array is intact)-
779 may return this eventually*/
780 /* regions_intact = init_num_regions - count;*/
781
782
783 /* clean up */
784 hypre_TFree(fraction_full);
785 hypre_TFree(order);
786 hypre_TFree(delete_indices);
787 hypre_BoxArrayDestroy(tmp_array);
788
789
790
791 return hypre_error_flag;
792
793
794}
795
796
797/******************************************************************************
798 *
799 * Construct an assumed partition
800 *
801 * 8/06 - changed the assumption that
802 * that the local boxes have boxnums 0 to num(local_boxes)-1 (now need to pass in
803 * boxnums)
804 *****************************************************************************/
805
806
807int hypre_StructAssumedPartitionCreate(int dim, hypre_Box *bounding_box,
808 double global_boxes_size,
809 int global_num_boxes,
810 hypre_BoxArray *local_boxes, int *local_boxnums,
811 int max_regions, int max_refinements,
812 double gamma,
813 MPI_Comm comm,
814 hypre_StructAssumedPart **p_assumed_partition)
815{
816
817 int i, j, d;
818 int size;
819 int myid, num_procs;
820 int count_array_size;
821 int *count_array=NULL;
822 double *vol_array=NULL, one_volume;
823 int return_code;
824 int num_refine;
825 int total_boxes, proc_count, max_position, tmp_num;
826 int *proc_array=NULL;
827 int i1, i2, i11, i22, pos1, pos2, pos0;
828 int tmp, ti1, ti2, t_tmp, t_total;
829 double f1, f2, r,x_box, y_box, z_box, dbl_vol;
830 int initial_level;
831 int grow, grow_array[6];
832
833
834 hypre_Index div_index;
835 hypre_BoxArray *region_array;
836 hypre_Box *box, *grow_box;
837
838 hypre_StructAssumedPart *assumed_part;
839
840
841 int proc_alloc, count, box_count;
842 int max_response_size;
843 int *response_buf = NULL, *response_buf_starts=NULL;
844 int *tmp_box_nums = NULL, *tmp_proc_ids = NULL;
845 int *proc_array_starts=NULL;
846
847
848 hypre_BoxArray *my_partition;
849 hypre_DataExchangeResponse response_obj;
850
851 int *contact_boxinfo;
852 int index;
853
854
855
856
857 MPI_Comm_size(comm, &num_procs);
858 MPI_Comm_rank(comm, &myid);
859
860
861 /*FIRST DO ALL THE GLOBAL PARTITION INFO */
862
863
864 /*initially divide the bounding box*/
865
866 /*first modify any input parameters if necessary */
867
868 /*don't want the number of regions exceeding the number of processors*/
869 /* note: this doesn't change the value in the caller's code */
870 max_regions = hypre_min(num_procs, max_regions);
871
872
873 /* start with a region array of size 0*/
874 region_array = hypre_BoxArrayCreate(0);
875
876 /*if the bounding box is sufficiently covered by boxes then we will
877 just have one region - the bounding box - otherwise we will subdivide
878 probably just start with one level of division */
879
880 /* one_volume = (double) hypre_BoxSizeX(bounding_box) *
881 (double) hypre_BoxSizeY(bounding_box) * (double) hypre_BoxSizeZ(bounding_box); */
882
883 one_volume = (double) hypre_doubleBoxVolume(bounding_box);
884
885
886 if( ((global_boxes_size/one_volume) > gamma) ||
887 ( global_num_boxes > one_volume) || global_num_boxes == 0 )
888 {
889 /*don't bother with any refinements - we are full enough -
890 or we have a small bounding box
891 and we are not full because of neg. boxes */
892 initial_level = 0;
893 max_refinements = 0;
894
895 }
896 else
897 {
898 initial_level = 1; /*we could let this be an input parameter
899 - but I think 1 division is probably
900 sufficient */
901
902 /* start with the specified intial_levels for the original domain -
903 unless we have a smaller number of procs */
904 for (i= 0; i < initial_level; i++)
905 {
906 if ( pow(2,initial_level*dim) > num_procs) initial_level --;
907
908 if (!initial_level) max_refinements = 0; /* we will not be able to do
909 any refinements due to the
910 number of processors*/
911 }
912 }
913
914
915#if NO_REFINE
916 max_refinements = 0;
917 initial_level = 0;
918#endif
919
920
921
922#if REFINE_INFO
923 if (myid ==0)
924 {
925 printf("gamma = %g\n", gamma);
926 printf("max_regions = %d\n", max_regions);
927 printf("max_refinements = %d\n", max_refinements);
928 printf("initial level = %d\n", initial_level);
929 }
930
931#endif
932
933
934 /*divide the bounding box */
935 hypre_APSubdivideRegion(bounding_box, dim, initial_level, region_array,
936 &size);
937 /* if no subdividing occured (becuz too small) then don't try to refine */
938 if (initial_level > 0 && size ==1) max_refinements = 0;
939
940 /*need space for count and volume */
941 size = hypre_BoxArraySize(region_array);
942 count_array_size = size; /* memory allocation size */
943 count_array = hypre_CTAlloc(int, size);
944 vol_array = hypre_CTAlloc(double, size);
945
946 /* how many boxes are in each region (global count) and what the volume is*/
947 hypre_APGetAllBoxesInRegions( region_array, local_boxes, &count_array,
948 &vol_array, comm );
949
950 /* don't do any initial prune and shrink if we have only
951 one region and we can't do any refinements */
952
953 if ( !(size ==1 && max_refinements == 0))
954 {
955
956 /* get rid of regions with no boxes (and adjust count and vol arrays) */
957 hypre_APPruneRegions( region_array, &count_array, &vol_array);
958
959 /*shrink the extents*/
960 hypre_APShrinkRegions( region_array, local_boxes, comm);
961
962 }
963
964 /* keep track of refinements */
965 num_refine = 0;
966
967
968 /* now we can keep refining by dividing the regions that are not
969 full enough and eliminating empty regions */
970 while (( hypre_BoxArraySize(region_array)< max_regions) &&
971 (num_refine < max_refinements))
972 {
973 num_refine++;
974
975 /* now calculate how full the regions are and subdivide the
976 least full as needed */
977
978
979 size = hypre_BoxArraySize(region_array);
980
981 /* divide regions that are not full enough */
982 hypre_APRefineRegionsByVol( region_array, vol_array,
983 max_regions,
984 gamma, dim, &return_code, comm );
985
986
987 if (return_code == 1 || return_code == 4) /* 1 = all regions are at least
988 gamma full - no subdividing
989 occured */
990 { /* 4 = no subdividing occured
991 due to num_procs limit on
992 regions*/
993 break;
994 }
995 /* this is extraneous I think */
996 if (size == hypre_BoxArraySize(region_array))
997 {
998 /* no dividing occured -exit the loop */
999 break;
1000 }
1001
1002
1003 size = hypre_BoxArraySize(region_array);
1004 if (size > count_array_size)
1005 {
1006 count_array = hypre_TReAlloc(count_array, int, size);
1007 vol_array = hypre_TReAlloc(vol_array, double, size);
1008 count_array_size =size;
1009 }
1010
1011 /* FUTURE MOD - just count and prune and shrink in the modified regions
1012 from refineRegionsByVol - these are the last regions in the array */
1013
1014 /* num boxes are in each region (global count) and what the volume is*/
1015 hypre_APGetAllBoxesInRegions( region_array, local_boxes, &count_array,
1016 &vol_array, comm );
1017
1018 /* get rid of regions with no boxes (and adjust count and vol arrays) */
1019 hypre_APPruneRegions( region_array, &count_array, &vol_array);
1020
1021 /*shrink the extents*/
1022 hypre_APShrinkRegions( region_array, local_boxes, comm);
1023
1024
1025 /* actually 3 and 5 may be ok after pruning..but if no pruning then
1026 exit the loop */
1027
1028 if ( (return_code == 3 || return_code == 5)
1029 && size ==hypre_BoxArraySize(region_array) )
1030 /* 5 = all regions < gamma full
1031 were subdivided and max
1032 reached */
1033 /* 3 = some regions were divided
1034 (not all that needed) and max
1035 reached */
1036 {
1037 break;
1038 }
1039
1040 }
1041 /* end of refinements */
1042
1043
1044 /*error checking */
1045 hypre_ForBoxI(i, region_array)
1046 {
1047 if (hypre_BoxVolume(hypre_BoxArrayBox(region_array, i))==0)
1048 {
1049 if (myid ==0) printf("ERROR: a region has zero volume! "
1050 "(this should never happen)");
1051 }
1052 }
1053
1054
1055
1056#if REGION_STAT
1057 if (myid == 0) printf("myid = %d: %d REGIONS (after refining %d times accord. "
1058 "to vol\n",
1059 myid, hypre_BoxArraySize(region_array), num_refine);
1060#endif
1061
1062
1063
1064#if REGION_STAT
1065 if (myid ==0)
1066 {
1067 printf("myid = %d, REGIONS (after refining %d times accord. to vol\n",
1068 myid, num_refine);
1069
1070 hypre_ForBoxI(i, region_array)
1071 {
1072 box = hypre_BoxArrayBox(region_array, i);
1073 printf("myid = %d, %d: (%d, %d, %d) x (%d, %d, %d)\n",
1074 myid, i,
1075 hypre_BoxIMinX(box),
1076 hypre_BoxIMinY(box),
1077 hypre_BoxIMinZ(box),
1078 hypre_BoxIMaxX(box),
1079 hypre_BoxIMaxY(box),
1080 hypre_BoxIMaxZ(box));
1081 }
1082 }
1083#endif
1084
1085
1086 hypre_TFree(vol_array);
1087
1088
1089/* ------------------------------------------------------------------------*/
1090 /*now we have the regions - construct the assumed partition */
1091
1092 size = hypre_BoxArraySize(region_array);
1093 assumed_part = hypre_TAlloc(hypre_StructAssumedPart, 1);
1094 hypre_StructAssumedPartRegions(assumed_part) = region_array;
1095 /*the above is aliased - so don't destroy region_array in this function */
1096 hypre_StructAssumedPartNumRegions(assumed_part) = size;
1097 hypre_StructAssumedPartDivisions(assumed_part) = hypre_CTAlloc(hypre_Index,
1098 size);
1099
1100 /* first determine which processors (how many) to assign to each region*/
1101 proc_array = hypre_CTAlloc(int, size);
1102 total_boxes = 0; /* this is different than the total number of
1103 boxes as some boxes can be in more than
1104 one region */
1105 proc_count = 0;
1106 d = -1;
1107 max_position = -1;
1108 /* calculate total number of boxes in the regions */
1109 for (i=0; i < size; i++)
1110 {
1111 total_boxes += count_array[i];
1112 }
1113 /* calculate the fraction of actual boxes in each region, mult. by total number
1114 of procs, put result in proc_array to
1115 assign each region a number of processors proportional to the fraction
1116 of boxes */
1117 for (i=0; i < size; i++)
1118 {
1119
1120 if (!total_boxes) /* in case there are no boxes in a grid */
1121 {
1122 proc_array[i] = 0;
1123 }
1124 else
1125 {
1126 proc_array[i] = (int) hypre_round(((double)count_array[i]/
1127 (double)total_boxes)* (double) num_procs);
1128 }
1129
1130 box = hypre_BoxArrayBox(region_array, i);
1131 /* vol = hypre_BoxVolume(box); */
1132 dbl_vol = hypre_doubleBoxVolume(box);
1133
1134 /* can't have any zeros! */
1135 if (!proc_array[i]) proc_array[i] = 1;
1136
1137
1138 if (dbl_vol < (double) proc_array[i])
1139 {
1140 proc_array[i] = (int) dbl_vol; /*don't let the the number of procs be
1141 greater than the volume - safe to case back to int if
1142 this is true - then vol is not overflowing */
1143 }
1144
1145 proc_count += proc_array[i];
1146 if (d < proc_array[i])
1147 {
1148 d = proc_array[i];
1149 max_position = i;
1150 }
1151
1152 /* if (myid == 0) printf("proc array[%d] = %d\n", i, proc_array[i]);*/
1153 }
1154
1155
1156 hypre_TFree(count_array);
1157
1158
1159
1160 /* adjust such that num_procs = proc_count (they should be close) */
1161 /* a processor is only assigned to ONE region*/
1162
1163 /* if we need a few more processors assigned
1164 in proc_array for proc_count to = num_procs
1165 (it is ok if we have fewer procs in proc_array
1166 due to volume constraints */
1167 while (num_procs > proc_count)
1168 {
1169 proc_array[max_position]++;
1170
1171 if ( (double) proc_array[max_position] >
1172 hypre_doubleBoxVolume(hypre_BoxArrayBox(region_array, max_position)))
1173 {
1174 proc_array[max_position]--;
1175 break; /* some processors won't get assigned partitions */
1176 }
1177 proc_count++;
1178 }
1179
1180 /* if we we need fewer processors in proc_array*/
1181 i = 0;
1182 while (num_procs < proc_count)
1183 {
1184 if (proc_array[max_position] != 1)
1185 {
1186 proc_array[max_position]--;
1187 }
1188 else
1189 {
1190 while (proc_array[i] <=1 && i < size) /* size is the number of regions */
1191 {
1192 i++;
1193 }
1194 proc_array[i]--;
1195 }
1196 proc_count--;
1197 }
1198 /* the above logic would be flawed IF we allowed more regions
1199 than processors, but this is not allowed! */
1200
1201
1202 /*now we have the number of processors in each region so create the
1203 processor partition */
1204 /* size = # of regions */
1205 hypre_StructAssumedPartProcPartitions(assumed_part) =
1206 hypre_CTAlloc(int, size+ 1);
1207 hypre_StructAssumedPartProcPartition(assumed_part, 0) = 0;
1208 for (i=0; i< size; i++)
1209 {
1210 hypre_StructAssumedPartProcPartition(assumed_part, i+1) =
1211 hypre_StructAssumedPartProcPartition(assumed_part, i) + proc_array[i];
1212 }
1213
1214
1215 /* now determine the NUMBER of divisions in the x, y amd z dir according
1216 to the number or processors assigned to the region */
1217
1218 /* FOR EACH REGION */
1219 for (i = 0; i< size; i++)
1220 {
1221 proc_count = proc_array[i];
1222 box = hypre_BoxArrayBox(region_array, i);
1223 x_box = (double) hypre_BoxSizeX(box);
1224 y_box = (double) hypre_BoxSizeY(box);
1225 z_box = (double) hypre_BoxSizeZ(box);
1226
1227
1228 /* this could be re-written so that the two
1229 dimensions use the same code*/
1230 if (dim == 2)
1231 {
1232
1233 /*dimension 2 */
1234 if ( (x_box/y_box) > 1.0 )
1235 {
1236 f1 = x_box/y_box;
1237 pos0 = 1; /* find y first */
1238 pos1 = 0;
1239
1240 }
1241 else
1242 {
1243 f1 = y_box/x_box;
1244 pos0 = 0; /* find x first */
1245 pos1 = 1;
1246
1247 }
1248 i1 = (int) ceil(f1);
1249 i11 = (int) floor(f1);
1250
1251 /*case 1*/
1252 r = (double) proc_count/ (double) i1;
1253 ti1 = i1;
1254 t_tmp = (int) ceil(sqrt(r));
1255 t_total = t_tmp*t_tmp*i1;
1256
1257 /* is this better?*/
1258 r = (double) proc_count/ (double) i11;
1259 tmp = (int) ceil(sqrt(r));
1260 tmp_num = tmp*tmp*i11;
1261 if (tmp_num < t_total && tmp_num >= proc_count)
1262 {
1263 ti1 = i11;
1264 t_tmp = tmp;
1265 t_total = tmp_num;
1266 }
1267
1268 if ( t_total < proc_count ) printf("ERROR: (this shouldn't happen) "
1269 "the struct assumed partition doesn't"
1270 "have enough partitions!!!\n");
1271 hypre_IndexD(div_index, pos0) = t_tmp;
1272 hypre_IndexD(div_index, pos1) = t_tmp*ti1;
1273 hypre_IndexZ(div_index) = 1;
1274
1275 }
1276 else
1277 {
1278
1279 tmp = hypre_min(x_box, y_box);
1280 tmp = hypre_min(tmp, z_box);
1281
1282 if (tmp == x_box) /* x is smallest*/
1283 {
1284 f1 = (y_box/x_box);
1285 f2 = (z_box/x_box);
1286 pos0 = 0;
1287 pos1 = 1;
1288 pos2 = 2;
1289
1290 }
1291 else if (tmp == y_box) /*y is smallest */
1292 {
1293 f1 = (x_box/y_box);
1294 f2 = (z_box/y_box);
1295 pos0 = 1;
1296 pos1 = 0;
1297 pos2 = 2;
1298 }
1299 else /*z is smallest */
1300 {
1301 f1 = (x_box/z_box);
1302 f2 = (y_box/z_box);
1303 pos0 = 2;
1304 pos1 = 0;
1305 pos2 = 1;
1306 }
1307
1308 i1 = (int) ceil(f1);
1309 i2 = (int) ceil(f2);
1310 i11 = (int) floor(f1);
1311 i22 = (int) floor(f2);
1312
1313 /* case 0 - this will give a number of divisions > proc count */
1314 r = (double) proc_count / (double) (i2*i1);
1315 tmp = (int) ceil(pow(r,(1.0/3.0)));
1316 tmp_num = tmp*tmp*tmp*i1*i2;
1317
1318 ti1 = i1;
1319 ti2 = i2;
1320 t_tmp = tmp;
1321 t_total = tmp_num;
1322
1323 /* can we do better ? */
1324 /*case 1: i11 and i2 */
1325 r = (double) proc_count / (double) (i2*i11);
1326 tmp = (int) ceil(pow(r,(1.0/3.0)));
1327 tmp_num = tmp*tmp*tmp*i11*i2;
1328 if (tmp_num < t_total && tmp_num >= proc_count)
1329 {
1330 ti1 = i11;
1331 ti2 = i2;
1332 t_tmp = tmp;
1333 t_total = tmp_num;
1334 }
1335 /*case 2: i11 and i22 */
1336 r = (double) proc_count / (double) (i22*i11);
1337 tmp = (int) ceil(pow(r,(1.0/3.0)));
1338 tmp_num = tmp*tmp*tmp*i11*i22;
1339 if (tmp_num < t_total && tmp_num >= proc_count)
1340 {
1341 ti1 = i11;
1342 ti2 = i22;
1343 t_tmp = tmp;
1344 t_total = tmp_num;
1345 }
1346 /*case 3: i1 and i22 */
1347 r = (double) proc_count / (double) (i22*i1);
1348 tmp = (int) ceil(pow(r,(1.0/3.0)));
1349 tmp_num = tmp*tmp*tmp*i1*i22;
1350 if (tmp_num < t_total && tmp_num >= proc_count)
1351 {
1352 ti1 = i1;
1353 ti2 = i22;
1354 t_tmp = tmp;
1355 t_total = tmp_num;
1356 }
1357
1358 if ( t_total < proc_count ) printf("ERROR: (this shouldn't happen)"
1359 " the struct assumed partition "
1360 "doesn't have enough partitions!!!\n");
1361
1362
1363 /*set final division */
1364 hypre_IndexD(div_index, pos0) = t_tmp;
1365 hypre_IndexD(div_index, pos1) = t_tmp*ti1;
1366 hypre_IndexD(div_index, pos2) = t_tmp*ti2;
1367
1368 }
1369 /* end of finding divisions */
1370
1371
1372 /*see if we can further reduce the number of assumed regions -
1373 here we are effecting the aspect ratio but are avoiding an
1374 excessive number of assumed regions
1375 per processor. If the aspect ratio of the object is poor then
1376 there can be many more assumed box divisions than processors for
1377 small numbers of processors - so this should only iterate multiple
1378 times for poor aspect ratios*/
1379
1380 while (1)
1381 {
1382
1383 hypre_MaxIndexPosition(div_index, &d);
1384 tmp = hypre_IndexD(div_index, d);
1385 if ((tmp-1)==0) break;
1386 hypre_IndexD(div_index, d) = tmp - 1;
1387 tmp_num = (hypre_IndexX(div_index))*(hypre_IndexY(div_index))*
1388 (hypre_IndexZ(div_index));
1389 if (tmp_num < proc_count)
1390 {
1391 /* restore and exit */
1392 hypre_IndexD(div_index, d) = tmp;
1393 break;
1394 }
1395 }
1396
1397 /*check to see that we won't have more than 2 assumed partitions per proc
1398 this should never happen according to my proof :) */
1399 tmp_num = (hypre_IndexX(div_index))*(hypre_IndexY(div_index))*
1400 (hypre_IndexZ(div_index));
1401 if ( tmp_num > 2*proc_count ) printf("ERROR: the struct assumed partition "
1402 "has more than 2*procs (this "
1403 "shouldn't happen) myid = %d, x = %d, y = %d, x = %d, proc_count = %d \n",myid, hypre_IndexX(div_index),
1404 hypre_IndexY(div_index),hypre_IndexZ(div_index), proc_count);
1405
1406
1407 hypre_CopyIndex(div_index, hypre_StructAssumedPartDivision(assumed_part, i));
1408
1409#if REGION_STAT
1410 if ( myid ==0) printf("region = %d, proc_count = %d, divisions = [%d, %d, %d]\n",
1411 i, proc_count,
1412 hypre_IndexX(div_index), hypre_IndexY(div_index),
1413 hypre_IndexZ(div_index));
1414
1415#endif
1416 } /* end of FOR EACH REGION loop */
1417
1418
1419
1420 /* NOW WE HAVE COMPLETED GLOBAL INFO - START FILLING IN LOCAL INFO */
1421
1422
1423 /* now we need to populate the assumed partition object
1424 with info specific to each processor, like which assumed partition
1425 we own, which boxes are in that region, etc. */
1426
1427 /* figure out my partition region and put it in the assumed_part structure*/
1428 hypre_StructAssumedPartMyPartition(assumed_part) = hypre_BoxArrayCreate(2);
1429 my_partition = hypre_StructAssumedPartMyPartition(assumed_part);
1430 hypre_StructAssumedPartitionGetRegionsFromProc(assumed_part, myid, my_partition);
1431#if 0
1432 hypre_ForBoxI(i, my_partition)
1433 {
1434 box = hypre_BoxArrayBox(my_partition, i);
1435 printf("myid = %d: MY ASSUMED Partitions (%d): (%d, %d, %d) x "
1436 "(%d, %d, %d)\n",
1437 myid, i,
1438 hypre_BoxIMinX(box),
1439 hypre_BoxIMinY(box),
1440 hypre_BoxIMinZ(box),
1441 hypre_BoxIMaxX(box),
1442 hypre_BoxIMaxY(box),
1443 hypre_BoxIMaxZ(box));
1444 }
1445#endif
1446
1447
1448 /* find out the boxes in my partition - so I need to look through my boxes,
1449 figure our which assumed parition (AP) they fall in and contact that
1450 processor. we need to use the exchange data functionality for this */
1451
1452 proc_alloc = 8;
1453 proc_array = hypre_TReAlloc(proc_array, int, proc_alloc);
1454
1455 /* probably there will mostly be one proc per box */
1456 /* don't want to allocate too much memory here */
1457 size = 1.2 * hypre_BoxArraySize(local_boxes);
1458
1459 tmp_box_nums = hypre_CTAlloc(int, size);
1460 tmp_proc_ids = hypre_CTAlloc(int, size);
1461
1462 proc_count = 0;
1463 count = 0; /* current number of procs */
1464 grow_box = hypre_BoxCreate();
1465
1466 hypre_ForBoxI(i, local_boxes)
1467 {
1468 box = hypre_BoxArrayBox(local_boxes, i);
1469 if (hypre_BoxVolume(box) == 0) /* zero volume boxes - still
1470 need to be in the partition*/
1471 {
1472 hypre_CopyBox(box, grow_box);
1473 for (d = 0; d < 3; d++)
1474 {
1475 if(!hypre_BoxSizeD(box, d))
1476 {
1477 grow = (hypre_BoxIMinD(box, d) - hypre_BoxIMaxD(box, d) + 1)/2;
1478 grow_array[2*d] = grow;
1479 grow_array[2*d+1] = grow;
1480 }
1481 else
1482 {
1483 grow_array[2*d] = 0;
1484 grow_array[2*d+1] = 0;
1485 }
1486 }
1487 /* expand the grow box (leave our box untouched)*/
1488 hypre_BoxExpand(grow_box, grow_array);
1489
1490 /* NOTE - part of the box could lie outside of the regions */
1491 hypre_StructAssumedPartitionGetProcsFromBox(assumed_part, grow_box,
1492 &proc_count,
1493 &proc_alloc, &proc_array);
1494 }
1495 else /* box with positive volume */
1496 {
1497 hypre_StructAssumedPartitionGetProcsFromBox(assumed_part, box, &proc_count,
1498 &proc_alloc, &proc_array);
1499 }
1500
1501 /* do we need more storage? */
1502 if ((count + proc_count) > size)
1503 {
1504 size = size + proc_count + 1.2*(hypre_BoxArraySize(local_boxes)-i);
1505 /* printf("myid = %d, *adjust* alloc size = %d\n", myid, size); */
1506 tmp_box_nums = hypre_TReAlloc(tmp_box_nums, int, size);
1507 tmp_proc_ids = hypre_TReAlloc(tmp_proc_ids, int, size);
1508 }
1509 for (j = 0; j< proc_count; j++)
1510 {
1511
1512 /* tmp_box_nums[count] = i;*/ /*box numbers correspond to box order */
1513 tmp_box_nums[count] = local_boxnums[i];
1514 tmp_proc_ids[count] = proc_array[j];
1515 count++;
1516
1517 }
1518 }
1519
1520
1521 hypre_BoxDestroy(grow_box);
1522
1523
1524 /*now we have two arrays: tmp_proc_ids and tmp_box_nums - these are
1525 corresponding box numbers and proc. ids - we need to sort the
1526 processor ids and then create a new
1527 buffer to send to the exchange data function */
1528
1529 /*sort the proc_ids */
1530 hypre_qsort2i(tmp_proc_ids, tmp_box_nums, 0, count-1);
1531
1532 /*now use proc_array for the processor ids to contact. we will use
1533 box array to get our boxes and then pass the array only (not the
1534 structure) to exchange data */
1535 box_count = count;
1536
1537 contact_boxinfo = hypre_CTAlloc(int, box_count*7);
1538
1539 proc_array = hypre_TReAlloc(proc_array, int, box_count);
1540 proc_array_starts = hypre_CTAlloc(int, box_count+1);
1541 proc_array_starts[0] = 0;
1542
1543 proc_count = 0;
1544 index = 0;
1545
1546 if (box_count)
1547 {
1548 proc_array[0] = tmp_proc_ids[0];
1549
1550 contact_boxinfo[index++] = tmp_box_nums[0];
1551 box = hypre_BoxArrayBox(local_boxes, tmp_box_nums[0]);
1552 for (d=0; d< 3; d++)
1553 {
1554 contact_boxinfo[index++] = hypre_BoxIMinD(box, d);
1555 contact_boxinfo[index++] = hypre_BoxIMaxD(box, d);
1556 }
1557 proc_count++;
1558 }
1559
1560 for (i=1; i< box_count; i++)
1561 {
1562 if (tmp_proc_ids[i] != proc_array[proc_count-1])
1563 {
1564 proc_array[proc_count] = tmp_proc_ids[i];
1565 proc_array_starts[proc_count] = i;
1566 proc_count++;
1567
1568 }
1569
1570 /* these boxes are not copied in a particular order -
1571 they are sorted later */
1572
1573 contact_boxinfo[index++] = tmp_box_nums[i];
1574 box = hypre_BoxArrayBox(local_boxes, tmp_box_nums[i]);
1575 for (d=0; d< 3; d++)
1576 {
1577 contact_boxinfo[index++] = hypre_BoxIMinD(box, d);
1578 contact_boxinfo[index++] = hypre_BoxIMaxD(box, d);
1579 }
1580
1581 }
1582 proc_array_starts[proc_count] = box_count;
1583
1584 /* clean up */
1585 hypre_TFree(tmp_proc_ids);
1586 hypre_TFree(tmp_box_nums);
1587
1588
1589 /* EXCHANGE DATA */
1590
1591 /* prepare to populate the local info in the assumed partition */
1592 hypre_StructAssumedPartMyPartitionBoxes(assumed_part)
1593 = hypre_BoxArrayCreate(box_count);
1594 hypre_BoxArraySetSize(hypre_StructAssumedPartMyPartitionBoxes(assumed_part), 0);
1595 hypre_StructAssumedPartMyPartitionIdsSize(assumed_part) = 0;
1596 hypre_StructAssumedPartMyPartitionIdsAlloc(assumed_part) = box_count;
1597 hypre_StructAssumedPartMyPartitionProcIds(assumed_part)
1598 = hypre_CTAlloc(int, box_count);
1599 hypre_StructAssumedPartMyPartitionBoxnums(assumed_part)
1600 = hypre_CTAlloc(int, box_count);
1601 hypre_StructAssumedPartMyPartitionNumDistinctProcs(assumed_part) = 0;
1602
1603 /* set up for exchanging data */
1604 /* the response we expect is just a confirmation*/
1605 response_buf = NULL;
1606 response_buf_starts = NULL;
1607
1608 /*response object*/
1609 response_obj.fill_response = hypre_APFillResponseStructAssumedPart;
1610 response_obj.data1 = assumed_part; /* where we keep info from contacts*/
1611 response_obj.data2 = NULL;
1612
1613 max_response_size = 0; /* no response data - just confirmation*/
1614
1615 hypre_DataExchangeList(proc_count, proc_array,
1616 contact_boxinfo, proc_array_starts,
1617 7*sizeof(int),
1618 sizeof(int), &response_obj, max_response_size, 1,
1619 comm, (void**) &response_buf, &response_buf_starts);
1620
1621
1622 hypre_TFree(proc_array);
1623 hypre_TFree(proc_array_starts);
1624 hypre_TFree(response_buf);
1625 hypre_TFree(response_buf_starts);
1626 hypre_TFree(contact_boxinfo);
1627
1628
1629
1630
1631 /* return vars */
1632 *p_assumed_partition = assumed_part;
1633
1634
1635 return hypre_error_flag;
1636
1637}
1638
1639/******************************************************************************
1640 *
1641 * Destroy the assumed partition
1642 *
1643 *****************************************************************************/
1644
1645
1646int hypre_StructAssumedPartitionDestroy(hypre_StructAssumedPart *assumed_part)
1647{
1648
1649 if (assumed_part)
1650 {
1651
1652
1653 hypre_BoxArrayDestroy( hypre_StructAssumedPartRegions(assumed_part));
1654 hypre_TFree(hypre_StructAssumedPartProcPartitions(assumed_part));
1655 hypre_TFree(hypre_StructAssumedPartDivisions(assumed_part));
1656 hypre_BoxArrayDestroy( hypre_StructAssumedPartMyPartition(assumed_part));
1657 hypre_BoxArrayDestroy( hypre_StructAssumedPartMyPartitionBoxes(assumed_part));
1658 hypre_TFree(hypre_StructAssumedPartMyPartitionProcIds(assumed_part));
1659 hypre_TFree( hypre_StructAssumedPartMyPartitionBoxnums(assumed_part));
1660
1661 /* this goes last! */
1662 hypre_TFree(assumed_part);
1663 }
1664
1665
1666 return hypre_error_flag;
1667
1668
1669}
1670
1671/******************************************************************************
1672 *
1673 * fillResponseStructAssumedPart
1674 *
1675 *****************************************************************************/
1676
1677int
1678hypre_APFillResponseStructAssumedPart(void *p_recv_contact_buf,
1679 int contact_size, int contact_proc, void *ro,
1680 MPI_Comm comm, void **p_send_response_buf,
1681 int *response_message_size )
1682{
1683
1684 int size,alloc_size, myid, i, d, index;
1685 int *ids, *boxnums;
1686 int *recv_contact_buf;
1687
1688 hypre_Box *box;
1689
1690 hypre_BoxArray *part_boxes;
1691 hypre_DataExchangeResponse *response_obj = ro;
1692 hypre_StructAssumedPart *assumed_part = response_obj->data1;
1693
1694
1695 /*initialize stuff */
1696 MPI_Comm_rank(comm, &myid );
1697
1698 part_boxes = hypre_StructAssumedPartMyPartitionBoxes(assumed_part);
1699 ids = hypre_StructAssumedPartMyPartitionProcIds(assumed_part);
1700 boxnums = hypre_StructAssumedPartMyPartitionBoxnums(assumed_part);
1701
1702
1703 size = hypre_StructAssumedPartMyPartitionIdsSize(assumed_part);
1704 alloc_size = hypre_StructAssumedPartMyPartitionIdsAlloc(assumed_part);
1705
1706
1707 recv_contact_buf = (int * ) p_recv_contact_buf;
1708
1709 /*increment how many procs have contacted us */
1710 hypre_StructAssumedPartMyPartitionNumDistinctProcs(assumed_part)++;
1711
1712
1713 /*check to see if we need to allocate more space for ids and boxnums*/
1714 if ((size + contact_size) > alloc_size)
1715 {
1716
1717 alloc_size = size + contact_size;
1718 ids = hypre_TReAlloc(ids, int, alloc_size);
1719 boxnums = hypre_TReAlloc(boxnums, int, alloc_size);
1720 hypre_StructAssumedPartMyPartitionIdsAlloc(assumed_part) = alloc_size;
1721 }
1722
1723
1724 box = hypre_BoxCreate();
1725
1726 /* populate our assumed partition according to boxes received */
1727 index=0;
1728 for (i=0; i < contact_size; i++)
1729 {
1730 ids[size+i] = contact_proc; /*set the proc id*/
1731 boxnums[size+i] = recv_contact_buf[index++];
1732 for (d=0; d< 3; d++)
1733 {
1734 hypre_BoxIMinD(box, d)= recv_contact_buf[index++];
1735 hypre_BoxIMaxD(box, d) = recv_contact_buf[index++];
1736 }
1737
1738 hypre_AppendBox(box, part_boxes);
1739 }
1740 /* adjust the size of the proc ids*/
1741 hypre_StructAssumedPartMyPartitionIdsSize(assumed_part) = size + contact_size;
1742
1743 /*in case more memory was allocated we have to assign these
1744 pointers back */
1745 hypre_StructAssumedPartMyPartitionBoxes(assumed_part) = part_boxes;
1746 hypre_StructAssumedPartMyPartitionProcIds(assumed_part) = ids;
1747 hypre_StructAssumedPartMyPartitionBoxnums(assumed_part) = boxnums;
1748
1749
1750 /*output - no message to return (confirmation) */
1751 *response_message_size = 0;
1752
1753
1754 hypre_BoxDestroy(box);
1755
1756
1757 return hypre_error_flag;
1758
1759}
1760
1761
1762/******************************************************************************
1763 *
1764 * Given a processor id, get that processor's assumed region(s)
1765 *
1766 * At most a processor has 2 assumed regions- pass in a BoxArray of size 2.
1767 *****************************************************************************/
1768
1769
1770int hypre_StructAssumedPartitionGetRegionsFromProc( hypre_StructAssumedPart *assumed_part ,
1771 int proc_id, hypre_BoxArray *assumed_regions)
1772{
1773
1774
1775 int i;
1776 int in_region, proc_count, proc_start, num_partitions;
1777 int part_num, adj_part_num, x_row, y_row, extra, points, width;
1778 int plane, xyplane, adj_proc_id;
1779 int num_assumed, num_regions;
1780
1781
1782 hypre_Box *region, *box;
1783 hypre_Index div, isize, imin, imax;
1784
1785
1786 num_regions = hypre_StructAssumedPartNumRegions(assumed_part);
1787
1788
1789 /* check to see that this processor owns an assumed region - it is rare
1790 that it won't (only if the # of procs > vol. of bounding box) */
1791
1792 if (proc_id >= hypre_StructAssumedPartProcPartition(assumed_part,
1793 num_regions))
1794 {
1795 /*owns no boxes */
1796 num_assumed = 0;
1797 }
1798 else
1799 {
1800
1801 /* which partition region am i in? */
1802 in_region = 0;
1803 if ( num_regions > 1)
1804 {
1805 while (proc_id >= hypre_StructAssumedPartProcPartition(assumed_part,
1806 in_region+1))
1807 {
1808 in_region++;
1809 }
1810 }
1811
1812 /* how many processors in that region? */
1813 proc_count = hypre_StructAssumedPartProcPartition(assumed_part, in_region+1)
1814 - hypre_StructAssumedPartProcPartition(assumed_part, in_region);
1815 /* first processor in the range */
1816 proc_start = hypre_StructAssumedPartProcPartition(assumed_part, in_region);
1817 /*get the region */
1818 region = hypre_BoxArrayBox(hypre_StructAssumedPartRegions(assumed_part), in_region);
1819 /* size of the regions */
1820 hypre_BoxGetSize(region , isize);
1821 /* get the divisions in each dimension */
1822 hypre_CopyIndex(hypre_StructAssumedPartDivision(assumed_part, in_region), div);
1823
1824 /* now calculate the assumed partition(s) (at most 2) that I own */
1825 /* given: region, number and range of processors, number of divisions in
1826 each dimension */
1827
1828 num_partitions = hypre_IndexX(div)*hypre_IndexY(div)*hypre_IndexZ(div);
1829 /* how many procs have 2 partitions instead of one*/
1830 extra = num_partitions - proc_count*(num_partitions/proc_count);
1831
1832 /* adjust the proc number to take into account the actual proceesor ids
1833 assigned to the particular region */
1834 /* now adj_proc_id range is 0 - (proc_count-1) */
1835 adj_proc_id = proc_id - proc_start;
1836
1837 /* the region is divided into partitions according to the number of
1838 divisions in each directions => num_partitions. Some processors may
1839 own more
1840 than one partition (up to 2). These partitions are numbered from
1841 L to R and
1842 bottom to top. From the partition number then we can calculate the
1843 processor
1844 id. This is analogous to the 1-d ij case,
1845 but is of course more complicated....*/
1846
1847 /* get my partition number */
1848 if (adj_proc_id < extra)
1849 {
1850 part_num = adj_proc_id*2;
1851 num_assumed = 2;
1852 }
1853 else
1854 {
1855 part_num = extra+adj_proc_id;
1856 num_assumed = 1;
1857 }
1858 }
1859
1860 /* make sure BoxArray has been allocated and reflects the number of
1861 boxes we need */
1862 hypre_BoxArraySetSize(assumed_regions, num_assumed);
1863
1864 /*where is part_num? numbering from L->R, bottom to top, 0 - (proc_count - 1)*/
1865 for (i = 0; i< num_assumed; i++)
1866 {
1867
1868 part_num += i;
1869
1870 /*find z coords first*/
1871 xyplane = hypre_IndexX(div)*hypre_IndexY(div);
1872 plane = part_num/xyplane;
1873
1874 points = hypre_IndexZ(isize);
1875 width = points / hypre_IndexZ(div);
1876 extra = points - width* hypre_IndexZ(div);
1877
1878 /* z start */
1879 hypre_IndexZ(imin) = width*plane;
1880 hypre_IndexZ(imin) += hypre_min(extra, plane);
1881 /* z end */
1882 hypre_IndexZ(imax) = width*(plane+1);
1883 hypre_IndexZ(imax) += hypre_min(extra, plane+1);
1884 hypre_IndexZ(imax) -= 1;
1885 /*now change relative coordinates to absolute in z-dir*/
1886 hypre_IndexZ(imin) += hypre_BoxIMinZ(region);
1887 hypre_IndexZ(imax) += hypre_BoxIMinZ(region);
1888
1889 /* now adjust the part_num to be in the lowest plane so
1890 that we can figure the x and y coords*/
1891 adj_part_num = part_num - plane*xyplane;
1892
1893 /*x and y coords*/
1894 /* x_row and y_row indicate the row that the partion is in
1895 according to the number of divisions in each direction */
1896 y_row = adj_part_num / hypre_IndexX(div);
1897 x_row = adj_part_num % hypre_IndexX(div); /*mod */
1898
1899 /* x */
1900 points = hypre_IndexX(isize);
1901 width = points / hypre_IndexX(div);
1902 extra = points - width* hypre_IndexX(div);
1903 /* x start */
1904 hypre_IndexX(imin) = width*x_row;
1905 hypre_IndexX(imin) += hypre_min(extra, x_row);
1906 /* x end */
1907 hypre_IndexX(imax) = width*(x_row+1);
1908 hypre_IndexX(imax) += hypre_min(extra, x_row+1);
1909 hypre_IndexX(imax) -= 1;
1910 /*now change relative coordinates to absolute in x-dir*/
1911 hypre_IndexX(imin) += hypre_BoxIMinX(region);
1912 hypre_IndexX(imax) += hypre_BoxIMinX(region);
1913
1914 /* y */
1915 points = hypre_IndexY(isize);
1916 width = points / hypre_IndexY(div);
1917 extra = points - width* hypre_IndexY(div);
1918 /* y start */
1919 hypre_IndexY(imin) = width*y_row;
1920 hypre_IndexY(imin) += hypre_min(extra, y_row);
1921 /* y end */
1922 hypre_IndexY(imax) = width*(y_row+1);
1923 hypre_IndexY(imax) += hypre_min(extra, y_row+1);
1924 hypre_IndexY(imax) -= 1;
1925 /*now change relative coordinates to absolute in y-dir*/
1926 hypre_IndexY(imin) += hypre_BoxIMinY(region);
1927 hypre_IndexY(imax) += hypre_BoxIMinY(region);
1928
1929 /* Note: a processor is only assigned a partition in 1 region */
1930
1931 /* set the assumed region*/
1932 box = hypre_BoxArrayBox(assumed_regions, i);
1933 hypre_BoxSetExtents(box, imin, imax);
1934
1935
1936 }
1937
1938 /* some thoughts: if x and y division are even (or if x is even and all the
1939 extras
1940 the two partitions into one partition (they would be side by side in x-dir).
1941 I think it may be better to leave them seperate in the interest of
1942 reducing the search space for neighbor calculations */
1943
1944 return hypre_error_flag;
1945
1946
1947}
1948
1949
1950
1951/******************************************************************************
1952 *
1953 * Given a box, which processor(s) assumed partition does the box intersect
1954 *
1955 * proc_array should be allocated to size_alloc_proc_array
1956 *****************************************************************************/
1957
1958
1959int hypre_StructAssumedPartitionGetProcsFromBox( hypre_StructAssumedPart *assumed_part ,
1960 hypre_Box *box,
1961 int *num_proc_array,
1962 int *size_alloc_proc_array,
1963 int **p_proc_array)
1964{
1965
1966 int i,j,k,r,myid;
1967 int num_regions, in_regions, this_region, proc_count, proc_start;
1968 int adj_proc_id, extra, num_partitions, part_num;
1969 int gridpt[2], xyplane, extra_procs, switch_proc, points, width;
1970 int switch_pt;
1971
1972 int *proc_array, proc_array_count;
1973 int *which_regions;
1974 int *proc_ids, num_proc_ids, size_proc_ids;
1975
1976
1977 hypre_Box *region;
1978 hypre_Box *result_box;
1979 hypre_Index div, isize, part_row[2];
1980 hypre_BoxArray *region_array;
1981
1982
1983 /* need myid only for the printf statement*/
1984 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
1985
1986 proc_array = *p_proc_array;
1987 region_array = hypre_StructAssumedPartRegions(assumed_part);
1988 num_regions = hypre_StructAssumedPartNumRegions(assumed_part);
1989
1990 /*first intersect the box to find out which region or regions(s) it lies in*/
1991 /*then determine which processor owns the assumed part of the particular
1992 regions(s) that it is in */
1993
1994 result_box = hypre_BoxCreate();
1995 which_regions = hypre_CTAlloc(int, num_regions);
1996
1997 size_proc_ids = 8;
1998 proc_ids = hypre_CTAlloc(int, size_proc_ids);
1999 num_proc_ids = 0;
2000
2001
2002 /* which partition region(s) am i in? */
2003 in_regions = 0;
2004 for (i = 0; i< num_regions; i++)
2005 {
2006 region = hypre_BoxArrayBox(region_array, i);
2007 hypre_IntersectBoxes( box, region, result_box);
2008 if ( hypre_BoxVolume(result_box) > 0 )
2009 {
2010 which_regions[in_regions] = i;
2011 in_regions++;
2012 }
2013 }
2014 if (in_regions == 0)
2015 {
2016 if (hypre_BoxVolume(box) > 0)
2017 {
2018 printf("MY_ID = %d Error: positive volume box (%d, %d, %d) x "
2019 "(%d, %d, %d) not in any assumed regions! (this should never"
2020 " happen)\n",
2021 myid,
2022 hypre_BoxIMinX(box),
2023 hypre_BoxIMinY(box),
2024 hypre_BoxIMinZ(box),
2025 hypre_BoxIMaxX(box),
2026 hypre_BoxIMaxY(box),
2027 hypre_BoxIMaxZ(box));
2028
2029 }
2030 else
2031 {
2032 /*this is ok 12/04 - current use of function is only called on
2033 pos. boxes*/
2034 /* printf("MY_ID = %d Error: neg volume box not in partition\n",
2035 myid);*/
2036 }
2037
2038 }
2039
2040 /*for each region, who is assumed to own this box? add the proc number
2041 to proc array */
2042 for (r = 0; r< in_regions; r++)
2043 {
2044
2045 /* initialization for this particular region */
2046 this_region = which_regions[r];
2047 region = hypre_BoxArrayBox(region_array, this_region);
2048 /* first processor in the range */
2049 proc_start = hypre_StructAssumedPartProcPartition(assumed_part, this_region);
2050 /* how many processors in that region? */
2051 proc_count = hypre_StructAssumedPartProcPartition(assumed_part,
2052 this_region+1)
2053 -proc_start;
2054 /* size of the regions */
2055 hypre_BoxGetSize(region , isize);
2056 /* get the divisons in each dimension */
2057 hypre_CopyIndex(hypre_StructAssumedPartDivision(assumed_part,
2058 this_region), div);
2059
2060 /* number of partitions in this region? */
2061 num_partitions = hypre_IndexX(div)*hypre_IndexY(div)*hypre_IndexZ(div);
2062 /* how many procs have 2 partitions instead of one*/
2063 extra_procs = num_partitions - proc_count*(num_partitions/proc_count);
2064 switch_proc = 2*extra_procs;
2065 /* size of the xy-plane */
2066 xyplane = hypre_IndexX(div)*hypre_IndexY(div);
2067
2068 /* get the location of a imin and imax indexes for this box
2069 in terms of
2070 the xrow, yrow, and zrow in the assumed partition
2071 coordinates - store these in part_row[0] and part_row[1]
2072 for imin and imax respectively */
2073
2074 /*check each dimension - get the partition row info an put in part_row*/
2075 for (i = 0; i< 3; i++)
2076 {
2077 /* first get the max and min grid point in this dimension
2078 and change to coords relative to
2079 the region (so relative means the min is (0,0,0)
2080 - if a point is not in the region
2081 then take the regions end point */
2082 if (hypre_IndexDInBoxP(hypre_BoxIMin(box), i, region))
2083 {
2084 gridpt[0] = hypre_BoxIMinD(box, i) - hypre_BoxIMinD(region, i);
2085 }
2086 else /*grid point not in the region */
2087 {
2088 gridpt[0] = 0; /* 0 is the min *relative* corrd. */
2089 }
2090 if (hypre_IndexDInBoxP(hypre_BoxIMax(box), i, region))
2091 {
2092 gridpt[1] = hypre_BoxIMaxD(box, i) - hypre_BoxIMinD(region, i);
2093 }
2094 else /*grid point not in the region */
2095 {
2096 gridpt[1] = hypre_BoxIMaxD(region, i) - hypre_BoxIMinD(region, i);
2097 }
2098
2099 /* now find the correct part_row for this dimension*/
2100
2101 points = hypre_IndexD(isize, i); /*size of the region in this dimension */
2102 width = points / hypre_IndexD(div, i); /*width of a partition */
2103 extra = points - width* hypre_IndexD(div, i);
2104 switch_pt = (width + 1) * extra;
2105
2106
2107 /* for imin(j=0) and imax (j=1) find the corresponding partition row*/
2108 for (j=0; j< 2; j++)
2109 {
2110 if (gridpt[j] >= switch_pt)
2111 {
2112 hypre_IndexD(part_row[j], i)= extra + (gridpt[j] - switch_pt)/width;
2113 }
2114 else
2115 {
2116 hypre_IndexD(part_row[j], i) = gridpt[j]/(width+1);
2117 }
2118 }
2119
2120 } /*end of for each dimension */
2121
2122
2123 /*now we have the correct part_row for each of the box's corners since
2124 we checked the max and min indexes - these correct partition rows
2125 are stored in part_row */
2126
2127
2128 /*find the partition number and proc_id for each of the 8 corner points*/
2129 /* we get the location of the corner points from the location of imin and imax
2130 which was determined above and stored in part_row*/
2131
2132
2133 for (i = hypre_IndexX(part_row[0]); i<= hypre_IndexX(part_row[1]); i++) /* x*/
2134 {
2135 for (j = hypre_IndexY(part_row[0]); j <= hypre_IndexY(part_row[1]); j++) /*y*/
2136 {
2137 for (k = hypre_IndexZ(part_row[0]); k <= hypre_IndexZ(part_row[1]); k++) /*z*/
2138 {
2139
2140 part_num = 0;
2141 /*move up in y */
2142 part_num += j* hypre_IndexX(div);
2143 /* move over in x*/
2144 part_num += i;
2145 /*adjust the plane for z*/
2146 part_num += k*xyplane;
2147
2148 /*convert the partition number to a processor number*/
2149 if (part_num >= switch_proc)
2150 {
2151 adj_proc_id = extra_procs + (part_num - switch_proc);
2152 }
2153 else
2154 {
2155 adj_proc_id = part_num/2 ;
2156 }
2157
2158 if (num_proc_ids == size_proc_ids)
2159 {
2160 size_proc_ids+=8;
2161 proc_ids = hypre_TReAlloc(proc_ids, int, size_proc_ids);
2162 }
2163
2164
2165 proc_ids[num_proc_ids] = adj_proc_id + proc_start;
2166 num_proc_ids++;
2167
2168 }
2169 }
2170 }
2171
2172
2173 } /*end of for each region loop*/
2174
2175
2176 if (in_regions)
2177 {
2178
2179 /* now determine unique values in proc_id array (could be duplicates -
2180 do to a processor owning more than one partiton in a region)*/
2181 /*sort the array*/
2182 qsort0(proc_ids, 0, num_proc_ids-1);
2183
2184 /*make sure we have enough space from proc_array*/
2185 if (*size_alloc_proc_array < num_proc_ids)
2186 {
2187 proc_array = hypre_TReAlloc(proc_array, int, num_proc_ids);
2188 *size_alloc_proc_array = num_proc_ids;
2189 }
2190
2191 /*put unique values in proc_array*/
2192 proc_array[0] = proc_ids[0]; /*there will be at least one processor id */
2193 proc_array_count = 1;
2194 for (i=1; i< num_proc_ids; i++)
2195 {
2196 if (proc_ids[i] != proc_array[proc_array_count-1])
2197 {
2198 proc_array[proc_array_count] = proc_ids[i];
2199 proc_array_count++;
2200 }
2201 }
2202 }
2203 else /*no processors for this box (neg. volume box) */
2204 {
2205 proc_array_count = 0;
2206 }
2207
2208
2209
2210 /*return variables */
2211 *p_proc_array = proc_array;
2212 *num_proc_array = proc_array_count;
2213
2214
2215
2216 /*clean up*/
2217 hypre_BoxDestroy(result_box);
2218 hypre_TFree(which_regions);
2219 hypre_TFree(proc_ids);
2220
2221
2222 return hypre_error_flag;
2223
2224
2225}
2226
Note: See TracBrowser for help on using the repository browser.