1
/*============================================================================
2
* Handle boxes aligned with Cartesian axes.
3
*===========================================================================*/
6
This file is part of Code_Saturne, a general-purpose CFD tool.
8
Copyright (C) 1998-2011 EDF S.A.
10
This program is free software; you can redistribute it and/or modify it under
11
the terms of the GNU General Public License as published by the Free Software
12
Foundation; either version 2 of the License, or (at your option) any later
15
This program is distributed in the hope that it will be useful, but WITHOUT
16
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
20
You should have received a copy of the GNU General Public License along with
21
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22
Street, Fifth Floor, Boston, MA 02110-1301, USA.
25
/*----------------------------------------------------------------------------*/
27
#if defined(HAVE_CONFIG_H)
28
#include "cs_config.h"
31
/*----------------------------------------------------------------------------
32
* Standard C library headers
33
*---------------------------------------------------------------------------*/
42
/*----------------------------------------------------------------------------
44
*---------------------------------------------------------------------------*/
47
#include <bft_timer.h>
48
#include <bft_printf.h>
50
/*----------------------------------------------------------------------------
52
*---------------------------------------------------------------------------*/
54
#include "fvm_config_defs.h"
55
#include "fvm_parall.h"
57
/*----------------------------------------------------------------------------
58
* Header for the current file
59
*---------------------------------------------------------------------------*/
62
#include "fvm_box_priv.h"
64
/*---------------------------------------------------------------------------*/
69
} /* Fake brace to force Emacs auto-indentation back to column 0 */
71
#endif /* __cplusplus */
73
/*=============================================================================
74
* Local Macro definitions
75
*===========================================================================*/
77
/*============================================================================
78
* Type and structure definitions
79
*===========================================================================*/
81
/*============================================================================
82
* Private function definitions
83
*===========================================================================*/
87
/*----------------------------------------------------------------------------
88
* Display a histogram on leaves associated to the boxes and several
89
* other pieces of information (min, max, ...)
92
* distrib <-- pointer to the fvm_box_distrib_t structure
93
* n_quantiles <-> number of quantiles requested (or NULL);
94
* may be lower upon return
95
* quantile_start --> start of quantile (size: n_quantiles + 1)
96
* n_quantile_boxes --> number of boxes per quantile (size: n_quantiles)
97
* imbalance --> distribution imbalance measure (or NULL)
98
* n_ranks --> number of ranks with boxes (or NULL)
99
* comm <-- associated MPI communicator
100
*---------------------------------------------------------------------------*/
103
_get_distrib_statistics(const fvm_box_distrib_t *distrib,
104
fvm_lnum_t *n_quantiles,
105
fvm_lnum_t quantile_start[],
106
fvm_lnum_t n_quantile_boxes[],
111
fvm_lnum_t i, j, k, step, delta, _n_rank_boxes;
114
fvm_lnum_t _min = INT_MAX, _max = 0, gmin = 0, gmax = 0;
118
assert(distrib != NULL);
119
assert(distrib->index != NULL);
121
if (n_quantiles != NULL) {
123
fvm_lnum_t _n_quantiles = 0;
125
/* Get global min and max number of boxes */
127
for (i = 0; i < distrib->n_ranks; i++) {
129
_n_rank_boxes = distrib->index[i+1] - distrib->index[i];
130
_min = FVM_MIN(_min, _n_rank_boxes);
131
_max = FVM_MAX(_max, _n_rank_boxes);
133
if (_n_rank_boxes > 0)
141
MPI_Allreduce(&_min, &gmin, 1, FVM_MPI_LNUM, MPI_MIN, comm);
142
MPI_Allreduce(&_max, &gmax, 1, FVM_MPI_LNUM, MPI_MAX, comm);
144
/* Build a histogram for the distribution of boxes */
147
if (delta < _n_quantiles)
148
_n_quantiles = delta;
150
/* Define quantiles */
152
step = delta / _n_quantiles;
153
if (delta % _n_quantiles > 0)
156
for (i = 0; i < _n_quantiles; i++)
157
quantile_start[i] = gmin + i*step;
159
quantile_start[_n_quantiles] = gmax + 1;
161
/* Count for quantiles */
163
for (j = 0; j < _n_quantiles; j++)
164
n_quantile_boxes[j] = 0;
166
if (delta > 0) { /* Loop on boxes */
168
for (i = 0; i < distrib->n_ranks; i++) {
170
_n_rank_boxes = distrib->index[i+1] - distrib->index[i];
172
for (k = 1; k < _n_quantiles; k++) {
173
if (_n_rank_boxes < gmin + k*step)
176
n_quantile_boxes[k-1] += 1;
178
} /* End of loop on boxes */
182
*n_quantiles = _n_quantiles;
185
/* Set other return values */
187
if (imbalance != NULL)
188
*imbalance = distrib->fit;
194
#endif /* defined(HAVE_MPI) */
196
/*============================================================================
197
* Public function definitions
198
*===========================================================================*/
200
/*----------------------------------------------------------------------------
201
* Create a set of boxes and initialize it.
204
* dim <-- spatial dimension
205
* normalize <-- 1 if boxes are to be normalized, 0 otherwize
206
* allow_projection <-- if 1, project to lower dimension if all boxes
207
* are cut by the median plane of the set.
208
* n_boxes <-- number of elements to create
209
* box_gnum <-- global numbering of boxes
210
* extents <-- coordinate extents (size: n_boxes*dim*2, as
211
* xmin1, ymin1, .. xmax1, ymax1, ..., xmin2, ...)
212
* comm <-- associated MPI communicator
215
* a new allocated pointer to a fvm_box_set_t structure.
216
*---------------------------------------------------------------------------*/
218
#if defined(HAVE_MPI)
220
fvm_box_set_create(int dim,
222
int allow_projection,
224
const fvm_gnum_t *box_gnum,
225
const fvm_coord_t *box_extents,
229
fvm_box_set_create(int dim,
231
int allow_projection,
233
const fvm_gnum_t *box_gnum,
234
const fvm_coord_t *box_extents)
239
fvm_gnum_t n_g_boxes = n_boxes;
240
fvm_coord_t g_min[3], g_max[3], g_extents[6];
242
fvm_box_set_t *boxes = NULL;
244
/* Get global min/max coordinates */
246
#if defined(HAVE_MPI)
247
fvm_morton_get_global_extents(dim, n_boxes, box_extents, g_extents, comm);
249
fvm_morton_get_global_extents(dim, n_boxes, box_extents, g_extents);
252
for (j = 0; j < 3; j++) {
253
g_min[j] = g_extents[j];
254
g_max[j] = g_extents[j+dim];
257
#if defined(HAVE_MPI)
259
if (comm != MPI_COMM_NULL) {
261
fvm_gnum_t box_max = 0;
263
for (i = 0; i < n_boxes; i++)
264
box_max = FVM_MAX(box_max, box_gnum[i]);
266
MPI_Allreduce(&box_max, &n_g_boxes, 1, FVM_MPI_GNUM, MPI_MAX, comm);
272
/* Allocate box set structure and initialize it */
274
BFT_MALLOC(boxes, 1, fvm_box_set_t);
277
boxes->n_boxes = n_boxes;
278
boxes->n_g_boxes = n_g_boxes;
280
for (j = 0; j < 3; j++) {
281
boxes->dimensions[j] = j;
282
boxes->gmin[j] = g_min[j];
283
boxes->gmax[j] = g_max[j];
287
boxes->extents = NULL;
289
#if defined(HAVE_MPI)
293
/* Optionally allow and detect a layout of lower
294
dimension than the spatial dimension */
296
if (allow_projection) {
299
int proj[] = {1, 1, 1};
301
for (j = 0; j < dim; j++)
302
g_mid[j] = (g_min[j] + g_max[j]) * 0.5;
304
for (i = 0; i < n_boxes; i++) {
305
for (j = 0; j < dim; j++) {
306
if ( box_extents[i*dim*2 + j] > g_mid[j]
307
|| box_extents[i*dim*2 + j+dim] < g_mid[j])
312
#if defined(HAVE_MPI)
313
if (comm != MPI_COMM_NULL) {
315
for (j = 0; j < dim; j++)
317
MPI_Allreduce(l_proj, proj, dim, MPI_INT, MPI_MIN, comm);
322
for (j = 0; j < dim; j++) {
324
boxes->dimensions[boxes->dim] = j;
332
for (j = boxes->dim; j < 3; j++) /* ensure all is initialized */
333
boxes->dimensions[j] = -1;
335
/* Now assign values */
337
BFT_MALLOC(boxes->g_num, n_boxes, fvm_gnum_t);
338
BFT_MALLOC(boxes->extents, n_boxes*boxes->dim*2, fvm_coord_t);
340
for (i = 0; i < n_boxes; i++) {
342
fvm_coord_t *_min = boxes->extents + (boxes->dim*2*i);
343
fvm_coord_t *_max = _min + boxes->dim;
345
boxes->g_num[i] = box_gnum[i];
347
for (j = 0; j < boxes->dim; j++) {
348
k = boxes->dimensions[j];
349
_min[j] = box_extents[i*dim*2 + k];
350
_max[j] = box_extents[i*dim*2 + k+dim];
351
assert(_min[j] <= _max[j]);
355
/* Define the normalized min/max coordinates of the box */
359
fvm_coord_t d[3], s[3];
361
for (j = 0; j < boxes->dim; j++) {
362
k = boxes->dimensions[j];
364
d[j] = g_max[k] - g_min[k];
367
for (i = 0; i < n_boxes; i++) {
369
fvm_coord_t *_min = boxes->extents + (boxes->dim*2*i);
370
fvm_coord_t *_max = _min + boxes->dim;
372
for (j = 0; j < boxes->dim; j++) {
373
_min[j] = (_min[j] - s[j]) / d[j];
374
_max[j] = (_max[j] - s[j]) / d[j];
380
/* Return pointer to structure */
385
/*----------------------------------------------------------------------------
386
* Delete a fvm_box_set_t structure.
389
* boxes <-> pointer to the fvm_box_set_t structure to delete
390
*---------------------------------------------------------------------------*/
393
fvm_box_set_destroy(fvm_box_set_t **boxes)
397
fvm_box_set_t *_boxes = *boxes;
402
BFT_FREE(_boxes->g_num);
403
BFT_FREE(_boxes->extents);
408
/*----------------------------------------------------------------------------
409
* Return the dimension associated with a set of boxes.
412
* boxes <-- pointer to set of boxes
415
* associated spatial dimension
416
*---------------------------------------------------------------------------*/
419
fvm_box_set_get_dim(const fvm_box_set_t *boxes)
429
/*----------------------------------------------------------------------------
430
* Return the local number of boxes in a set.
433
* boxes <-- pointer to set of boxes
436
* local number of boxes
437
*---------------------------------------------------------------------------*/
440
fvm_box_set_get_size(const fvm_box_set_t *boxes)
442
fvm_lnum_t retval = 0;
445
retval = boxes->n_boxes;
450
/*----------------------------------------------------------------------------
451
* Return the global number of boxes in a set.
454
* boxes <-- pointer to set of boxes
457
* global number of boxes
458
*---------------------------------------------------------------------------*/
461
fvm_box_set_get_global_size(const fvm_box_set_t *boxes)
463
fvm_gnum_t retval = 0;
466
retval = boxes->n_g_boxes;
471
/*----------------------------------------------------------------------------
472
* Return extents associated with a set of boxes.
474
* The extents array is organized in the following fashion:
475
* {x_min_0, y_min_0, ..., x_max_0, y_max_0, ...
476
* x_min_n, y_min_n, ..., x_max_n, y_max_n, ...}
478
* Its size is thus: n_boxes * dim * 2.
481
* boxes <-- pointer to set of boxes
484
* pointer to extents array
485
*---------------------------------------------------------------------------*/
488
fvm_box_set_get_extents(fvm_box_set_t *boxes)
490
assert(boxes != NULL);
492
return boxes->extents;
495
/*----------------------------------------------------------------------------
496
* Return global numbers associated with a set of boxes.
499
* boxes <-- pointer to set of boxes
502
* pointer to global box numbers array
503
*---------------------------------------------------------------------------*/
506
fvm_box_set_get_g_num(fvm_box_set_t *boxes)
508
assert(boxes != NULL);
513
/*----------------------------------------------------------------------------
514
* Build a Morton_index to get a well-balanced distribution of the boxes.
517
* boxes <-- pointer to associated fvm_box_set_t structure
518
* distrib <-> pointer to a fvm_box_distrib_t structure
519
* n_leaves <-- number of leaves with weight > 0
520
* leaf_codes <-- Morton code for each leaf
521
* weight <-- number of boxes related to each leaf
522
*---------------------------------------------------------------------------*/
525
fvm_box_set_build_morton_index(const fvm_box_set_t *boxes,
526
fvm_box_distrib_t *distrib,
528
fvm_morton_code_t *leaf_codes,
531
#if defined(HAVE_MPI)
533
fvm_lnum_t *order = NULL;
535
assert(distrib != NULL);
536
assert(distrib->morton_index != NULL);
538
BFT_MALLOC(order, n_leaves, fvm_lnum_t);
540
/* Locally order Morton encoding */
542
fvm_morton_local_order(n_leaves,
546
/* Compute a Morton index on ranks and return the associated fit */
548
if (boxes->comm != MPI_COMM_NULL)
549
distrib->fit = fvm_morton_build_rank_index(boxes->dim,
555
distrib->morton_index,
564
/*----------------------------------------------------------------------------
565
* Redistribute boxes over the ranks according to the Morton index to
566
* assume a better balanced distribution of the boxes.
569
* distrib <-- data structure on box distribution
570
* boxes <-> pointer to the structure to redistribute
571
*---------------------------------------------------------------------------*/
574
fvm_box_set_redistribute(const fvm_box_distrib_t *distrib,
575
fvm_box_set_t *boxes)
577
#if defined(HAVE_MPI)
582
int *send_count = NULL, *send_shift = NULL;
583
int *recv_count = NULL, *recv_shift = NULL;
584
fvm_gnum_t *send_g_num = NULL;
585
fvm_coord_t *send_extents = NULL;
587
const int stride = boxes->dim * 2;
591
assert(distrib != NULL);
592
assert(boxes != NULL);
593
assert(distrib->n_ranks > 1);
595
/* Build send_buf, send_count and send_shift
596
to build a rank to boxes indexed list */
598
BFT_MALLOC(send_count, distrib->n_ranks, int);
599
BFT_MALLOC(recv_count, distrib->n_ranks, int);
600
BFT_MALLOC(send_shift, distrib->n_ranks + 1, int);
601
BFT_MALLOC(recv_shift, distrib->n_ranks + 1, int);
603
for (rank_id = 0; rank_id < distrib->n_ranks; rank_id++)
605
= distrib->index[rank_id+1] - distrib->index[rank_id];
607
/* Exchange number of boxes to send to each process */
609
MPI_Alltoall(send_count, 1, MPI_INT,
610
recv_count, 1, MPI_INT, boxes->comm);
612
for (i = 0; i < distrib->n_ranks; i++)
613
send_shift[i] = distrib->index[i];
616
for (rank_id = 0; rank_id < distrib->n_ranks; rank_id++)
617
recv_shift[rank_id + 1] = recv_shift[rank_id] + recv_count[rank_id];
619
/* Build send_buffers */
621
BFT_MALLOC(send_g_num, distrib->index[distrib->n_ranks], fvm_gnum_t);
622
BFT_MALLOC(send_extents,
623
distrib->index[distrib->n_ranks] * boxes->dim * 2,
626
for (rank_id = 0; rank_id < distrib->n_ranks; rank_id++)
627
send_count[rank_id] = 0;
629
for (rank_id = 0; rank_id < distrib->n_ranks; rank_id++) {
631
for (i = distrib->index[rank_id];
632
i < distrib->index[rank_id+1];
635
fvm_lnum_t box_id = distrib->list[i];
636
fvm_lnum_t shift = distrib->index[rank_id] + send_count[rank_id];
638
send_g_num[shift] = boxes->g_num[box_id];
640
for (j = 0; j < stride; j++)
641
send_extents[shift*stride + j] = boxes->extents[box_id*stride + j];
643
send_count[rank_id] += 1;
647
} /* End of loop on ranks */
649
/* Prepare to replace the local arrays */
651
boxes->n_boxes = recv_shift[distrib->n_ranks];
652
BFT_FREE(boxes->g_num);
653
BFT_FREE(boxes->extents);
655
BFT_MALLOC(boxes->g_num, boxes->n_boxes, fvm_gnum_t);
656
BFT_MALLOC(boxes->extents, boxes->n_boxes*stride, fvm_coord_t);
658
/* Exchange boxes between processes */
660
MPI_Alltoallv(send_g_num, send_count, send_shift, FVM_MPI_GNUM,
661
boxes->g_num, recv_count, recv_shift, FVM_MPI_GNUM,
664
for (rank_id = 0; rank_id < distrib->n_ranks; rank_id++) {
665
send_count[rank_id] *= stride;
666
send_shift[rank_id] *= stride;
667
recv_count[rank_id] *= stride;
668
recv_shift[rank_id] *= stride;
671
MPI_Alltoallv(send_extents, send_count, send_shift, FVM_MPI_COORD,
672
boxes->extents, recv_count, recv_shift, FVM_MPI_COORD,
677
BFT_FREE(send_g_num);
678
BFT_FREE(send_extents);
679
BFT_FREE(send_count);
680
BFT_FREE(send_shift);
681
BFT_FREE(recv_count);
682
BFT_FREE(recv_shift);
684
#endif /* HAVE_MPI */
687
/*----------------------------------------------------------------------------
688
* Dump a fvm_box_set_t structure.
691
* boxes <-- pointer to the fvm_box_t structure
692
* verbosity <-- verbosity level (0 or 1)
693
*----------------------------------------------------------------------------*/
696
fvm_box_set_dump(const fvm_box_set_t *boxes,
701
const char XYZ[3] = "XYZ";
706
/* Print basic information */
709
bft_printf("\nBox set (3D layout):\n\n"
710
"global min/max on selected faces:\n"
711
" [%7.5e %7.5e %7.5e] --> [%7.5e %7.5e %7.5e]\n",
712
boxes->gmin[0], boxes->gmin[1], boxes->gmin[2],
713
boxes->gmax[0], boxes->gmax[1], boxes->gmax[2]);
715
else if (boxes->dim == 2) {
716
bft_printf("\nBox set (2D layout, selected axes [%c, %c]\n\n",
717
XYZ[boxes->dimensions[0]],
718
XYZ[boxes->dimensions[1]]);
719
bft_printf("global min/max on selected faces:\n"
720
" [%7.5e %7.5e] --> [%7.5e %7.5e]\n",
721
boxes->gmin[boxes->dimensions[0]],
722
boxes->gmin[boxes->dimensions[1]],
723
boxes->gmax[boxes->dimensions[0]],
724
boxes->gmax[boxes->dimensions[1]]);
727
else if (boxes->dim == 1) {
728
bft_printf("\nBox set (1D layout, selected axis [%c]\n\n",
729
XYZ[boxes->dimensions[0]]);
730
bft_printf("global min/max on selected faces:\n"
731
" [%7.5e %7.5e] --> [%7.5e %7.5e]\n",
732
boxes->gmin[boxes->dimensions[0]],
733
boxes->gmin[boxes->dimensions[1]],
734
boxes->gmax[boxes->dimensions[0]],
735
boxes->gmax[boxes->dimensions[1]]);
739
/* Print detailed box information */
744
if (boxes->dim == 3) {
745
for (i = 0; i < boxes->n_boxes; i++) {
746
const fvm_coord_t *bmin = boxes->extents + i*6;
747
const fvm_coord_t *bmax = boxes->extents + i*6 + 3;
748
bft_printf(" id %8d, num %9llu: "
749
"[%7.5e %7.5e %7.5e] --> [%7.5e %7.5e %7.5e]\n",
750
i, (unsigned long long)(boxes->g_num[i]),
751
bmin[0], bmin[1], bmin[2],
752
bmax[0], bmax[1], bmax[2]);
756
else if (boxes->dim == 2) {
757
for (i = 0; i < boxes->n_boxes; i++) {
758
const fvm_coord_t *bmin = boxes->extents + i*4;
759
const fvm_coord_t *bmax = boxes->extents + i*4 + 2;
760
bft_printf(" id %8d, num %9llu: "
761
"[%7.5e %7.5e] --> [%7.5e %7.5e]\n",
762
i, (unsigned long long)(boxes->g_num[i]),
763
bmin[0], bmin[1], bmax[0], bmax[1]);
767
else if (boxes->dim == 1) {
768
for (i = 0; i < boxes->n_boxes; i++) {
769
const fvm_coord_t *bmin = boxes->extents + i*2;
770
const fvm_coord_t *bmax = boxes->extents + i*2 + 1;
771
bft_printf(" id %8d, num %9llu: "
772
"[%7.5e] --> [%7.5e]\n",
773
i, (unsigned long long)(boxes->g_num[i]),
780
for (i = 0; i < boxes->n_boxes; i++) {
782
const fvm_coord_t *bmin = boxes->extents + boxes->dim*2*i;
783
const fvm_coord_t *bmax = boxes->extents + boxes->dim*(2*i + 1);
784
for (j = 0; j < boxes->dim; j++) {
785
if (bmin[j] > bmax[j])
786
bft_error(__FILE__, __LINE__, 0,
787
_("Inconsistent box found (min > max):\n"
788
" global number: %u\n"
791
boxes->g_num[i], bmin[j], bmax[j]);
797
#if defined(HAVE_MPI)
799
/*----------------------------------------------------------------------------
800
* Create a fvm_box_distrib_t structure.
803
* n_boxes <-- number of boxes
804
* n_g_boxes <-- global number of boxes
805
* max_level <-- max level reached locally in the related tree
806
* comm <-- MPI communicator. on which the distribution takes place
809
* a pointer to a new allocated fvm_box_distrib_t structure.
810
*---------------------------------------------------------------------------*/
813
fvm_box_distrib_create(fvm_lnum_t n_boxes,
814
fvm_gnum_t n_g_boxes,
818
int i, n_ranks, gmax_level;
820
fvm_box_distrib_t *new_distrib = NULL;
825
BFT_MALLOC(new_distrib, 1, fvm_box_distrib_t);
827
/* Parallel parameters */
829
MPI_Comm_size(comm, &n_ranks);
831
new_distrib->n_ranks = n_ranks;
833
new_distrib->n_boxes = n_boxes;
837
BFT_MALLOC(new_distrib->morton_index, n_ranks + 1, fvm_morton_code_t);
839
MPI_Allreduce(&max_level, &gmax_level, 1, MPI_INT, MPI_MAX, comm);
841
new_distrib->max_level = gmax_level;
842
new_distrib->fit = 999.0;
844
BFT_MALLOC(new_distrib->index, n_ranks + 1, fvm_lnum_t);
846
for (i = 0; i < n_ranks + 1; i++)
847
new_distrib->index[i] = 0;
849
new_distrib->list = NULL;
854
/*----------------------------------------------------------------------------
855
* Destroy a fvm_box_distrib_t structure.
858
* distrib <-> pointer to pointer to the structure to destroy
859
*---------------------------------------------------------------------------*/
862
fvm_box_distrib_destroy(fvm_box_distrib_t **distrib)
864
if (distrib != NULL) {
866
fvm_box_distrib_t *d = *distrib;
873
BFT_FREE(d->morton_index);
879
/*----------------------------------------------------------------------------
880
* Delete redundancies in box distribution
883
* distrib <-> pointer to the fvm_box_distrib_t structure
884
*---------------------------------------------------------------------------*/
887
fvm_box_distrib_clean(fvm_box_distrib_t *distrib)
891
fvm_lnum_t *counter = NULL, *new_index = NULL;
893
BFT_MALLOC(counter, distrib->n_boxes, fvm_lnum_t);
894
BFT_MALLOC(new_index, distrib->n_ranks + 1, fvm_lnum_t);
896
for (i = 0; i < distrib->n_ranks + 1; i++)
899
for (rank = 0; rank < distrib->n_ranks; rank++) {
901
fvm_lnum_t shift = new_index[rank];
902
fvm_lnum_t start = distrib->index[rank];
903
fvm_lnum_t end = distrib->index[rank + 1];
905
if (end - start > 0) {
907
for (i = 0; i < distrib->n_boxes; i++)
910
for (i = start; i < end; i++)
911
counter[distrib->list[i]] += 1;
913
for (i = 0; i < distrib->n_boxes; i++) {
916
distrib->list[shift++] = i;
920
} /* end if end - start > 0 */
922
new_index[rank+1] = shift;
924
} /* End of loop on ranks */
926
/* Memory management */
928
BFT_FREE(distrib->index);
929
BFT_REALLOC(distrib->list, new_index[distrib->n_ranks], fvm_lnum_t);
931
distrib->index = new_index;
936
/*----------------------------------------------------------------------------
937
* Display a histogram on leaves associated to the boxes and several
938
* other pieces of information (min, max, ...)
941
* distrib <-- pointer to the fvm_box_distrib_t structure
942
* comm <-- associated MPI communicator
943
*---------------------------------------------------------------------------*/
946
fvm_box_distrib_dump_statistics(const fvm_box_distrib_t *distrib,
952
fvm_lnum_t n_quantiles = 5;
953
fvm_lnum_t quantile_start[6];
954
fvm_lnum_t n_boxes[5];
958
assert(distrib != NULL);
959
assert(distrib->index != NULL);
961
_get_distrib_statistics(distrib,
970
"- Box distribution statistics -\n\n");
972
bft_printf(" Distribution imbalance: %10.4g\n",
974
bft_printf(" Number of ranks in distribution: %8d\n\n",
977
/* Print histogram to show the distribution of boxes */
979
if (n_quantiles > 0) {
981
for (i = 0; i < n_quantiles - 1; i++)
982
bft_printf(" %3d : [ %10d ; %10d [ = %10d\n",
983
i+1, quantile_start[i], quantile_start[i+1], n_boxes[i]);
986
bft_printf(" %3d : [ %10d ; %10d ] = %10d\n",
987
i+1, quantile_start[i], quantile_start[i+1] - 1, n_boxes[i]);
993
#endif /* defined(HAVE_MPI) */
995
/*---------------------------------------------------------------------------*/
999
#endif /* __cplusplus */