Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
tree-mpi.h
Go to the documentation of this file.
1/** @file tree-mpi.h
2 */
3// this can be used to control the outputs of debug_mpi()
5
6void debug_mpi (FILE * fp1);
7
8typedef struct {
9 CacheLevel * halo; // ghost cell indices for each level
10 void * buf; // MPI buffer
11 MPI_Request r; // MPI request
12 int depth; // the maximum number of levels
13 int pid; // the rank of the PE
14 int maxdepth; // the maximum depth for this PE (= depth or depth + 1)
15} Rcv;
16
17typedef struct {
19 char * name;
20 int npid;
21} RcvPid;
22
23typedef struct {
24 RcvPid * rcv, * snd;
25} SndRcv;
26
27typedef struct {
29
30 SndRcv mpi_level, mpi_level_root, restriction;
31 Array * send, * receive; // which pids do we send to/receive from
33
35{
36 c->p = NULL;
37 c->n = c->nm = 0;
38}
39
40static void rcv_append (Point point, Rcv * rcv)
41{
42 if (level > rcv->depth) {
43 qrealloc (rcv->halo, level + 1, CacheLevel);
44 for (int j = rcv->depth + 1; j <= level; j++)
45 cache_level_init (&rcv->halo[j]);
46 rcv->depth = level;
47 }
49 if (level > rcv->maxdepth)
50 rcv->maxdepth = level;
51}
52
53void rcv_print (Rcv * rcv, FILE * fp, const char * prefix)
54{
55 for (int l = 0; l <= rcv->depth; l++)
56 if (rcv->halo[l].n > 0)
58 fprintf (fp, "%s%g %g %g %d %d\n", prefix, x, y, z, rcv->pid, level);
59}
60
61static void rcv_free_buf (Rcv * rcv)
62{
63 if (rcv->buf) {
64 prof_start ("rcv_pid_receive");
66 free (rcv->buf);
67 rcv->buf = NULL;
68 prof_stop();
69 }
70}
71
72static void rcv_destroy (Rcv * rcv)
73{
74 rcv_free_buf (rcv);
75 for (int i = 0; i <= rcv->depth; i++)
76 if (rcv->halo[i].n > 0)
77 free (rcv->halo[i].p);
78 free (rcv->halo);
79}
80
81static RcvPid * rcv_pid_new (const char * name)
82{
83 RcvPid * r = qcalloc (1, RcvPid);
84 r->name = strdup (name);
85 return r;
86}
87
88static Rcv * rcv_pid_pointer (RcvPid * p, int pid)
89{
90 assert (pid >= 0 && pid < npe());
91
92 int i;
93 for (i = 0; i < p->npid; i++)
94 if (pid == p->rcv[i].pid)
95 break;
96
97 if (i == p->npid) {
98 qrealloc (p->rcv, ++p->npid, Rcv);
99 Rcv * rcv = &p->rcv[p->npid-1];
100 rcv->pid = pid;
101 rcv->depth = rcv->maxdepth = 0;
102 rcv->halo = qmalloc (1, CacheLevel);
103 rcv->buf = NULL;
104 cache_level_init (&rcv->halo[0]);
105 }
106 return &p->rcv[i];
107}
108
109static void rcv_pid_append (RcvPid * p, int pid, Point point)
110{
112}
113
115{
116 // appends the pids of @p to @pids without duplication
117 for (int i = 0; i < p->npid; i++) {
118 int pid = p->rcv[i].pid, j, * a;
119 for (j = 0, a = pids->p; j < pids->len/sizeof(int); j++,a++)
120 if (*a == pid)
121 break;
122 if (j == pids->len/sizeof(int))
123 array_append (pids, &pid, sizeof(int));
124 }
125}
126
127void rcv_pid_write (RcvPid * p, const char * name)
128{
129 for (int i = 0; i < p->npid; i++) {
130 Rcv * rcv = &p->rcv[i];
131 char fname[80];
132 sprintf (fname, "%s-%d-%d", name, pid(), rcv->pid);
133 FILE * fp = fopen (fname, "w");
134 rcv_print (rcv, fp, "");
135 fclose (fp);
136 }
137}
138
139static void rcv_pid_print (RcvPid * p, FILE * fp, const char * prefix)
140{
141 for (int i = 0; i < p->npid; i++)
142 rcv_print (&p->rcv[i], fp, prefix);
143}
144
145static void rcv_pid_destroy (RcvPid * p)
146{
147 for (int i = 0; i < p->npid; i++)
148 rcv_destroy (&p->rcv[i]);
149 free (p->rcv);
150 free (p->name);
151 free (p);
152}
153
155
156#define BOUNDARY_TAG(level) (level)
157#define COARSEN_TAG(level) ((level) + 64)
158#define REFINE_TAG() (128)
159#define MOVED_TAG() (256)
160
161void debug_mpi (FILE * fp1);
162
163static void apply_bc (Rcv * rcv, scalar * list, scalar * listv,
164 vector * listf, int l, MPI_Status s)
165{
166 double * b = rcv->buf;
167 foreach_cache_level(rcv->halo[l], l) {
168 for (int _s = 0; _s < 1; _s++) /* scalar in list */ {
169 memcpy (&s[], b, sizeof(double)*s.block);
170 b += s.block;
171 }
172 for (int _v = 0; _v < 1; _v++) /* vector in listf */
173 for (int _d = 0; _d < dimension; _d++) {
174 memcpy (&v.x[], b, sizeof(double)*v.x.block);
175 b += v.x.block;
176 if (*b != nodata && allocated(1))
177 memcpy (&v.x[1], b, sizeof(double)*v.x.block);
178 b += v.x.block;
179 }
180 for (int _s = 0; _s < 1; _s++) /* scalar in listv */ {
181 for (int i = 0; i <= 1; i++)
182 for (int j = 0; j <= 1; j++)
183#if dimension == 3
184 for (int k = 0; k <= 1; k++) {
185 if (*b != nodata && allocated(i,j,k))
186 memcpy (&s[i,j,k], b, sizeof(double)*s.block);
187 b += s.block;
188 }
189#else // dimension == 2
190 {
191 if (*b != nodata && allocated(i,j))
192 memcpy (&s[i,j], b, sizeof(double)*s.block);
193 b += s.block;
194 }
195#endif // dimension == 2
196 }
197 }
198 size_t size = b - (double *) rcv->buf;
199 free (rcv->buf);
200 rcv->buf = NULL;
201
202 int rlen;
204 if (rlen != size) {
206 "rlen (%d) != size (%ld), %d receiving from %d at level %d\n"
207 "Calling debug_mpi(NULL)...\n"
208 "Aborting...\n",
209 rlen, size, pid(), rcv->pid, l);
210 fflush (stderr);
211 debug_mpi (NULL);
213 }
214}
215
216#ifdef TIMEOUT
217static struct {
218 int count, source, tag;
219 const char * name;
220} RecvArgs;
221
222static void timeout (int sig, siginfo_t *si, void *uc)
223{
225 "ERROR MPI_Recv \"%s\" (count = %d, source = %d, tag = %d):\n"
226 "Time out\n"
227 "Calling debug_mpi(NULL)...\n"
228 "Aborting...\n",
229 RecvArgs.name, RecvArgs.count, RecvArgs.source, RecvArgs.tag);
230 fflush (stderr);
231 debug_mpi (NULL);
233}
234#endif // TIMEOUT
235
236static void mpi_recv_check (void * buf, int count, MPI_Datatype datatype,
237 int source, int tag,
239 const char * name)
240{
241#ifdef TIMEOUT
242 RecvArgs.count = count;
243 RecvArgs.source = source;
244 RecvArgs.tag = tag;
245 RecvArgs.name = name;
246
248 extern double t;
249 if (t > TIMEOUT) {
250 struct sigaction sa;
251 sa.sa_flags = SA_SIGINFO;
252 sa.sa_sigaction = timeout;
253 sigemptyset(&sa.sa_mask);
254 assert (sigaction(SIGRTMIN, &sa, NULL) != -1);
255
256 struct sigevent sev;
257 sev.sigev_notify = SIGEV_SIGNAL;
258 sev.sigev_signo = SIGRTMIN;
259 sev.sigev_value.sival_ptr = &timerid;
261
262 struct itimerspec its;
263 its.it_value.tv_sec = 10;
264 its.it_value.tv_nsec = 0;
265 its.it_interval.tv_sec = 0;
266 its.it_interval.tv_nsec = 0;
267 assert (timer_settime(timerid, 0, &its, NULL) != -1);
268 }
269#endif // TIMEOUT
270
272 if (errorcode != MPI_SUCCESS) {
273 char string[MPI_MAX_ERROR_STRING];
274 int resultlen;
277 "ERROR MPI_Recv \"%s\" (count = %d, source = %d, tag = %d):\n%s\n"
278 "Calling debug_mpi(NULL)...\n"
279 "Aborting...\n",
280 name, count, source, tag, string);
281 fflush (stderr);
282 debug_mpi (NULL);
284 }
285
286#ifdef TIMEOUT
287 if (t > TIMEOUT)
288 assert (timer_delete (timerid) != -1);
289#endif
290}
291
292trace
298
299static int list_lenb (scalar * list) {
300 int len = 0;
301 for (int _s = 0; _s < 1; _s++) /* scalar in list */
302 len += s.block;
303 return len;
304}
305
306static int vectors_lenb (vector * list) {
307 int len = 0;
308 for (int _v = 0; _v < 1; _v++) /* vector in list */
309 len += v.x.block;
310 return len;
311}
312
314 vector * listf, int l)
315{
316 if (m->npid == 0)
317 return;
318
319 prof_start ("rcv_pid_receive");
320
321 int len = list_lenb (list) + 2*dimension*vectors_lenb (listf) +
322 (1 << dimension)*list_lenb (listv);
323
324 MPI_Request r[m->npid];
325 Rcv * rrcv[m->npid]; // fixme: using NULL requests should be OK
326 int nr = 0;
327 for (int i = 0; i < m->npid; i++) {
328 Rcv * rcv = &m->rcv[i];
329 if (l <= rcv->depth && rcv->halo[l].n > 0) {
330 assert (!rcv->buf);
331 rcv->buf = malloc (sizeof (double)*rcv->halo[l].n*len);
332#if 0
333 fprintf (stderr, "%s receiving %d doubles from %d level %d\n",
334 m->name, rcv->halo[l].n*len, rcv->pid, l);
335 fflush (stderr);
336#endif
337#if 1 /* initiate non-blocking receive */
338 MPI_Irecv (rcv->buf, rcv->halo[l].n*len, MPI_DOUBLE, rcv->pid,
340 rrcv[nr++] = rcv;
341#else /* blocking receive (useful for debugging) */
343 mpi_recv_check (rcv->buf, rcv->halo[l].n*len, MPI_DOUBLE, rcv->pid,
344 BOUNDARY_TAG(l), MPI_COMM_WORLD, &s, "rcv_pid_receive");
345 apply_bc (rcv, list, listf, listv, l, s);
346#endif
347 }
348 }
349
350 /* non-blocking receives (does nothing when using blocking receives) */
351 if (nr > 0) {
352 int i;
354 mpi_waitany (nr, r, &i, &s);
355 while (i != MPI_UNDEFINED) {
356 Rcv * rcv = rrcv[i];
357 assert (l <= rcv->depth && rcv->halo[l].n > 0);
358 assert (rcv->buf);
359 apply_bc (rcv, list, listv, listf, l, s);
360 mpi_waitany (nr, r, &i, &s);
361 }
362 }
363
364 prof_stop();
365}
366
367trace
368static void rcv_pid_wait (RcvPid * m)
369{
370 /* wait for completion of send requests */
371 for (int i = 0; i < m->npid; i++)
372 rcv_free_buf (&m->rcv[i]);
373}
374
376 vector * listf, int l)
377{
378 if (m->npid == 0)
379 return;
380
381 prof_start ("rcv_pid_send");
382
383 int len = list_lenb (list) + 2*dimension*vectors_lenb (listf) +
384 (1 << dimension)*list_lenb (listv);
385
386 /* send ghost values */
387 for (int i = 0; i < m->npid; i++) {
388 Rcv * rcv = &m->rcv[i];
389 if (l <= rcv->depth && rcv->halo[l].n > 0) {
390 assert (!rcv->buf);
391 rcv->buf = malloc (sizeof (double)*rcv->halo[l].n*len);
392 double * b = rcv->buf;
393 foreach_cache_level(rcv->halo[l], l) {
394 for (int _s = 0; _s < 1; _s++) /* scalar in list */ {
395 memcpy (b, &s[], sizeof(double)*s.block);
396 b += s.block;
397 }
398 for (int _v = 0; _v < 1; _v++) /* vector in listf */
399 for (int _d = 0; _d < dimension; _d++) {
400 memcpy (b, &v.x[], sizeof(double)*v.x.block);
401 b += v.x.block;
402 if (allocated(1))
403 memcpy (b, &v.x[1], sizeof(double)*v.x.block);
404 else
405 *b = nodata;
406 b += v.x.block;
407 }
408 for (int _s = 0; _s < 1; _s++) /* scalar in listv */ {
409 for (int i = 0; i <= 1; i++)
410 for (int j = 0; j <= 1; j++)
411#if dimension == 3
412 for (int k = 0; k <= 1; k++) {
413 if (allocated(i,j,k))
414 memcpy (b, &s[i,j,k], sizeof(double)*s.block);
415 else
416 *b = nodata;
417 b += s.block;
418 }
419#else // dimension == 2
420 {
421 if (allocated(i,j))
422 memcpy (b, &s[i,j], sizeof(double)*s.block);
423 else
424 *b = nodata;
425 b += s.block;
426 }
427#endif // dimension == 2
428 }
429 }
430#if 0
431 fprintf (stderr, "%s sending %d doubles to %d level %d\n",
432 m->name, rcv->halo[l].n*len, rcv->pid, l);
433 fflush (stderr);
434#endif
435 MPI_Isend (rcv->buf, (b - (double *) rcv->buf),
437 &rcv->r);
438 }
439 }
440
441 prof_stop();
442}
443
444static void rcv_pid_sync (SndRcv * m, scalar * list, int l)
445{
446 scalar * listr = NULL, * listv = NULL;
447 vector * listf = NULL;
448 for (int _s = 0; _s < 1; _s++) /* scalar in list */
449 if (!is_constant(s) && s.block > 0) {
450 if (s.face)
451 listf = vectors_add (listf, s.v);
452 else if (s.restriction == restriction_vertex)
453 listv = list_add (listv, s);
454 else
455 listr = list_add (listr, s);
456 }
457 rcv_pid_send (m->snd, listr, listv, listf, l);
458 rcv_pid_receive (m->rcv, listr, listv, listf, l);
459 rcv_pid_wait (m->snd);
460 free (listr);
461 free (listf);
462 free (listv);
463}
464
465static void snd_rcv_destroy (SndRcv * m)
466{
467 rcv_pid_destroy (m->rcv);
468 rcv_pid_destroy (m->snd);
469}
470
471static void snd_rcv_init (SndRcv * m, const char * name)
472{
473 char s[strlen(name) + 5];
474 strcpy (s, name);
475 strcat (s, ".rcv");
476 m->rcv = rcv_pid_new (s);
477 strcpy (s, name);
478 strcat (s, ".snd");
479 m->snd = rcv_pid_new (s);
480}
481
483{
484 MpiBoundary * m = (MpiBoundary *) b;
485 snd_rcv_destroy (&m->mpi_level);
486 snd_rcv_destroy (&m->mpi_level_root);
487 snd_rcv_destroy (&m->restriction);
488 array_free (m->send);
489 array_free (m->receive);
490 free (m);
491}
492
493trace
494static void mpi_boundary_level (const Boundary * b, scalar * list, int l)
495{
496 MpiBoundary * m = (MpiBoundary *) b;
497 rcv_pid_sync (&m->mpi_level, list, l);
498 rcv_pid_sync (&m->mpi_level_root, list, l);
499}
500
501trace
502static void mpi_boundary_restriction (const Boundary * b, scalar * list, int l)
503{
504 MpiBoundary * m = (MpiBoundary *) b;
505 rcv_pid_sync (&m->restriction, list, l);
506}
507
509{
515 snd_rcv_init (&mpi->mpi_level, "mpi_level");
516 snd_rcv_init (&mpi->mpi_level_root, "mpi_level_root");
517 snd_rcv_init (&mpi->restriction, "restriction");
518 mpi->send = array_new();
519 mpi->receive = array_new();
521}
522
523static FILE * fopen_prefix (FILE * fp, const char * name, char * prefix)
524{
525 if (fp) {
526 sprintf (prefix, "%s-%d ", name, pid());
527 return fp;
528 }
529 else {
530 strcpy (prefix, "");
531 char fname[80];
532 if (debug_iteration >= 0)
533 sprintf (fname, "%s-%d-%d", name, debug_iteration, pid());
534 else
535 sprintf (fname, "%s-%d", name, pid());
536 return fopen (fname, "w");
537 }
538}
539
541{
543
544 char prefix[80];
545 FILE * fp;
546
547 // cleanup
548 if (fp1 == NULL) {
549 char name[80];
550 sprintf (name, "halo-%d", pid()); remove (name);
551 sprintf (name, "cells-%d", pid()); remove (name);
552 sprintf (name, "faces-%d", pid()); remove (name);
553 sprintf (name, "vertices-%d", pid()); remove (name);
554 sprintf (name, "neighbors-%d", pid()); remove (name);
555 sprintf (name, "mpi-level-rcv-%d", pid()); remove (name);
556 sprintf (name, "mpi-level-snd-%d", pid()); remove (name);
557 sprintf (name, "mpi-level-root-rcv-%d", pid()); remove (name);
558 sprintf (name, "mpi-level-root-snd-%d", pid()); remove (name);
559 sprintf (name, "mpi-restriction-rcv-%d", pid()); remove (name);
560 sprintf (name, "mpi-restriction-snd-%d", pid()); remove (name);
561 sprintf (name, "mpi-border-%d", pid()); remove (name);
562 sprintf (name, "exterior-%d", pid()); remove (name);
563 sprintf (name, "depth-%d", pid()); remove (name);
564 sprintf (name, "refined-%d", pid()); remove (name);
565 }
566
567 // local halo
568 fp = fopen_prefix (fp1, "halo", prefix);
569 for (int l = 0; l < depth(); l++)
570 foreach_halo (prolongation, l)
571 for (int _c = 0; _c < 4; _c++) /* foreach_child */
572 fprintf (fp, "%s%g %g %g %d\n", prefix, x, y, z, level);
573 if (!fp1)
574 fclose (fp);
575
576 if (!fp1) {
577 fp = fopen_prefix (fp1, "cells", prefix);
579 fclose (fp);
580 }
581
582 fp = fopen_prefix (fp1, "faces", prefix);
583 for (int _i = 0; _i < _N; _i++) /* foreach_face */
584 fprintf (fp, "%s%g %g %g %d\n", prefix, x, y, z, level);
585 if (!fp1)
586 fclose (fp);
587
588 fp = fopen_prefix (fp1, "vertices", prefix);
589 for (int _i = 0; _i < _N; _i++) /* foreach_vertex */
590 fprintf (fp, "%s%g %g %g %d\n", prefix, x, y, z, level);
591 if (!fp1)
592 fclose (fp);
593
594 fp = fopen_prefix (fp1, "neighbors", prefix);
595 for (int _i = 0; _i < _N; _i++) /* foreach */ {
596 int n = 0;
597 for (int _n = 0; _n < 1; _n++)
598 if (is_refined(cell))
599 n++;
600 fprintf (fp, "%s%g %g %g %d\n", prefix, x, y, z, cell.neighbors);
601 assert (cell.neighbors == n);
602 }
603 if (!fp1)
604 fclose (fp);
605
607
608 fp = fopen_prefix (fp1, "mpi-level-rcv", prefix);
609 rcv_pid_print (mpi->mpi_level.rcv, fp, prefix);
610 if (!fp1)
611 fclose (fp);
612
613 fp = fopen_prefix (fp1, "mpi-level-root-rcv", prefix);
614 rcv_pid_print (mpi->mpi_level_root.rcv, fp, prefix);
615 if (!fp1)
616 fclose (fp);
617
618 fp = fopen_prefix (fp1, "mpi-restriction-rcv", prefix);
619 rcv_pid_print (mpi->restriction.rcv, fp, prefix);
620 if (!fp1)
621 fclose (fp);
622
623 fp = fopen_prefix (fp1, "mpi-level-snd", prefix);
624 rcv_pid_print (mpi->mpi_level.snd, fp, prefix);
625 if (!fp1)
626 fclose (fp);
627
628 fp = fopen_prefix (fp1, "mpi-level-root-snd", prefix);
629 rcv_pid_print (mpi->mpi_level_root.snd, fp, prefix);
630 if (!fp1)
631 fclose (fp);
632
633 fp = fopen_prefix (fp1, "mpi-restriction-snd", prefix);
634 rcv_pid_print (mpi->restriction.snd, fp, prefix);
635 if (!fp1)
636 fclose (fp);
637
638 fp = fopen_prefix (fp1, "mpi-border", prefix);
639 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
640 if (is_border(cell))
641 fprintf (fp, "%s%g %g %g %d %d %d\n",
642 prefix, x, y, z, level, cell.neighbors, cell.pid);
643 else
644 continue;
645 if (is_leaf(cell))
646 continue;
647 }
648 if (!fp1)
649 fclose (fp);
650
651 fp = fopen_prefix (fp1, "exterior", prefix);
652 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
653 if (!is_local(cell))
654 fprintf (fp, "%s%g %g %g %d %d %d %d\n",
655 prefix, x, y, z, level, cell.neighbors,
656 cell.pid, cell.flags & leaf);
657#if 0
658 else if (is_active(cell) && !is_border(cell))
659 continue;
660 if (is_leaf(cell))
661 continue;
662#endif
663 }
664 if (!fp1)
665 fclose (fp);
666
667 fp = fopen_prefix (fp1, "depth", prefix);
668 fprintf (fp, "depth: %d %d\n", pid(), depth());
669 fprintf (fp, "======= mpi_level.snd ======\n");
670 RcvPid * snd = mpi->mpi_level.snd;
671 for (int i = 0; i < snd->npid; i++)
672 fprintf (fp, "%d %d %d\n", pid(), snd->rcv[i].pid, snd->rcv[i].maxdepth);
673 fprintf (fp, "======= mpi_level.rcv ======\n");
674 snd = mpi->mpi_level.rcv;
675 for (int i = 0; i < snd->npid; i++)
676 fprintf (fp, "%d %d %d\n", pid(), snd->rcv[i].pid, snd->rcv[i].maxdepth);
677 if (!fp1)
678 fclose (fp);
679
680 fp = fopen_prefix (fp1, "refined", prefix);
681 for (int _i = 0; _i < 1; _i++) /* cache tree->refined */
682 fprintf (fp, "%s%g %g %g %d\n", prefix, x, y, z, level);
683 if (!fp1)
684 fclose (fp);
685}
686
687static void snd_rcv_free (SndRcv * p)
688{
689 char name[strlen(p->rcv->name) + 1];
690 strcpy (name, p->rcv->name);
691 rcv_pid_destroy (p->rcv);
692 p->rcv = rcv_pid_new (name);
693 strcpy (name, p->snd->name);
694 rcv_pid_destroy (p->snd);
695 p->snd = rcv_pid_new (name);
696}
697
698static bool is_root (Point point)
699{
700 if (is_refined(cell))
701 for (int _c = 0; _c < 4; _c++) /* foreach_child */
702 if (is_local(cell))
703 return true;
704 return false;
705}
706
707// see src/figures/prolongation.svg
709{
710#if dimension == 2
711 struct { int x, y; } dp = {p.i - point.i, p.j - point.j};
712#elif dimension == 3
713 struct { int x, y, z; } dp = {p.i - point.i, p.j - point.j, p.k - point.k};
714#endif
715 for (int _d = 0; _d < dimension; _d++) {
716 if (dp.x == 0 && (is_refined(neighbor(-1)) || is_refined(neighbor(1))))
717 return true;
718 if (is_refined(neighbor(dp.x)))
719 return true;
720 }
721 return false;
722}
723
724#define is_remote(cell) (cell.pid >= 0 && cell.pid != pid())
725
726static void append_pid (Array * pids, int pid)
727{
728 for (int i = 0, * p = (int *) pids->p; i < pids->len/sizeof(int); i++, p++)
729 if (*p == pid)
730 return;
731 array_append (pids, &pid, sizeof(int));
732}
733
735{
736 if (is_leaf(cell)) { // prolongation
737 if (is_local(cell)) {
738 Point p = point;
739 for (int _n = 0; _n < 1; _n++) {
740 if (is_remote(cell) &&
742 append_pid (pids, cell.pid);
743 if (is_refined(cell))
744 for (int _c = 0; _c < 4; _c++) /* foreach_child */
745 if (is_remote(cell))
746 append_pid (pids, cell.pid);
747 }
748 }
749 }
750 else
751 for (int _n = 0; _n < 1; _n++) {
752 if (is_remote(cell))
753 append_pid (pids, cell.pid);
754 if (is_refined(cell))
755 for (int _c = 0; _c < 4; _c++) /* foreach_child */
756 if (is_remote(cell))
757 append_pid (pids, cell.pid);
758 }
759 return pids->len/sizeof(int);
760}
761
763{
764 for (int _c = 0; _c < 4; _c++) /* foreach_child */
765 if (is_remote(cell))
766 append_pid (pids, cell.pid);
767 return pids->len/sizeof(int);
768}
769
770// turns on tree_check() and co with outputs controlled by the condition
771// #define DEBUGCOND (pid() >= 300 && pid() <= 400 && t > 0.0784876)
772
773// turns on tree_check() and co without any outputs
774// #define DEBUGCOND false
775
776static void rcv_pid_row (RcvPid * m, int l, int * row)
777{
778 for (int i = 0; i < npe(); i++)
779 row[i] = 0;
780 for (int i = 0; i < m->npid; i++) {
781 Rcv * rcv = &m->rcv[i];
782 if (l <= rcv->depth && rcv->halo[l].n > 0)
783 row[rcv->pid] = rcv->halo[l].n;
784 }
785}
786
787void check_snd_rcv_matrix (SndRcv * sndrcv, const char * name)
788{
789 int maxlevel = depth();
790 mpi_all_reduce (maxlevel, MPI_INT, MPI_MAX);
791 int * row = qmalloc (npe(), int);
792 for (int l = 0; l <= maxlevel; l++) {
793 int status = 0;
794 if (pid() == 0) { // master
795 // send/receive matrix i.e.
796 // send[i][j] = number of points sent/received from i to j
797 int ** send = matrix_new (npe(), npe(), sizeof(int));
798 int ** receive = matrix_new (npe(), npe(), sizeof(int));
799 rcv_pid_row (sndrcv->snd, l, row);
800 MPI_Gather (row, npe(), MPI_INT, &send[0][0], npe(), MPI_INT, 0,
802 rcv_pid_row (sndrcv->rcv, l, row);
803 MPI_Gather (row, npe(), MPI_INT, &receive[0][0], npe(), MPI_INT, 0,
805
806 int * astatus = qmalloc (npe(), int);
807 for (int i = 0; i < npe(); i++)
808 astatus[i] = 0;
809 for (int i = 0; i < npe(); i++)
810 for (int j = 0; j < npe(); j++)
811 if (send[i][j] != receive[j][i]) {
812 fprintf (stderr, "%s: %d sends %d to %d at level %d\n",
813 name, i, send[i][j], j, l);
814 fprintf (stderr, "%s: %d receives %d from %d at level %d\n",
815 name, j, receive[j][i], i, l);
816 fflush (stderr);
817 for (int k = i - 2; k <= i + 2; k++)
818 if (k >= 0 && k < npe())
819 astatus[k] = 1;
820 for (int k = j - 2; k <= j + 2; k++)
821 if (k >= 0 && k < npe())
822 astatus[k] = 1;
823 }
825 free (astatus);
826
827 matrix_free (send);
828 matrix_free (receive);
829 }
830 else { // slave
831 rcv_pid_row (sndrcv->snd, l, row);
833 rcv_pid_row (sndrcv->rcv, l, row);
836 }
837 if (status) {
839 "check_snd_rcv_matrix \"%s\" failed\n"
840 "Calling debug_mpi(NULL)...\n"
841 "Aborting...\n",
842 name);
843 fflush (stderr);
844 debug_mpi (NULL);
846 }
847 }
848 free (row);
849}
850
852{
853 for (int _c = 0; _c < 4; _c++) /* foreach_child */
854 if (is_local(cell))
855 return true;
856 return false;
857}
858
859trace
861{
862 if (npe() == 1)
863 return;
864
865 prof_start ("mpi_boundary_update_buffers");
866
868 SndRcv * mpi_level = &m->mpi_level;
869 SndRcv * mpi_level_root = &m->mpi_level_root;
870 SndRcv * restriction = &m->restriction;
871
872 snd_rcv_free (mpi_level);
873 snd_rcv_free (mpi_level_root);
875
876 static const unsigned short used = 1 << user;
877 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
878 if (is_active(cell) && !is_border(cell))
879 /* We skip the interior of the local domain.
880 Note that this can be commented out in case of suspicion that
881 something is wrong with border cell tagging. */
882 continue;
883
884 if (cell.neighbors) {
885 // sending
886 Array pids = {NULL, 0, 0};
887 int n = locals_pids (point, &pids);
888 if (n) {
889 for (int _c = 0; _c < 4; _c++) /* foreach_child */
890 if (is_local(cell))
891 for (int i = 0, * p = (int *) pids.p; i < n; i++, p++)
892 rcv_pid_append (mpi_level->snd, *p, point);
893 free (pids.p);
894 }
895 // receiving
896 bool locals = false;
897 if (is_leaf(cell)) { // prolongation
898 if (is_remote(cell)) {
899 Point p = point;
900 for (int _n = 0; _n < 1; _n++)
901 if ((is_local(cell) &&
903 is_root(point)) {
904 locals = true; break;
905 }
906 }
907 }
908 else
909 for (int _n = 0; _n < 1; _n++)
910 if (is_local(cell) || is_root(point)) {
911 locals = true; break;
912 }
913 if (locals)
914 for (int _c = 0; _c < 4; _c++) /* foreach_child */
915 if (is_remote(cell))
916 rcv_pid_append (mpi_level->rcv, cell.pid, point),
917 cell.flags |= used;
918
919 // root cells
920 if (!is_leaf(cell)) {
921 // sending
922 if (is_local(cell)) {
923 Array pids = {NULL, 0, 0};
924 // root cell
925 int n = root_pids (point, &pids);
926 if (n) {
927 for (int _n = 0; _n < ; _n++)
928 for (int i = 0, * p = (int *) pids.p; i < n; i++, p++)
929 if (cell.pid >= 0 && cell.pid != *p)
930 rcv_pid_append (mpi_level_root->snd, *p, point);
931 // restriction (remote root)
932 for (int i = 0, * p = (int *) pids.p; i < n; i++, p++)
934 free (pids.p);
935 }
936 }
937 // receiving
938 else if (is_remote(cell)) {
939 bool root = false;
940 for (int _c = 0; _c < 4; _c++) /* foreach_child */
941 if (is_local(cell)) {
942 root = true; break;
943 }
944 if (root) {
945 int pid = cell.pid;
946 for (int _n = 0; _n < ; _n++)
947 if (is_remote(cell))
948 rcv_pid_append (mpi_level_root->rcv, pid, point),
949 cell.flags |= used;
950 // restriction (remote root)
951 rcv_pid_append (restriction->rcv, pid, point);
952 }
953 }
954 }
955 }
956
957 // restriction (remote siblings/children)
958 if (level > 0) {
959 if (is_local(cell)) {
960 // sending
961 Array pids = {NULL, 0, 0};
962 if (is_remote(aparent(0)))
963 append_pid (&pids, aparent(0).pid);
964 int n = root_pids (parent, &pids);
965 if (n) {
966 for (int i = 0, * p = (int *) pids.p; i < n; i++, p++)
968 free (pids.p);
969 }
970 }
971 else if (is_remote(cell)) {
972 // receiving
973 if (is_local(aparent(0)) || has_local_child (parent))
975 }
976 }
977 }
978
979 /* we remove unused cells
980 we do a breadth-first traversal from fine to coarse, so that
981 coarsening of unused cells can proceed fully. */
982
983 static const unsigned short keep = 1 << (user + 1);
984 for (int l = depth(); l >= 0; l--)
985 for (int _i = 0; _i < _N; _i++) /* foreach_cell */
986 if (level == l) {
987 if (level > 0 && (cell.pid < 0 || is_local(cell) || (cell.flags & used)))
988 aparent(0).flags |= keep;
989 if (is_refined(cell) && !(cell.flags & keep))
991 cell.flags &= ~(used|keep);
992 continue; // level == l
993 }
994
995 /* we update the list of send/receive pids */
996 m->send->len = m->receive->len = 0;
997 rcv_pid_append_pids (mpi_level->snd, m->send);
998 rcv_pid_append_pids (mpi_level_root->snd, m->send);
999 rcv_pid_append_pids (mpi_level->rcv, m->receive);
1000 rcv_pid_append_pids (mpi_level_root->rcv, m->receive);
1001
1002 prof_stop();
1003
1004#if DEBUG_MPI
1005 debug_mpi (NULL);
1006#endif
1007
1008#ifdef DEBUGCOND
1009 extern double t; NOT_UNUSED(t);
1010 check_snd_rcv_matrix (mpi_level, "mpi_level");
1011 check_snd_rcv_matrix (mpi_level_root, "mpi_level_root");
1012 check_snd_rcv_matrix (restriction, "restriction");
1013 if (DEBUGCOND)
1014 debug_mpi (NULL);
1015 tree_check();
1016#endif
1017}
1018
1019trace
1021{
1022 prof_start ("mpi_boundary_refine");
1023
1025
1026 /* Send refinement cache to each neighboring process. */
1027 Array * snd = mpi->send;
1028 MPI_Request r[2*snd->len/sizeof(int)];
1029 int nr = 0;
1030 for (int i = 0, * dest = snd->p; i < snd->len/sizeof(int); i++,dest++) {
1031 int len = tree->refined.n;
1032 MPI_Isend (&tree->refined.n, 1, MPI_INT, *dest,
1033 REFINE_TAG(), MPI_COMM_WORLD, &r[nr++]);
1034 if (len > 0)
1035 MPI_Isend (tree->refined.p, sizeof(Index)/sizeof(int)*len,
1036 MPI_INT, *dest, REFINE_TAG(), MPI_COMM_WORLD, &r[nr++]);
1037 }
1038
1039 /* Receive refinement cache from each neighboring process.
1040 fixme: use non-blocking receives */
1041 Array * rcv = mpi->receive;
1042 Cache rerefined = {NULL, 0, 0};
1043 for (int i = 0, * source = rcv->p; i < rcv->len/sizeof(int); i++,source++) {
1044 int len;
1045 mpi_recv_check (&len, 1, MPI_INT, *source, REFINE_TAG(),
1047 "mpi_boundary_refine (len)");
1048 if (len > 0) {
1049 Index p[len];
1050 mpi_recv_check (p, sizeof(Index)/sizeof(int)*len,
1053 "mpi_boundary_refine (p)");
1054 Cache refined = {p, len, len};
1055 for (int _i = 0; _i < 1; _i++) /* cache refined */
1056 if (level <= depth() && allocated(0)) {
1057 if (is_leaf(cell)) {
1058 bool neighbors = false;
1059 for (int _n = 0; _n < ; _n++)
1060 if (allocated(0) && (is_active(cell) || is_local(aparent(0)))) {
1061 neighbors = true; break;
1062 }
1063 // refine the cell only if it has local neighbors
1064 if (neighbors)
1066 }
1067 }
1068 }
1069 }
1070
1071 /* check that caches were received OK and free ressources */
1072 if (nr)
1074
1075 /* update the refinement cache with "re-refined" cells */
1076 free (tree->refined.p);
1077 tree->refined = rerefined;
1078
1079 prof_stop();
1080
1081 /* if any cell has been re-refined, we repeat the process to take care
1082 of recursive refinements induced by the 2:1 constraint */
1084 if (rerefined.n)
1086 for (int _s = 0; _s < 1; _s++) /* scalar in list */
1088}
1089
1090static void check_depth()
1091{
1092#if DEBUG_MPI
1093 int max = 0;
1095 if (level > max)
1096 max = level;
1097 if (depth() != max) {
1098 FILE * fp = fopen ("layer", "w");
1099 fprintf (fp, "depth() = %d, max = %d\n", depth(), max);
1100 for (int l = 0; l <= depth(); l++) {
1101 Layer * L = tree->L[l];
1102 fprintf (fp, "Layer level = %d, nc = %d, len = %d\n", l, L->nc, L->len);
1103 for (int i = 0; i < L->len; i++)
1104 if (L->m[i]) {
1105 fprintf (fp, " i = %d, refcount = %d\n", i,
1106 *((int *)(((char *)L->m[i]) + L->len*sizeof(char *))));
1107 for (int j = 0; j < L->len; j++)
1108 if (L->m[i][j]) {
1109 fprintf (fp, " j = %d\n", j);
1110 fprintf (fp, "point %g %g %d\n",
1111 X0 + (i - 1.5)*L0/(1 << l), Y0 + (j - 1.5)*L0/(1 << l),
1112 l);
1113 }
1114 }
1115 }
1116 fclose (fp);
1117 fp = fopen ("colls", "w");
1119 fclose (fp);
1120 assert (false);
1121 }
1122#endif
1123}
1124
1125typedef struct {
1126 int refined, leaf;
1127} Remote;
1128
1129#define REMOTE() ((Remote *)&val(remote,0))
1130
1131trace
1133{
1134 if (npe() == 1)
1135 return;
1136
1137 check_depth();
1138
1139 assert (sizeof(Remote) == sizeof(double));
1140
1141 scalar remote[];
1142 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1143 if (level == l) {
1144 if (is_local(cell)) {
1145 REMOTE()->refined = is_refined(cell);
1146 REMOTE()->leaf = is_leaf(cell);
1147 }
1148 else {
1149 REMOTE()->refined = true;
1150 REMOTE()->leaf = false;
1151 }
1152 continue;
1153 }
1154 if (is_leaf(cell))
1155 continue;
1156 }
1158
1159 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1160 if (level == l) {
1161 if (!is_local(cell)) {
1162 if (is_refined(cell) && !REMOTE()->refined)
1164 else if (is_leaf(cell) && cell.neighbors && REMOTE()->leaf) {
1165 int pid = cell.pid;
1166 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1167 cell.pid = pid;
1168 }
1169 }
1170 continue;
1171 }
1172 if (is_leaf(cell))
1173 continue;
1174 }
1175
1176 check_depth();
1177
1178 if (l > 0) {
1179 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1180 if (level == l) {
1181 remote[] = is_local(cell) ? cell.neighbors : 0;
1182 continue;
1183 }
1184 if (is_leaf(cell))
1185 continue;
1186 }
1188 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1189 if (level == l)
1190 if (!is_local(cell) && is_local(aparent(0)) && remote[]) {
1191 aparent(0).flags &= ~too_fine;
1192 continue;
1193 }
1194 if (is_leaf(cell))
1195 continue;
1196 }
1197 }
1198}
1199
1201{
1202 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1203 if (is_active(cell)) {
1204 short flags = cell.flags & ~border;
1205 for (int _n = 0; _n < ; _n++) {
1206 if (!is_local(cell) || (level > 0 && !is_local(aparent(0)))) {
1207 flags |= border; break;
1208 }
1209 // root cell
1210 if (is_refined_check())
1211 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1212 if (!is_local(cell)) {
1213 flags |= border; break;
1214 }
1215 if (flags & border)
1216 break;
1217 }
1218 cell.flags = flags;
1219 }
1220 else {
1221 cell.flags &= ~border;
1222 // continue; // fixme
1223 }
1224 if (is_leaf(cell)) {
1225 if (cell.neighbors) {
1226 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1227 cell.flags &= ~border;
1228 if (is_border(cell)) {
1229 bool remote = false;
1230 for (int _n = 0; _n < GHOSTS/2; _n++)
1231 if (!is_local(cell)) {
1232 remote = true; break;
1233 }
1234 if (remote)
1235 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1236 cell.flags |= border;
1237 }
1238 }
1239 continue;
1240 }
1241 }
1242}
1243
1244static int balanced_pid (long index, long nt, int nproc)
1245{
1246 long ne = max(1, nt/nproc), nr = nt % nproc;
1247 int pid = index < nr*(ne + 1) ?
1248 index/(ne + 1) :
1249 nr + (index - nr*(ne + 1))/ne;
1250 return min(nproc - 1, pid);
1251}
1252
1253// static partitioning: only used for tests
1254trace
1256{
1257 prof_start ("mpi_partitioning");
1258
1259 long nt = 0;
1260 foreach (serial)
1261 nt++;
1262
1263 /* set the pid of each cell */
1264 long i = 0;
1265 tree->dirty = true;
1267 if (is_active (cell)) {
1268 if (is_leaf (cell)) {
1269 cell.pid = balanced_pid (i++, nt, npe());
1270 if (cell.neighbors > 0) {
1271 int pid = cell.pid;
1272 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1273 cell.pid = pid;
1274 }
1275 if (!is_local(cell))
1276 cell.flags &= ~active;
1277 }
1278 else {
1279 cell.pid = child(0).pid;
1280 bool inactive = true;
1281 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1282 if (is_active(cell)) {
1283 inactive = false; break;
1284 }
1285 if (inactive)
1286 cell.flags &= ~active;
1287 }
1288 }
1289
1291
1292 prof_stop();
1293
1295}
1296
1298{
1299 long index = 0, nt = 0, start = ftell (fp);
1300 scalar size[], * list = list_concat ({size}, list1);;
1301 long offset = sizeof(double)*list_len(list);
1302
1303 // read local cells
1304 static const unsigned short set = 1 << user;
1305 scalar * listm = is_constant(cm) ? NULL : (scalar *){fm};
1306 for (int _i = 0; _i < _N; _i++) /* foreach_cell */
1307 if (balanced_pid (index, nt, npe()) <= pid()) {
1308 unsigned flags;
1309 if (fread (&flags, sizeof(unsigned), 1, fp) != 1) {
1310 fprintf (stderr, "restore(): error: expecting 'flags'\n");
1311 exit (1);
1312 }
1313 for (int _s = 0; _s < 1; _s++) /* scalar in list */ {
1314 double val;
1315 if (fread (&val, sizeof(double), 1, fp) != 1) {
1316 fprintf (stderr, "restore(): error: expecting scalar\n");
1317 exit (1);
1318 }
1319 if (s.i != INT_MAX)
1320 s[] = val;
1321 }
1322 if (level == 0)
1323 nt = size[];
1324 cell.pid = balanced_pid (index, nt, npe());
1325 cell.flags |= set;
1326 if (!(flags & leaf) && is_leaf(cell)) {
1327 if (balanced_pid (index + size[] - 1, nt, npe()) < pid()) {
1328 fseek (fp, (sizeof(unsigned) + offset)*(size[] - 1), SEEK_CUR);
1329 index += size[];
1330 continue;
1331 }
1332 refine_cell (point, listm, 0, NULL);
1333 }
1334 index++;
1335 if (is_leaf(cell))
1336 continue;
1337 }
1338
1339 // read non-local neighbors
1340 fseek (fp, start, SEEK_SET);
1341 index = 0;
1342 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1343 unsigned flags;
1344 if (fread (&flags, sizeof(unsigned), 1, fp) != 1) {
1345 fprintf (stderr, "restore(): error: expecting 'flags'\n");
1346 exit (1);
1347 }
1348 if (cell.flags & set)
1349 fseek (fp, offset, SEEK_CUR);
1350 else {
1351 for (int _s = 0; _s < 1; _s++) /* scalar in list */ {
1352 double val;
1353 if (fread (&val, sizeof(double), 1, fp) != 1) {
1354 fprintf (stderr, "restore(): error: expecting a scalar\n");
1355 exit (1);
1356 }
1357 if (s.i != INT_MAX)
1358 s[] = val;
1359 }
1360 cell.pid = balanced_pid (index, nt, npe());
1361 if (is_leaf(cell) && cell.neighbors) {
1362 int pid = cell.pid;
1363 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1364 cell.pid = pid;
1365 }
1366 }
1367 if (!(flags & leaf) && is_leaf(cell)) {
1368 bool locals = false;
1369 for (int _n = 0; _n < 1; _n++)
1370 if ((cell.flags & set) && (is_local(cell) || is_root(point))) {
1371 locals = true; break;
1372 }
1373 if (locals)
1374 refine_cell (point, listm, 0, NULL);
1375 else {
1376 fseek (fp, (sizeof(unsigned) + offset)*(size[] - 1), SEEK_CUR);
1377 index += size[];
1378 continue;
1379 }
1380 }
1381 index++;
1382 if (is_leaf(cell))
1383 continue;
1384 }
1385
1386 /* set active flags */
1388 cell.flags &= ~set;
1389 if (is_active (cell)) {
1390 if (is_leaf (cell)) {
1391 if (cell.neighbors > 0) {
1392 int pid = cell.pid;
1393 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1394 cell.pid = pid;
1395 }
1396 if (!is_local(cell))
1397 cell.flags &= ~active;
1398 }
1399 else if (!is_local(cell)) {
1400 bool inactive = true;
1401 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1402 if (is_active(cell)) {
1403 inactive = false; break;
1404 }
1405 if (inactive)
1406 cell.flags &= ~active;
1407 }
1408 }
1409 }
1410
1412
1413 scalar * clean = NULL;
1414 for (int _s = 0; _s < 1; _s++) /* scalar in list */
1415 if (s.i != INT_MAX)
1416 clean = list_append (clean, s);
1417 free (list);
1419 free (clean);
1420}
1421
1422/**
1423# *z_indexing()*: fills *index* with the Z-ordering index.
1424
1425If `leaves` is `true` only leaves are indexed, otherwise all active
1426cells are indexed.
1427
1428On the master process (`pid() == 0`), the function returns the
1429(global) maximum index (and -1 on all other processes).
1430
1431On a single processor, we would just need something
1432like (for leaves)
1433
1434~~~literatec
1435double i = 0;
1436for (int _i = 0; _i < _N; _i++) /* foreach */
1437 index[] = i++;
1438~~~
1439
1440In parallel, this is a bit more difficult. */
1441
1442trace
1444{
1445 /**
1446 We first compute the size of each subtree. */
1447
1448 scalar size[];
1450
1451 /**
1452 The maximum index value is the size of the entire tree (i.e. the
1453 value of `size` in the root cell on the master process) minus
1454 one. */
1455
1456 double maxi = -1.;
1457 if (pid() == 0)
1458 for (int _l = 0; _l < 0, serial; _l++)
1459 maxi = size[] - 1.;
1460
1461 /**
1462 fixme: doc */
1463
1464 for (int _l = 0; _l < 0; _l++)
1465 index[] = 0;
1466 for (int l = 0; l < depth(); l++) {
1468 for (int _i = 0; _i < _N; _i++) /* foreach_cell */ {
1469 if (level == l) {
1470 if (is_leaf(cell)) {
1471 if (is_local(cell) && cell.neighbors) {
1472 int i = index[];
1473 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1474 index[] = i;
1475 }
1476 }
1477 else { // not leaf
1478 bool loc = is_local(cell);
1479 if (!loc)
1480 for (int _c = 0; _c < 4; _c++) /* foreach_child */
1481 if (is_local(cell)) {
1482 loc = true; break;
1483 }
1484 if (loc) {
1485 int i = index[] + !leaves;
1486 for (int _c = 0; _c < 4; _c++) /* foreach_child */ {
1487 index[] = i;
1488 i += size[];
1489 }
1490 }
1491 }
1492 continue; // level == l
1493 }
1494 if (is_leaf(cell))
1495 continue;
1496 }
1497 }
1499
1500 return maxi;
1501}
const vector a
Definition all-mach.h:59
Array * array_new()
Definition array.h:10
void array_free(Array *a)
Definition array.h:18
void * array_append(Array *a, void *elem, size_t size)
Definition array.h:24
int npe
Definition balance.h:195
if TRASH define &&NewPid *& val(newpid, 0, 0, 0)) -> pid > 0) @else @ define is_newpid()(((NewPid *)&val(newpid, 0, 0, 0)) ->pid > 0) @endif Array *linear_tree(size_t size, scalar newpid)
Definition balance.h:13
bool leaves
Definition balance.h:193
int min
Definition balance.h:192
struct @5 mpi
void mpi_boundary_update(scalar *list)
Definition balance.h:396
#define dimension
Definition bitree.h:3
#define boundary_iterate(type,...)
Definition boundaries.h:40
void add_boundary(Boundary *b)
Definition boundaries.h:16
define k
define double double char flags
define l
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
define neighbor(o, p, q)((Point)
Definition cartesian.h:146
#define GHOSTS
Definition cartesian.h:13
free(list1)
define VT _attribute[s.i] v y scalar * list
Definition cartesian.h:276
int y
Definition common.h:76
int x
Definition common.h:76
int z
Definition common.h:76
const scalar cm[]
Definition common.h:397
vector * vectors_add(vector *list, vector v)
Definition common.h:267
#define nodata
Definition common.h:7
scalar * list_concat(scalar *l1, scalar *l2)
Definition common.h:234
scalar * list_add(scalar *list, scalar s)
Definition common.h:208
double L0
Definition common.h:36
void matrix_free(void *m)
Definition common.h:500
int list_len(scalar *list)
Definition common.h:180
void * matrix_new(int n, int=(type *) realloc(p,(size) *sizeof(type)) p=(type *) realloc(p,(size) *sizeof(type)), size_t size)
Definition common.h:486
double X0
Definition common.h:34
scalar * list_append(scalar *list, scalar s)
Definition common.h:188
double Y0
Definition common.h:34
const vector fm[]
Definition common.h:396
#define p
Definition tree.h:320
#define qcalloc(size, type)
#define qmalloc(size, type)
#define assert(a)
Definition config.h:107
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line line line line strdup(s) @ define tracing(...) @ define end_tracing(...) @define tid() 0 @define pid() 0 @define npe() 1 @define mpi_all_reduce(v
Point point
Definition conserving.h:86
else return n
Definition curvature.h:101
scalar dp[]
scalar s
Definition embed-tree.h:56
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
double v[2]
Definition embed.h:383
scalar int i
Definition embed.h:74
static char * fname
Definition errors.c:753
double t
Definition events.h:24
macro2 foreach_cell_all()
macro2 foreach_cell_post(bool condition)
#define depth()
Definition cartesian.h:14
static int
Definition include.c:978
size_t max
Definition mtrace.h:8
size_t nr
Definition mtrace.h:10
FILE * fp
Definition mtrace.h:7
void(* restriction)(Point, scalar)
static void restriction_vertex(Point point, scalar s)
void subtree_size(scalar size, bool leaves)
int int tag
size_t size
size *double * b
int int int level
size *double * buf
define is_active() cell(true) @define is_leaf(cell)(point.level
int source
Definition qcc.c:67
int parallel
Definition qcc.c:61
def _i
Definition stencils.h:405
static void set_dirty_stencil(scalar s)
Definition stencils.h:34
Definition array.h:5
void * p
Definition array.h:6
long len
Definition array.h:7
int n
Definition tree.h:95
IndexLevel * p
Definition tree.h:94
Definition tree.h:109
Definition tree.h:98
Definition tree.h:116
int len
Definition tree.h:120
struct _Memindex * m
Definition tree.h:117
long nc
Definition tree.h:119
Array * receive
Definition tree-mpi.h:31
Boundary parent
Definition tree-mpi.h:28
SndRcv mpi_level
Definition tree-mpi.h:30
int pid
Definition balance.h:7
Definition linear.h:21
int i
Definition linear.h:23
Rcv * rcv
Definition tree-mpi.h:18
char * name
Definition tree-mpi.h:19
int npid
Definition tree-mpi.h:20
Definition tree-mpi.h:8
int depth
Definition tree-mpi.h:12
void * buf
Definition tree-mpi.h:10
MPI_Request r
Definition tree-mpi.h:11
CacheLevel * halo
Definition tree-mpi.h:9
int pid
Definition tree-mpi.h:13
int maxdepth
Definition tree-mpi.h:14
int leaf
Definition tree-mpi.h:1126
RcvPid * snd
Definition tree-mpi.h:24
RcvPid * rcv
Definition tree-mpi.h:24
void(* destroy)(Boundary *b)
Definition boundaries.h:8
void(* restriction)(const Boundary *b, scalar *list, int l)
Definition boundaries.h:11
void(* level)(const Boundary *b, scalar *list, int l)
Definition boundaries.h:9
int i
Definition common.h:44
scalar nt
Definition terrain.h:17
trace void tree_check()
void coarsen_cell_recursive(Point point, scalar *list)
bool coarsen_cell(Point point, scalar *list)
int refine_cell(Point point, scalar *list, int flag, Cache *refined)
Definition tree-common.h:23
static Boundary * mpi_boundary
Definition tree-mpi.h:154
static void rcv_pid_sync(SndRcv *m, scalar *list, int l)
Definition tree-mpi.h:444
static void rcv_pid_receive(RcvPid *m, scalar *list, scalar *listv, vector *listf, int l)
Definition tree-mpi.h:313
static int locals_pids(Point point, Array *pids)
Definition tree-mpi.h:734
static void snd_rcv_init(SndRcv *m, const char *name)
Definition tree-mpi.h:471
static void rcv_pid_print(RcvPid *p, FILE *fp, const char *prefix)
Definition tree-mpi.h:139
static void check_depth()
Definition tree-mpi.h:1090
void mpi_boundary_new()
Definition tree-mpi.h:508
#define is_remote(cell)
Definition tree-mpi.h:724
trace void mpi_boundary_update_buffers()
Definition tree-mpi.h:860
static void cache_level_init(CacheLevel *c)
Definition tree-mpi.h:34
trace void mpi_boundary_refine(scalar *list)
Definition tree-mpi.h:1020
static void rcv_pid_append(RcvPid *p, int pid, Point point)
Definition tree-mpi.h:109
static bool is_local_prolongation(Point point, Point p)
Definition tree-mpi.h:708
static trace void mpi_boundary_level(const Boundary *b, scalar *list, int l)
Definition tree-mpi.h:494
trace void mpi_boundary_coarsen(int l, int too_fine)
Definition tree-mpi.h:1132
static void append_pid(Array *pids, int pid)
Definition tree-mpi.h:726
#define BOUNDARY_TAG(level)
Definition tree-mpi.h:156
static void rcv_destroy(Rcv *rcv)
Definition tree-mpi.h:72
static void rcv_pid_destroy(RcvPid *p)
Definition tree-mpi.h:145
static Rcv * rcv_pid_pointer(RcvPid *p, int pid)
Definition tree-mpi.h:88
static RcvPid * rcv_pid_new(const char *name)
Definition tree-mpi.h:81
static trace void rcv_pid_wait(RcvPid *m)
Definition tree-mpi.h:368
#define REFINE_TAG()
Definition tree-mpi.h:158
void debug_mpi(FILE *fp1)
Definition tree-mpi.h:540
static int list_lenb(scalar *list)
Definition tree-mpi.h:299
static void rcv_pid_send(RcvPid *m, scalar *list, scalar *listv, vector *listf, int l)
Definition tree-mpi.h:375
void check_snd_rcv_matrix(SndRcv *sndrcv, const char *name)
Definition tree-mpi.h:787
void rcv_pid_write(RcvPid *p, const char *name)
Definition tree-mpi.h:127
trace void mpi_partitioning()
Definition tree-mpi.h:1255
static void mpi_boundary_destroy(Boundary *b)
Definition tree-mpi.h:482
static void apply_bc(Rcv *rcv, scalar *list, scalar *listv, vector *listf, int l, MPI_Status s)
Definition tree-mpi.h:163
static void snd_rcv_destroy(SndRcv *m)
Definition tree-mpi.h:465
static int vectors_lenb(vector *list)
Definition tree-mpi.h:306
static void mpi_recv_check(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status, const char *name)
Definition tree-mpi.h:236
static bool has_local_child(Point point)
Definition tree-mpi.h:851
static FILE * fopen_prefix(FILE *fp, const char *name, char *prefix)
Definition tree-mpi.h:523
static void flag_border_cells()
Definition tree-mpi.h:1200
static trace void mpi_boundary_restriction(const Boundary *b, scalar *list, int l)
Definition tree-mpi.h:502
static bool is_root(Point point)
Definition tree-mpi.h:698
void restore_mpi(FILE *fp, scalar *list1)
Definition tree-mpi.h:1297
static void snd_rcv_free(SndRcv *p)
Definition tree-mpi.h:687
#define REMOTE()
Definition tree-mpi.h:1129
static int balanced_pid(long index, long nt, int nproc)
Definition tree-mpi.h:1244
void rcv_print(Rcv *rcv, FILE *fp, const char *prefix)
Definition tree-mpi.h:53
static void rcv_pid_row(RcvPid *m, int l, int *row)
Definition tree-mpi.h:776
trace double z_indexing(scalar index, bool leaves)
Definition tree-mpi.h:1443
static trace int mpi_waitany(int count, MPI_Request array_of_requests[], int *indx, MPI_Status *status)
Definition tree-mpi.h:293
static int root_pids(Point point, Array *pids)
Definition tree-mpi.h:762
static void rcv_pid_append_pids(RcvPid *p, Array *pids)
Definition tree-mpi.h:114
int debug_iteration
Definition tree-mpi.h:4
static void rcv_append(Point point, Rcv *rcv)
Definition tree-mpi.h:40
static void rcv_free_buf(Rcv *rcv)
Definition tree-mpi.h:61
def is_refined_check()((!is_leaf(cell) &&cell .neighbors &&cell .pid >=0) &&point.i > 0 &&point.i<(1<< level)+2 *2 - 1 &&point.j > 0 &&point.j<(1<< level)+2 *2 - 1) @ macro2 for(int _i=0
static void cache_level_append(CacheLevel *c, Point p)
Definition tree.h:190
def allocated(k, l, n)(mem_allocated(((Tree *) grid) -> L[point.level]->m, point.i+k, point.j+l)) @ @def NEIGHBOR(k, l, n)(((((Tree *) grid) ->L[point.level]->m) ->b[point.i+k][point.j+l])) @ @def PARENT(k, l, n)(((((Tree *) grid) ->L[point.level-1]->m) ->b[(point.i+2)/2+k][(point.j+2)/2+l])) @ @def allocated_child(k, l, n)(level< depth() &&mem_allocated(((Tree *) grid) ->L[point.level+1]->m, 2 *point.i- 2+k, 2 *point.j- 2+l)) @ @def CHILD(k, l, n)(((((Tree *) grid) ->L[point.level+1]->m) ->b[2 *point.i- 2+k][2 *point.j- 2+l])) @ @define CELL(m)(*((Cell *)(m))) @define depth()(grid->depth) @define aparent(k, l, n) CELL(PARENT(k, l, n)) @define child(k, l, n) CELL(CHILD(k, l, n)) @define cell CELL(NEIGHBOR(0, 0, 0)) @define neighbor(k, l, n) CELL(NEIGHBOR(k, l, n)) @def neighborp(l, m, n)(Point)
Definition tree.h:253
#define foreach_halo(type, l)
Definition tree.h:514
#define is_refined(cell)
Definition tree.h:410
#define tree
Definition tree.h:184
@ user
Definition tree.h:63
@ leaf
Definition tree.h:60
@ border
Definition tree.h:61
foreach_cache_level(_boundary, _l, reductions)
Definition tree.h:487
Array * index
scalar c
Definition vof.h:57
src vof fflush(ferr)