PLUTO
al_subarray_.c
Go to the documentation of this file.
1 /* ///////////////////////////////////////////////////////////////////// */
2 /*!
3  \file
4  \brief Creates a datatype describing a subarray of a
5  multidimensional array
6 
7  Creates a datatype describing a subarray of a
8  multidimensional array
9 
10  \authors A. Malagoli (University of Chicago)
11 
12  \date Jul 17, 1999
13 */
14 /* ///////////////////////////////////////////////////////////////////// */
15 #include "al_hidden.h"
16 
17 /* ********************************************************************* */
18 int AL_Type_create_subarray(int ndims, int *array_of_sizes,
19  int *array_of_subsizes, int *array_of_starts,
20  int order, MPI_Datatype oldtype,
21  MPI_Datatype *newtype)
22 /*!
23  * Creates a datatype describing a subarray of a multidimensional array
24  * NOTE:
25  * This routine has been modified from R. Thakur's ROMIO implementation
26  * of MPI_Type_create_subarry. The reason for keeping a local copy is
27  * mainly to reduce this package's dependence on ROMIO. It only affects
28  * the non I/O components of the library (e.g. AL_Allgather).
29  *
30  * \param [in] ndims number of array dimensions
31  * \param [in] array_of_sizes number of elements of type
32  * oldtype in each dimension of the
33  * full array
34  * \param [in] array_of_subsizes number of elements of type
35  * oldtype in each dimension of the
36  * subarray
37  * \param [in] array_of_starts starting coordinates of the subarray
38  * in each dimension
39  * \param [in] order array storage order flag
40  * \param [in] oldtype old datatype (handle)
41  * \param [out] newtype new datatype (handle)
42  *********************************************************************** */
43 {
44  MPI_Aint extent, disps[AL_MAX_DIM], size, size_with_aint;
45  int i, blklens[AL_MAX_DIM];
46  MPI_Datatype tmp1, tmp2, types[AL_MAX_DIM];
47  MPI_Offset size_with_offset;
48 
49  if (ndims <= 0) {
50  printf("MPI_Type_create_subarray: Invalid ndims argument\n");
51  MPI_Abort(MPI_COMM_WORLD, 1);
52  }
53  if (array_of_sizes <= (int *) 0) {
54  printf("MPI_Type_create_subarray: array_of_sizes is an invalid address\n");
55  MPI_Abort(MPI_COMM_WORLD, 1);
56  }
57  if (array_of_subsizes <= (int *) 0) {
58  printf("MPI_Type_create_subarray: array_of_subsizes is an invalid address\n");
59  MPI_Abort(MPI_COMM_WORLD, 1);
60  }
61  if (array_of_starts <= (int *) 0) {
62  printf("MPI_Type_create_subarray: array_of_starts is an invalid address\n");
63  MPI_Abort(MPI_COMM_WORLD, 1);
64  }
65 
66  for (i=0; i<ndims; i++) {
67  if (array_of_sizes[i] <= 0) {
68  printf("MPI_Type_create_subarray: Invalid value in array_of_sizes\n");
69  MPI_Abort(MPI_COMM_WORLD, 1);
70  }
71  if (array_of_subsizes[i] <= 0) {
72  printf("MPI_Type_create_subarray: Invalid value in array_of_subsizes\n");
73  MPI_Abort(MPI_COMM_WORLD, 1);
74  }
75  if (array_of_starts[i] < 0) {
76  printf("MPI_Type_create_subarray: Invalid value in array_of_starts\n");
77  MPI_Abort(MPI_COMM_WORLD, 1);
78  }
79  }
80 
81  /* order argument checked below */
82 
83  if (oldtype == MPI_DATATYPE_NULL) {
84  printf("MPI_Type_create_subarray: oldtype is an invalid datatype\n");
85  MPI_Abort(MPI_COMM_WORLD, 1);
86  }
87 
88  MPI_Type_extent(oldtype, (MPI_Aint *) &extent);
89 
90 /* check if MPI_Aint is large enough for size of global array.
91  if not, complain. */
92 
93  size_with_aint = extent;
94  for (i=0; i<ndims; i++) size_with_aint *= array_of_sizes[i];
95  size_with_offset = extent;
96  for (i=0; i<ndims; i++) size_with_offset *= array_of_sizes[i];
97  if (size_with_aint != size_with_offset) {
98  printf("MPI_Type_create_subarray: Can't use an array of this size unless the MPI implementation defines a 64-bit MPI_Aint\n");
99  MPI_Abort(MPI_COMM_WORLD, 1);
100  }
101 
102  if (order == AL_ORDER_FORTRAN) {
103  /* dimension 0 changes fastest */
104  if (ndims == 1)
105  MPI_Type_contiguous(array_of_subsizes[0], oldtype, &tmp1);
106  else {
107  MPI_Type_vector(array_of_subsizes[1], array_of_subsizes[0],
108  array_of_sizes[0], oldtype, &tmp1);
109 
110  size = array_of_sizes[0]*extent;
111  for (i=2; i<ndims; i++) {
112  size *= array_of_sizes[i-1];
113  MPI_Type_hvector(array_of_subsizes[i], 1, size, tmp1, &tmp2);
114  MPI_Type_free(&tmp1);
115  tmp1 = tmp2;
116  }
117  }
118 
119  /* add displacement and UB */
120 
121  disps[1] = array_of_starts[0];
122  size = 1;
123  for (i=1; i<ndims; i++) {
124  size *= array_of_sizes[i-1];
125  disps[1] += size*array_of_starts[i];
126  }
127  /* rest done below for both Fortran and C order */
128  }
129 
130  else if (order == AL_ORDER_C) {
131  /* dimension ndims-1 changes fastest */
132  if (ndims == 1)
133  MPI_Type_contiguous(array_of_subsizes[0], oldtype, &tmp1);
134  else {
135  MPI_Type_vector(array_of_subsizes[ndims-2],
136  array_of_subsizes[ndims-1],
137  array_of_sizes[ndims-1], oldtype, &tmp1);
138 
139  size = array_of_sizes[ndims-1]*extent;
140  for (i=ndims-3; i>=0; i--) {
141  size *= array_of_sizes[i+1];
142  MPI_Type_hvector(array_of_subsizes[i], 1, size, tmp1, &tmp2);
143  MPI_Type_free(&tmp1);
144  tmp1 = tmp2;
145  }
146  }
147 
148  /* add displacement and UB */
149 
150  disps[1] = array_of_starts[ndims-1];
151  size = 1;
152  for (i=ndims-2; i>=0; i--) {
153  size *= array_of_sizes[i+1];
154  disps[1] += size*array_of_starts[i];
155  }
156  }
157  else {
158  printf("MPI_Type_create_subarray: Invalid order argument\n");
159  MPI_Abort(MPI_COMM_WORLD, 1);
160  }
161 
162  disps[1] *= extent;
163 
164  disps[2] = extent;
165  for (i=0; i<ndims; i++) disps[2] *= array_of_sizes[i];
166 
167  disps[0] = 0;
168  blklens[0] = blklens[1] = blklens[2] = 1;
169  types[0] = MPI_LB;
170  types[1] = tmp1;
171  types[2] = MPI_UB;
172 
173  MPI_Type_struct(3, blklens, disps, types, newtype);
174 
175  MPI_Type_free(&tmp1);
176 
177  return MPI_SUCCESS;
178 }
#define AL_MAX_DIM
Definition: al_codes.h:18
#define AL_ORDER_C
Definition: al_codes.h:45
int AL_Type_create_subarray(int ndims, int *array_of_sizes, int *array_of_subsizes, int *array_of_starts, int order, MPI_Datatype oldtype, MPI_Datatype *newtype)
Definition: al_subarray_.c:18
#define AL_ORDER_FORTRAN
Definition: al_codes.h:46
int i
Definition: analysis.c:2
Internal include file for the ArrayLib.