source: CIVL/examples/mpi-omp/AMG2013/struct_mv/box_neighbors.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: 14.6 KB
RevLine 
[2aa6644]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/******************************************************************************
15 *
16 * Member functions for the hypre_BoxNeighbors class.
17 *
18 *****************************************************************************/
19
20#include "headers.h"
21
22#define DEBUG 0
23
24#if DEBUG
25char filename[255];
26FILE *file;
27int my_rank;
28hypre_Box *box;
29static int debug_count = 0;
30#endif
31
32/*--------------------------------------------------------------------------
33 * hypre_RankLinkCreate:
34 *--------------------------------------------------------------------------*/
35
36int
37hypre_RankLinkCreate( int rank,
38 int prank,
39 hypre_RankLink **rank_link_ptr)
40{
41 hypre_RankLink *rank_link;
42
43 rank_link = hypre_TAlloc(hypre_RankLink, 1);
44
45 hypre_RankLinkRank(rank_link) = rank;
46 hypre_RankLinkPRank(rank_link) = prank;
47 hypre_RankLinkNext(rank_link) = NULL;
48
49 *rank_link_ptr = rank_link;
50
51 return 0;
52}
53
54/*--------------------------------------------------------------------------
55 * hypre_RankLinkDestroy:
56 *--------------------------------------------------------------------------*/
57
58int
59hypre_RankLinkDestroy( hypre_RankLink *rank_link )
60{
61 int ierr = 0;
62
63 if (rank_link)
64 {
65 hypre_TFree(rank_link);
66 }
67
68 return ierr;
69}
70
71/*--------------------------------------------------------------------------
72 * hypre_BoxNeighborsCreate:
73 *--------------------------------------------------------------------------*/
74
75int
76hypre_BoxNeighborsCreate( hypre_BoxArray *boxes,
77 int *procs,
78 int *ids,
79 int first_local,
80 int num_local,
81 hypre_BoxNeighbors **neighbors_ptr )
82{
83 hypre_BoxNeighbors *neighbors;
84 int *boxnums;
85
86 neighbors = hypre_CTAlloc(hypre_BoxNeighbors, 1);
87 hypre_BoxNeighborsRankLinks(neighbors) =
88 hypre_CTAlloc(hypre_RankLink *, num_local);
89
90 hypre_BoxNeighborsBoxes(neighbors) = boxes;
91 hypre_BoxNeighborsProcs(neighbors) = procs;
92 hypre_ComputeBoxnums(boxes, procs, &boxnums);
93 hypre_BoxNeighborsBoxnums(neighbors) = boxnums;
94 hypre_BoxNeighborsIDs(neighbors) = ids;
95 hypre_BoxNeighborsFirstLocal(neighbors) = first_local;
96 hypre_BoxNeighborsNumLocal(neighbors) = num_local;
97
98 *neighbors_ptr = neighbors;
99
100 return 0;
101}
102
103/*--------------------------------------------------------------------------
104 * hypre_BoxNeighborsAssemble:
105 *
106 * Add "periodic boxes" to the 'boxes' BoxArray, then find boxes that
107 * are "near" (defined by 'max_distance') the local boxes. The ranks
108 * (in the 'boxes' array) of the nearby boxes of each local box are
109 * stored in a linked list (called 'rank_links') for fast access in
110 * other algorithms.
111 *
112 * If 'prune' is turned on, then only the folowing boxes are kept in
113 * the 'boxes' array: the local boxes, the nearby boxes, and all other
114 * boxes on the same processor as the nearby ones.
115 *
116 * NOTE: A box is not a neighbor of itself.
117 *
118 * NOTE: Periodic boxes are not assigned unique ids. The generating
119 * box and its associated processor/ID information can be found with
120 * index 'i % num_boxes', where 'i' is the index for the periodic box.
121 *
122 *--------------------------------------------------------------------------*/
123
124int
125hypre_BoxNeighborsAssemble( hypre_BoxNeighbors *neighbors,
126 hypre_Index periodic,
127 int max_distance,
128 int prune )
129{
130 hypre_BoxArray *boxes;
131 int *procs;
132 int *boxnums;
133 int *ids;
134 int first_local;
135 int num_local;
136 int num_periods;
137 hypre_Index *pshifts;
138
139 hypre_IndexRef pshift;
140 int period;
141 int keep_box;
142 int num_boxes;
143
144 hypre_RankLink **rank_links;
145 hypre_RankLink *rank_link;
146
147 hypre_Box *local_box;
148 hypre_Box *neighbor_box;
149
150 int distance;
151 int diff, firstproc, firstproci;
152 int i, j, p, d, ilocal, inew, ii;
153
154 int px = hypre_IndexX(periodic);
155 int py = hypre_IndexY(periodic);
156 int pz = hypre_IndexZ(periodic);
157
158 int i_periodic = px ? 1 : 0;
159 int j_periodic = py ? 1 : 0;
160 int k_periodic = pz ? 1 : 0;
161
162 int ierr = 0;
163
164 /*--------------------------------------------------
165 * Create periodic boxes
166 *--------------------------------------------------*/
167
168 boxes = hypre_BoxNeighborsBoxes(neighbors);
169 procs = hypre_BoxNeighborsProcs(neighbors);
170 boxnums = hypre_BoxNeighborsBoxnums(neighbors);
171 ids = hypre_BoxNeighborsIDs(neighbors);
172 num_boxes = hypre_BoxArraySize(boxes);
173
174 num_periods = (1+2*i_periodic) * (1+2*j_periodic) * (1+2*k_periodic);
175 pshifts = hypre_CTAlloc(hypre_Index, num_periods);
176
177 if( num_periods > 1 )
178 {
179 int ip, jp, kp;
180
181 hypre_BoxArraySetSize(boxes, num_periods*num_boxes);
182 procs = hypre_TReAlloc(procs, int, num_periods*num_boxes);
183
184 p = 1;
185 for (ip = -i_periodic; ip <= i_periodic; ip++)
186 {
187 for (jp = -j_periodic; jp <= j_periodic; jp++)
188 {
189 for (kp = -k_periodic; kp <= k_periodic; kp++)
190 {
191 if( !(ip == 0 && jp == 0 && kp == 0) )
192 {
193 pshift = pshifts[p];
194 hypre_SetIndex(pshift, ip*px, jp*py, kp*pz);
195
196 for (i = 0; i < num_boxes; i++)
197 {
198 inew = i + p*num_boxes;
199 local_box = hypre_BoxArrayBox(boxes, inew);
200 hypre_CopyBox(hypre_BoxArrayBox(boxes, i), local_box);
201 hypre_BoxShiftPos(local_box, pshift);
202
203 procs[inew] = procs[i];
204 }
205
206 p++;
207 }
208 }
209 }
210 }
211 }
212
213 hypre_BoxNeighborsBoxes(neighbors) = boxes;
214 hypre_BoxNeighborsProcs(neighbors) = procs;
215 hypre_CopyIndex(periodic, hypre_BoxNeighborsPeriodic(neighbors));
216 hypre_BoxNeighborsNumPeriods(neighbors) = num_periods;
217 hypre_BoxNeighborsPShifts(neighbors) = pshifts;
218
219 /*-----------------------------------------------------------------
220 * Find neighboring boxes:
221 *
222 * Keep boxes that are nearby plus all other boxes on the same
223 * processor as the nearby boxes.
224 *-----------------------------------------------------------------*/
225
226 period = num_boxes;
227 first_local = hypre_BoxNeighborsFirstLocal(neighbors);
228 num_local = hypre_BoxNeighborsNumLocal(neighbors);
229
230 rank_links = hypre_BoxNeighborsRankLinks(neighbors);
231
232 inew = 0;
233 num_boxes = 0;
234 firstproc = -1;
235 for (i = 0; i < period; i++)
236 {
237 /* keep all boxes with same process number as nearby boxes */
238 if (procs[i] > firstproc)
239 {
240 firstproci = i;
241 firstproc = procs[i];
242 keep_box = 0;
243 }
244
245 /* loop over box i and its periodic boxes; use ii */
246 for (p = 0; p < num_periods; p++)
247 {
248 ii = i + p*period;
249
250 for (j = 0; j < num_local; j++, ilocal++)
251 {
252 ilocal = first_local + j;
253
254 if (ii == ilocal)
255 {
256 keep_box = 1;
257 }
258 else
259 {
260 local_box = hypre_BoxArrayBox(boxes, ilocal);
261 neighbor_box = hypre_BoxArrayBox(boxes, ii);
262
263 /* compute distance info */
264 distance = 0;
265 for (d = 0; d < 3; d++)
266 {
267 diff = hypre_BoxIMinD(neighbor_box, d) -
268 hypre_BoxIMaxD(local_box, d);
269 if (diff > 0)
270 {
271 distance = hypre_max(distance, diff);
272 }
273
274 diff = hypre_BoxIMinD(local_box, d) -
275 hypre_BoxIMaxD(neighbor_box, d);
276 if (diff > 0)
277 {
278 distance = hypre_max(distance, diff);
279 }
280 }
281
282 /* if close enough, keep the box */
283 if (distance <= max_distance)
284 {
285 /* adjust for earlier boxes with same process number */
286 if (!keep_box)
287 {
288 num_boxes += (i - firstproci);
289 keep_box = 1;
290 }
291
292 /* create new rank_link and prepend to the list */
293 hypre_RankLinkCreate(num_boxes, p, &rank_link);
294 hypre_RankLinkNext(rank_link) = rank_links[j];
295 rank_links[j] = rank_link;
296 }
297 }
298 }
299 }
300
301 /*-----------------------------------------------------------------
302 * If pruning is on, use procs array to mark the boxes to keep
303 *-----------------------------------------------------------------*/
304
305 if (prune)
306 {
307 /* use procs array to store which boxes to keep */
308 if (keep_box)
309 {
310 if (inew < firstproci)
311 {
312 procs[inew] = firstproci;
313 }
314 inew = i + 1;
315
316 for (ii = firstproci; ii < inew; ii++)
317 {
318 procs[ii] = -procs[ii];
319 }
320 firstproci = inew;
321
322 num_boxes++;
323 }
324 }
325 else
326 {
327 /* keep all of the boxes */
328 num_boxes++;
329 }
330 }
331
332 /*-----------------------------------------------------------------
333 * Prune the array of neighbor boxes
334 *-----------------------------------------------------------------*/
335
336 if (prune)
337 {
338 for (p = 0; p < num_periods; p++)
339 {
340 i = 0;
341 for (inew = 0; inew < num_boxes; inew++)
342 {
343 if (procs[i] > 0)
344 {
345 i = procs[i];
346 }
347 hypre_CopyBox(hypre_BoxArrayBox(boxes, i + p*period),
348 hypre_BoxArrayBox(boxes, inew + p*num_boxes));
349 if (p == 0)
350 {
351 boxnums[inew] = boxnums[i];
352 ids[inew] = ids[i];
353 }
354
355 i++;
356 }
357 }
358
359 i = 0;
360 for (inew = 0; inew < num_boxes; inew++)
361 {
362 if (procs[i] > 0)
363 {
364 i = procs[i];
365 }
366 procs[inew] = -procs[i];
367 if (i == first_local)
368 {
369 first_local = inew;
370 }
371
372 i++;
373 }
374 for (p = 1; p < num_periods; p++)
375 {
376 for (inew = 0; inew < num_boxes; inew++)
377 {
378 procs[inew + p*num_boxes] = procs[inew];
379 }
380 }
381 }
382
383 num_boxes *= num_periods;
384 hypre_BoxArraySetSize(boxes, num_boxes);
385 hypre_BoxNeighborsFirstLocal(neighbors) = first_local;
386
387#if DEBUG
388{
389 int b, k, n;
390
391 MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
392
393 sprintf(filename, "zneighbors.%05d", my_rank);
394
395 if ((file = fopen(filename, "a")) == NULL)
396 {
397 printf("Error: can't open output file %s\n", filename);
398 exit(1);
399 }
400
401 fprintf(file, "\n\n============================\n\n");
402 fprintf(file, "\n\n%d\n\n", debug_count++);
403 fprintf(file, "num_boxes = %d\n", num_boxes);
404 for (i = 0; i < num_boxes; i++)
405 {
406 box = hypre_BoxArrayBox(boxes, i);
407 fprintf(file, "(%d,%d,%d) X (%d,%d,%d) ; (%d,%d); %d\n",
408 hypre_BoxIMinX(box),hypre_BoxIMinY(box),hypre_BoxIMinZ(box),
409 hypre_BoxIMaxX(box),hypre_BoxIMaxY(box),hypre_BoxIMaxZ(box),
410 procs[i], ids[i], hypre_BoxVolume(box));
411 }
412 fprintf(file, "first_local = %d\n", first_local);
413 fprintf(file, "num_local = %d\n", num_local);
414 fprintf(file, "periodic = %d %d %d\n",
415 periodic[0], periodic[1], periodic[2]);
416 fprintf(file, "num_periods = %d\n", num_periods);
417 fprintf(file, "max_distance = %d\n", max_distance);
418 fprintf(file, "prune = %d\n", prune);
419
420 fprintf(file, "rank_links:\n");
421 num_boxes /= num_periods;
422 for (b = 0; b < hypre_BoxNeighborsNumLocal(neighbors); b++)
423 {
424 for (k = -1; k <= 1; k++)
425 {
426 for (j = -1; j <= 1; j++)
427 {
428 for (i = -1; i <= 1; i++)
429 {
430 rank_link = hypre_BoxNeighborsRankLink(neighbors, b, i, j, k);
431 while (rank_link)
432 {
433 n = hypre_RankLinkRank(rank_link) +
434 hypre_RankLinkPRank(rank_link)*num_boxes;
435 fprintf(file, "(%d : %d, %d, %d) = %d\n",
436 b, i, j, k, n);
437
438 rank_link = hypre_RankLinkNext(rank_link);
439 }
440 }
441 }
442 }
443 }
444
445 fprintf(file, "\n");
446
447 fflush(file);
448 fclose(file);
449}
450#endif
451
452 return ierr;
453}
454
455/*--------------------------------------------------------------------------
456 * hypre_BoxNeighborsDestroy:
457 *--------------------------------------------------------------------------*/
458
459int
460hypre_BoxNeighborsDestroy( hypre_BoxNeighbors *neighbors )
461{
462 hypre_RankLink *rank_link;
463 hypre_RankLink *next_rank_link;
464
465 int b;
466
467 int ierr = 0;
468
469 if (neighbors)
470 {
471 for (b = 0; b < hypre_BoxNeighborsNumLocal(neighbors); b++)
472 {
473 rank_link = hypre_BoxNeighborsRankLink(neighbors, b);
474 while (rank_link)
475 {
476 next_rank_link = hypre_RankLinkNext(rank_link);
477 hypre_RankLinkDestroy(rank_link);
478 rank_link = next_rank_link;
479 }
480 }
481 hypre_BoxArrayDestroy(hypre_BoxNeighborsBoxes(neighbors));
482 hypre_TFree(hypre_BoxNeighborsProcs(neighbors));
483 hypre_TFree(hypre_BoxNeighborsBoxnums(neighbors));
484 hypre_TFree(hypre_BoxNeighborsIDs(neighbors));
485 hypre_TFree(hypre_BoxNeighborsPShifts(neighbors));
486 hypre_TFree(hypre_BoxNeighborsRankLinks(neighbors));
487 hypre_TFree(neighbors);
488 }
489
490 return ierr;
491}
Note: See TracBrowser for help on using the repository browser.