1 /*
2 This file contains routines for basic map object implementation.
3 */
4
5 #include <petsc/private/isimpl.h> /*I "petscis.h" I*/
6
7 /*@
8 PetscLayoutCreate - Allocates `PetscLayout` object
9
10 Collective
11
12 Input Parameter:
13 . comm - the MPI communicator
14
15 Output Parameter:
16 . map - the new `PetscLayout`
17
18 Level: advanced
19
20 Notes:
21 Typical calling sequence
22 .vb
23 PetscLayoutCreate(MPI_Comm,PetscLayout *);
24 PetscLayoutSetBlockSize(PetscLayout,bs);
25 PetscLayoutSetSize(PetscLayout,N); // or PetscLayoutSetLocalSize(PetscLayout,n);
26 PetscLayoutSetUp(PetscLayout);
27 .ve
28 Alternatively,
29 .vb
30 PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
31 .ve
32
33 Optionally use any of the following
34 .vb
35 PetscLayoutGetSize(PetscLayout,PetscInt *);
36 PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
37 PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
38 PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
39 PetscLayoutDestroy(PetscLayout*);
40 .ve
41
42 The `PetscLayout` object and methods are intended to be used in the PETSc `Vec` and `Mat` implementations; it is often not needed in
43 user codes unless you really gain something in their use.
44
45 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
46 `PetscLayout`, `PetscLayoutDestroy()`,
47 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`,
48 `PetscLayoutCreateFromSizes()`
49 @*/
PetscLayoutCreate(MPI_Comm comm,PetscLayout * map)50 PetscErrorCode PetscLayoutCreate(MPI_Comm comm, PetscLayout *map)
51 {
52 PetscFunctionBegin;
53 PetscCall(PetscNew(map));
54 PetscCallMPI(MPI_Comm_size(comm, &(*map)->size));
55 (*map)->comm = comm;
56 (*map)->bs = 1;
57 (*map)->n = -1;
58 (*map)->N = -1;
59 (*map)->range = NULL;
60 (*map)->range_alloc = PETSC_TRUE;
61 (*map)->rstart = 0;
62 (*map)->rend = 0;
63 (*map)->setupcalled = PETSC_FALSE;
64 (*map)->oldn = -1;
65 (*map)->oldN = -1;
66 (*map)->oldbs = -1;
67 PetscFunctionReturn(PETSC_SUCCESS);
68 }
69
70 /*@
71 PetscLayoutCreateFromSizes - Allocates `PetscLayout` object and sets the layout sizes, and sets the layout up.
72
73 Collective
74
75 Input Parameters:
76 + comm - the MPI communicator
77 . n - the local size (or `PETSC_DECIDE`)
78 . N - the global size (or `PETSC_DECIDE`)
79 - bs - the block size (or `PETSC_DECIDE`)
80
81 Output Parameter:
82 . map - the new `PetscLayout`
83
84 Level: advanced
85
86 Note:
87 .vb
88 PetscLayoutCreateFromSizes(comm, n, N, bs, &layout);
89 .ve
90 is a shorthand for
91 .vb
92 PetscLayoutCreate(comm, &layout);
93 PetscLayoutSetLocalSize(layout, n);
94 PetscLayoutSetSize(layout, N);
95 PetscLayoutSetBlockSize(layout, bs);
96 PetscLayoutSetUp(layout);
97 .ve
98
99 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
100 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromRanges()`
101 @*/
PetscLayoutCreateFromSizes(MPI_Comm comm,PetscInt n,PetscInt N,PetscInt bs,PetscLayout * map)102 PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm, PetscInt n, PetscInt N, PetscInt bs, PetscLayout *map)
103 {
104 PetscFunctionBegin;
105 PetscCall(PetscLayoutCreate(comm, map));
106 PetscCall(PetscLayoutSetLocalSize(*map, n));
107 PetscCall(PetscLayoutSetSize(*map, N));
108 PetscCall(PetscLayoutSetBlockSize(*map, bs));
109 PetscCall(PetscLayoutSetUp(*map));
110 PetscFunctionReturn(PETSC_SUCCESS);
111 }
112
113 /*@
114 PetscLayoutDestroy - Frees a `PetscLayout` object and frees its range if that exists.
115
116 Collective
117
118 Input Parameter:
119 . map - the `PetscLayout`
120
121 Level: developer
122
123 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
124 `PetscLayout`, `PetscLayoutCreate()`,
125 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`
126 @*/
PetscLayoutDestroy(PetscLayout * map)127 PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
128 {
129 PetscFunctionBegin;
130 if (!*map) PetscFunctionReturn(PETSC_SUCCESS);
131 if (!(*map)->refcnt--) {
132 if ((*map)->range_alloc) PetscCall(PetscFree((*map)->range));
133 PetscCall(ISLocalToGlobalMappingDestroy(&(*map)->mapping));
134 PetscCall(PetscFree(*map));
135 }
136 *map = NULL;
137 PetscFunctionReturn(PETSC_SUCCESS);
138 }
139
140 /*@
141 PetscLayoutCreateFromRanges - Creates a new `PetscLayout` with the given ownership ranges and sets it up.
142
143 Collective
144
145 Input Parameters:
146 + comm - the MPI communicator
147 . range - the array of ownership ranges for each rank with length commsize+1
148 . mode - the copy mode for range
149 - bs - the block size (or `PETSC_DECIDE`)
150
151 Output Parameter:
152 . newmap - the new `PetscLayout`
153
154 Level: developer
155
156 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`,
157 `PetscLayoutGetLocalSize()`, `PetscLayout`, `PetscLayoutDestroy()`,
158 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutSetUp()`, `PetscLayoutCreateFromSizes()`
159 @*/
PetscLayoutCreateFromRanges(MPI_Comm comm,const PetscInt range[],PetscCopyMode mode,PetscInt bs,PetscLayout * newmap)160 PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm, const PetscInt range[], PetscCopyMode mode, PetscInt bs, PetscLayout *newmap)
161 {
162 PetscLayout map;
163 PetscMPIInt rank;
164
165 PetscFunctionBegin;
166 PetscCallMPI(MPI_Comm_rank(comm, &rank));
167 PetscCall(PetscLayoutCreate(comm, &map));
168 PetscCall(PetscLayoutSetBlockSize(map, bs));
169 switch (mode) {
170 case PETSC_COPY_VALUES:
171 PetscCall(PetscMalloc1(map->size + 1, &map->range));
172 PetscCall(PetscArraycpy(map->range, range, map->size + 1));
173 break;
174 case PETSC_USE_POINTER:
175 map->range_alloc = PETSC_FALSE; /* fall through */
176 case PETSC_OWN_POINTER:
177 map->range = (PetscInt *)range;
178 break;
179 default:
180 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Received invalid PetscCopyMode somehow");
181 }
182 map->rstart = map->range[rank];
183 map->rend = map->range[rank + 1];
184 map->n = map->rend - map->rstart;
185 map->N = map->range[map->size] - map->range[0];
186 if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */
187 PetscInt tmp;
188 PetscCallMPI(MPIU_Allreduce(&map->n, &tmp, 1, MPIU_INT, MPI_SUM, map->comm));
189 PetscCheck(tmp == map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local lengths %" PetscInt_FMT " does not equal global length %" PetscInt_FMT ", my local length %" PetscInt_FMT ". The provided PetscLayout is wrong.", tmp, map->N, map->n);
190 PetscCheck(map->n % map->bs == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->n, map->bs);
191 PetscCheck(map->N % map->bs == 0, map->comm, PETSC_ERR_PLIB, "Global size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->N, map->bs);
192 }
193 /* lock the layout */
194 map->setupcalled = PETSC_TRUE;
195 map->oldn = map->n;
196 map->oldN = map->N;
197 map->oldbs = map->bs;
198 *newmap = map;
199 PetscFunctionReturn(PETSC_SUCCESS);
200 }
201
202 /*@
203 PetscLayoutSetUp - given a map where you have set either the global or local
204 size sets up the map so that it may be used.
205
206 Collective
207
208 Input Parameter:
209 . map - pointer to the map
210
211 Level: developer
212
213 Notes:
214 Typical calling sequence
215 .vb
216 PetscLayoutCreate(MPI_Comm,PetscLayout *);
217 PetscLayoutSetBlockSize(PetscLayout,1);
218 PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
219 PetscLayoutSetUp(PetscLayout);
220 PetscLayoutGetSize(PetscLayout,PetscInt *);
221 .ve
222
223 If range exists, and local size is not set, everything gets computed from the range.
224
225 If the local size, global size are already set and range exists then this does nothing.
226
227 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutSetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`,
228 `PetscLayout`, `PetscLayoutDestroy()`,
229 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`, `PetscLayoutCreate()`, `PetscSplitOwnership()`
230 @*/
PetscLayoutSetUp(PetscLayout map)231 PetscErrorCode PetscLayoutSetUp(PetscLayout map)
232 {
233 PetscMPIInt rank;
234 PetscInt p;
235
236 PetscFunctionBegin;
237 PetscCheck(!map->setupcalled || !(map->n != map->oldn || map->N != map->oldN), map->comm, PETSC_ERR_ARG_WRONGSTATE, "Layout is already setup with (local=%" PetscInt_FMT ",global=%" PetscInt_FMT "), cannot call setup again with (local=%" PetscInt_FMT ",global=%" PetscInt_FMT ")",
238 map->oldn, map->oldN, map->n, map->N);
239 if (map->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
240
241 PetscCheck(map->n < 0 || map->n % map->bs == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->n, map->bs);
242 PetscCheck(map->N < 0 || map->N % map->bs == 0, map->comm, PETSC_ERR_PLIB, "Global size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT, map->N, map->bs);
243
244 PetscCallMPI(MPI_Comm_rank(map->comm, &rank));
245 if (map->n > 0) map->n = map->n / map->bs;
246 if (map->N > 0) map->N = map->N / map->bs;
247 PetscCall(PetscSplitOwnership(map->comm, &map->n, &map->N));
248 map->n = map->n * map->bs;
249 map->N = map->N * map->bs;
250 if (!map->range) PetscCall(PetscMalloc1(map->size + 1, &map->range));
251 PetscCallMPI(MPI_Allgather(&map->n, 1, MPIU_INT, map->range + 1, 1, MPIU_INT, map->comm));
252
253 map->range[0] = 0;
254 for (p = 2; p <= map->size; p++) map->range[p] += map->range[p - 1];
255
256 map->rstart = map->range[rank];
257 map->rend = map->range[rank + 1];
258
259 /* lock the layout */
260 map->setupcalled = PETSC_TRUE;
261 map->oldn = map->n;
262 map->oldN = map->N;
263 map->oldbs = map->bs;
264 PetscFunctionReturn(PETSC_SUCCESS);
265 }
266
267 /*@
268 PetscLayoutDuplicate - creates a new `PetscLayout` with the same information as a given one. If the `PetscLayout` already exists it is destroyed first.
269
270 Collective
271
272 Input Parameter:
273 . in - input `PetscLayout` to be duplicated
274
275 Output Parameter:
276 . out - the copy
277
278 Level: developer
279
280 Note:
281 `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
282
283 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutReference()`
284 @*/
PetscLayoutDuplicate(PetscLayout in,PetscLayout * out)285 PetscErrorCode PetscLayoutDuplicate(PetscLayout in, PetscLayout *out)
286 {
287 MPI_Comm comm = in->comm;
288
289 PetscFunctionBegin;
290 PetscCall(PetscLayoutDestroy(out));
291 PetscCall(PetscLayoutCreate(comm, out));
292 PetscCall(PetscMemcpy(*out, in, sizeof(struct _n_PetscLayout)));
293 if (in->range) {
294 PetscCall(PetscMalloc1((*out)->size + 1, &(*out)->range));
295 PetscCall(PetscArraycpy((*out)->range, in->range, (*out)->size + 1));
296 }
297 (*out)->refcnt = 0;
298 PetscFunctionReturn(PETSC_SUCCESS);
299 }
300
301 /*@
302 PetscLayoutReference - Causes a PETSc `Vec` or `Mat` to share a `PetscLayout` with one that already exists.
303
304 Collective
305
306 Input Parameter:
307 . in - input `PetscLayout` to be copied
308
309 Output Parameter:
310 . out - the reference location
311
312 Level: developer
313
314 Notes:
315 `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
316
317 If the out location already contains a `PetscLayout` it is destroyed
318
319 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
320 @*/
PetscLayoutReference(PetscLayout in,PetscLayout * out)321 PetscErrorCode PetscLayoutReference(PetscLayout in, PetscLayout *out)
322 {
323 PetscFunctionBegin;
324 in->refcnt++;
325 PetscCall(PetscLayoutDestroy(out));
326 *out = in;
327 PetscFunctionReturn(PETSC_SUCCESS);
328 }
329
330 /*@
331 PetscLayoutSetISLocalToGlobalMapping - sets a `ISLocalGlobalMapping` into a `PetscLayout`
332
333 Collective
334
335 Input Parameters:
336 + in - input `PetscLayout`
337 - ltog - the local to global mapping
338
339 Level: developer
340
341 Notes:
342 `PetscLayoutSetUp()` does not need to be called on the resulting `PetscLayout`
343
344 If the `PetscLayout` already contains a `ISLocalGlobalMapping` it is destroyed
345
346 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutDestroy()`, `PetscLayoutSetUp()`, `PetscLayoutDuplicate()`
347 @*/
PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)348 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in, ISLocalToGlobalMapping ltog)
349 {
350 PetscFunctionBegin;
351 if (ltog) {
352 PetscInt bs;
353
354 PetscCall(ISLocalToGlobalMappingGetBlockSize(ltog, &bs));
355 PetscCheck(in->bs == 1 || bs == 1 || in->bs == bs, in->comm, PETSC_ERR_PLIB, "Blocksize of layout %" PetscInt_FMT " must match that of mapping %" PetscInt_FMT " (or the latter must be 1)", in->bs, bs);
356 }
357 PetscCall(PetscObjectReference((PetscObject)ltog));
358 PetscCall(ISLocalToGlobalMappingDestroy(&in->mapping));
359 in->mapping = ltog;
360 PetscFunctionReturn(PETSC_SUCCESS);
361 }
362
363 /*@
364 PetscLayoutSetLocalSize - Sets the local size for a `PetscLayout` object.
365
366 Collective
367
368 Input Parameters:
369 + map - pointer to the map
370 - n - the local size, pass `PETSC_DECIDE` (the default) to have this value determined by the global size set with `PetscLayoutSetSize()`
371
372 Level: developer
373
374 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetUp()`
375 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
376 @*/
PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)377 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map, PetscInt n)
378 {
379 PetscFunctionBegin;
380 PetscCheck(n % map->bs == 0, map->comm, PETSC_ERR_ARG_INCOMP, "Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT, n, map->bs);
381 map->n = n;
382 PetscFunctionReturn(PETSC_SUCCESS);
383 }
384
385 /*@
386 PetscLayoutGetLocalSize - Gets the local size for a `PetscLayout` object.
387
388 Not Collective
389
390 Input Parameter:
391 . map - pointer to the map
392
393 Output Parameter:
394 . n - the local size
395
396 Level: developer
397
398 Note:
399 Call this after the call to `PetscLayoutSetUp()`
400
401 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
402 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
403 @*/
PetscLayoutGetLocalSize(PetscLayout map,PetscInt * n)404 PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map, PetscInt *n)
405 {
406 PetscFunctionBegin;
407 *n = map->n;
408 PetscFunctionReturn(PETSC_SUCCESS);
409 }
410
411 /*@
412 PetscLayoutSetSize - Sets the global size for a `PetscLayout` object.
413
414 Logically Collective
415
416 Input Parameters:
417 + map - pointer to the map
418 - n - the global size, use `PETSC_DETERMINE` (the default) to have this value computed as the sum of the local sizes set with `PetscLayoutSetLocalSize()`
419
420 Level: developer
421
422 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
423 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
424 @*/
PetscLayoutSetSize(PetscLayout map,PetscInt n)425 PetscErrorCode PetscLayoutSetSize(PetscLayout map, PetscInt n)
426 {
427 PetscFunctionBegin;
428 map->N = n;
429 PetscFunctionReturn(PETSC_SUCCESS);
430 }
431
432 /*@
433 PetscLayoutGetSize - Gets the global size for a `PetscLayout` object.
434
435 Not Collective
436
437 Input Parameter:
438 . map - pointer to the map
439
440 Output Parameter:
441 . n - the global size
442
443 Level: developer
444
445 Note:
446 Call this after the call to `PetscLayoutSetUp()`
447
448 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
449 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetBlockSize()`
450 @*/
PetscLayoutGetSize(PetscLayout map,PetscInt * n)451 PetscErrorCode PetscLayoutGetSize(PetscLayout map, PetscInt *n)
452 {
453 PetscFunctionBegin;
454 *n = map->N;
455 PetscFunctionReturn(PETSC_SUCCESS);
456 }
457
458 /*@
459 PetscLayoutSetBlockSize - Sets the block size for a `PetscLayout` object.
460
461 Logically Collective
462
463 Input Parameters:
464 + map - pointer to the map
465 - bs - the size
466
467 Level: developer
468
469 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
470 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
471 @*/
PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)472 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map, PetscInt bs)
473 {
474 PetscFunctionBegin;
475 PetscCheck(bs > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Block size %" PetscInt_FMT " must be positive", bs);
476 PetscCheck(map->n <= 0 || (map->n % bs) == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT, map->n, bs);
477 if (map->mapping) {
478 PetscInt obs;
479
480 PetscCall(ISLocalToGlobalMappingGetBlockSize(map->mapping, &obs));
481 if (obs > 1) PetscCall(ISLocalToGlobalMappingSetBlockSize(map->mapping, bs));
482 }
483 map->bs = bs;
484 PetscFunctionReturn(PETSC_SUCCESS);
485 }
486
487 /*@
488 PetscLayoutGetBlockSize - Gets the block size for a `PetscLayout` object.
489
490 Not Collective
491
492 Input Parameter:
493 . map - pointer to the map
494
495 Output Parameter:
496 . bs - the size
497
498 Level: developer
499
500 Notes:
501 Call this after the call to `PetscLayoutSetUp()`
502
503 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`, `PetscLayoutSetUp()`
504 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutGetSize()`
505 @*/
PetscLayoutGetBlockSize(PetscLayout map,PetscInt * bs)506 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map, PetscInt *bs)
507 {
508 PetscFunctionBegin;
509 *bs = map->bs;
510 PetscFunctionReturn(PETSC_SUCCESS);
511 }
512
513 /*@
514 PetscLayoutGetRange - gets the range of values owned by this process
515
516 Not Collective
517
518 Input Parameter:
519 . map - pointer to the map
520
521 Output Parameters:
522 + rstart - first index owned by this process
523 - rend - one more than the last index owned by this process
524
525 Level: developer
526
527 Note:
528 Call this after the call to `PetscLayoutSetUp()`
529
530 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
531 `PetscLayoutGetSize()`, `PetscLayoutGetRanges()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()`
532 @*/
PetscLayoutGetRange(PetscLayout map,PetscInt * rstart,PetscInt * rend)533 PetscErrorCode PetscLayoutGetRange(PetscLayout map, PetscInt *rstart, PetscInt *rend)
534 {
535 PetscFunctionBegin;
536 if (rstart) *rstart = map->rstart;
537 if (rend) *rend = map->rend;
538 PetscFunctionReturn(PETSC_SUCCESS);
539 }
540
541 /*@C
542 PetscLayoutGetRanges - gets the ranges of values owned by all processes
543
544 Not Collective
545
546 Input Parameter:
547 . map - pointer to the map
548
549 Output Parameter:
550 . range - start of each processors range of indices (the final entry is one more than the
551 last index on the last process). The length of the array is one more than the number of processes in the MPI
552 communicator owned by `map`
553
554 Level: developer
555
556 Note:
557 Call this after the call to `PetscLayoutSetUp()`
558
559 Fortran Notes:
560 .vb
561 PetscInt, pointer :: range(:)
562 .ve
563
564 Call `PetscLayoutRestoreRanges()` when no longer needed.
565
566 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutSetSize()`,
567 `PetscLayoutGetSize()`, `PetscLayoutGetRange()`, `PetscLayoutSetBlockSize()`, `PetscLayoutSetUp()`
568 @*/
PetscLayoutGetRanges(PetscLayout map,const PetscInt * range[])569 PetscErrorCode PetscLayoutGetRanges(PetscLayout map, const PetscInt *range[])
570 {
571 PetscFunctionBegin;
572 *range = map->range;
573 PetscFunctionReturn(PETSC_SUCCESS);
574 }
575
576 /*@
577 PetscLayoutCompare - Compares two layouts
578
579 Not Collective
580
581 Input Parameters:
582 + mapa - pointer to the first map
583 - mapb - pointer to the second map
584
585 Output Parameter:
586 . congruent - `PETSC_TRUE` if the two layouts are congruent, `PETSC_FALSE` otherwise
587
588 Level: beginner
589
590 .seealso: [PetscLayout](sec_matlayout), `PetscLayoutCreate()`, `PetscLayoutSetLocalSize()`, `PetscLayoutGetLocalSize()`, `PetscLayoutGetBlockSize()`,
591 `PetscLayoutGetRange()`, `PetscLayoutGetRanges()`, `PetscLayoutSetSize()`, `PetscLayoutGetSize()`, `PetscLayoutSetUp()`
592 @*/
PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool * congruent)593 PetscErrorCode PetscLayoutCompare(PetscLayout mapa, PetscLayout mapb, PetscBool *congruent)
594 {
595 PetscFunctionBegin;
596 *congruent = PETSC_FALSE;
597 if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) PetscCall(PetscArraycmp(mapa->range, mapb->range, mapa->size + 1, congruent));
598 PetscFunctionReturn(PETSC_SUCCESS);
599 }
600
601 /*@
602 PetscLayoutFindOwner - Find the owning MPI process for a global index
603
604 Not Collective; No Fortran Support
605
606 Input Parameters:
607 + map - the layout
608 - idx - global index to find the owner of
609
610 Output Parameter:
611 . owner - the owning rank
612
613 Level: developer
614
615 .seealso: `PetscLayout`, `PetscLayoutFindOwnerIndex()`
616 @*/
PetscLayoutFindOwner(PetscLayout map,PetscInt idx,PetscMPIInt * owner)617 PetscErrorCode PetscLayoutFindOwner(PetscLayout map, PetscInt idx, PetscMPIInt *owner)
618 {
619 PetscMPIInt lo = 0, hi, t;
620
621 PetscFunctionBegin;
622 *owner = -1; /* GCC erroneously issues warning about possibly uninitialized use when error condition */
623 PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first");
624 PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx);
625 hi = map->size;
626 while (hi - lo > 1) {
627 t = lo + (hi - lo) / 2;
628 if (idx < map->range[t]) hi = t;
629 else lo = t;
630 }
631 *owner = lo;
632 PetscFunctionReturn(PETSC_SUCCESS);
633 }
634
635 /*@
636 PetscLayoutFindOwnerIndex - Find the owning MPI process and the local index on that process for a global index
637
638 Not Collective; No Fortran Support
639
640 Input Parameters:
641 + map - the layout
642 - idx - global index to find the owner of
643
644 Output Parameters:
645 + owner - the owning rank
646 - lidx - local index used by the owner for `idx`
647
648 Level: developer
649
650 .seealso: `PetscLayout`, `PetscLayoutFindOwner()`
651 @*/
PetscLayoutFindOwnerIndex(PetscLayout map,PetscInt idx,PetscMPIInt * owner,PetscInt * lidx)652 PetscErrorCode PetscLayoutFindOwnerIndex(PetscLayout map, PetscInt idx, PetscMPIInt *owner, PetscInt *lidx)
653 {
654 PetscMPIInt lo = 0, hi, t;
655
656 PetscFunctionBegin;
657 PetscAssert((map->n >= 0) && (map->N >= 0) && (map->range), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscLayoutSetUp() must be called first");
658 PetscAssert(idx >= 0 && idx <= map->N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Index %" PetscInt_FMT " is out of range", idx);
659 hi = map->size;
660 while (hi - lo > 1) {
661 t = lo + (hi - lo) / 2;
662 if (idx < map->range[t]) hi = t;
663 else lo = t;
664 }
665 if (owner) *owner = lo;
666 if (lidx) *lidx = idx - map->range[lo];
667 PetscFunctionReturn(PETSC_SUCCESS);
668 }
669