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