xref: /petsc/src/vec/is/utils/pmap.c (revision efa12513287cff49a2b9648ae83199dcbfaad71a)
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);CHKERRQ(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);CHKERRQ(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 Parameter:
352 + in - input PetscLayout
353 - ltog - the local to global mapping
354 
355 
356   Level: developer
357 
358   Notes:
359     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
360 
361   If the ltog location already contains a PetscLayout it is destroyed
362 
363 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
364 @*/
365 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
366 {
367   PetscErrorCode ierr;
368   PetscInt       bs;
369 
370   PetscFunctionBegin;
371   ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr);
372   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);
373   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
374   ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr);
375   in->mapping = ltog;
376   PetscFunctionReturn(0);
377 }
378 
379 /*@
380   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
381 
382   Collective on PetscLayout
383 
384   Input Parameters:
385 + map - pointer to the map
386 - n - the local size
387 
388   Level: developer
389 
390   Notes:
391   Call this after the call to PetscLayoutCreate()
392 
393 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
394           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
395 @*/
396 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
397 {
398   PetscFunctionBegin;
399   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);
400   map->n = n;
401   PetscFunctionReturn(0);
402 }
403 
404 /*@C
405      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
406 
407     Not Collective
408 
409    Input Parameters:
410 .    map - pointer to the map
411 
412    Output Parameters:
413 .    n - the local size
414 
415    Level: developer
416 
417     Notes:
418        Call this after the call to PetscLayoutSetUp()
419 
420     Fortran Notes:
421       Not available from Fortran
422 
423 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
424           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
425 
426 @*/
427 PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
428 {
429   PetscFunctionBegin;
430   *n = map->n;
431   PetscFunctionReturn(0);
432 }
433 
434 /*@
435   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
436 
437   Logically Collective on PetscLayout
438 
439   Input Parameters:
440 + map - pointer to the map
441 - n - the global size
442 
443   Level: developer
444 
445   Notes:
446   Call this after the call to PetscLayoutCreate()
447 
448 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
449           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
450 @*/
451 PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
452 {
453   PetscFunctionBegin;
454   map->N = n;
455   PetscFunctionReturn(0);
456 }
457 
458 /*@
459   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
460 
461   Not Collective
462 
463   Input Parameters:
464 . map - pointer to the map
465 
466   Output Parameters:
467 . n - the global size
468 
469   Level: developer
470 
471   Notes:
472   Call this after the call to PetscLayoutSetUp()
473 
474 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
475           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
476 @*/
477 PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
478 {
479   PetscFunctionBegin;
480   *n = map->N;
481   PetscFunctionReturn(0);
482 }
483 
484 /*@
485   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
486 
487   Logically Collective on PetscLayout
488 
489   Input Parameters:
490 + map - pointer to the map
491 - bs - the size
492 
493   Level: developer
494 
495   Notes:
496   Call this after the call to PetscLayoutCreate()
497 
498 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
499           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
500 @*/
501 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
502 {
503   PetscFunctionBegin;
504   if (bs < 0) PetscFunctionReturn(0);
505   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);
506   if (map->mapping) {
507     PetscInt       obs;
508     PetscErrorCode ierr;
509 
510     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);CHKERRQ(ierr);
511     if (obs > 1) {
512       ierr = ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);CHKERRQ(ierr);
513     }
514   }
515   map->bs = bs;
516   PetscFunctionReturn(0);
517 }
518 
519 /*@
520   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
521 
522   Not Collective
523 
524   Input Parameters:
525 . map - pointer to the map
526 
527   Output Parameters:
528 . bs - the size
529 
530   Level: developer
531 
532   Notes:
533   Call this after the call to PetscLayoutSetUp()
534 
535 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
536           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
537 @*/
538 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
539 {
540   PetscFunctionBegin;
541   *bs = PetscAbs(map->bs);
542   PetscFunctionReturn(0);
543 }
544 
545 /*@
546   PetscLayoutGetRange - gets the range of values owned by this process
547 
548   Not Collective
549 
550   Input Parameters:
551 . map - pointer to the map
552 
553   Output Parameters:
554 + rstart - first index owned by this process
555 - rend   - one more than the last index owned by this process
556 
557   Level: developer
558 
559   Notes:
560   Call this after the call to PetscLayoutSetUp()
561 
562 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
563           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
564 @*/
565 PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
566 {
567   PetscFunctionBegin;
568   if (rstart) *rstart = map->rstart;
569   if (rend)   *rend   = map->rend;
570   PetscFunctionReturn(0);
571 }
572 
573 /*@C
574      PetscLayoutGetRanges - gets the range of values owned by all processes
575 
576     Not Collective
577 
578    Input Parameters:
579 .    map - pointer to the map
580 
581    Output Parameters:
582 .    range - start of each processors range of indices (the final entry is one more then the
583              last index on the last process)
584 
585    Level: developer
586 
587     Notes:
588        Call this after the call to PetscLayoutSetUp()
589 
590     Fortran Notes:
591       Not available from Fortran
592 
593 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
594           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
595 
596 @*/
597 PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
598 {
599   PetscFunctionBegin;
600   *range = map->range;
601   PetscFunctionReturn(0);
602 }
603 
604 /*@
605   PetscLayoutCompare - Compares two layouts
606 
607   Not Collective
608 
609   Input Parameters:
610 + mapa - pointer to the first map
611 - mapb - pointer to the second map
612 
613   Output Parameters:
614 . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
615 
616   Level: beginner
617 
618   Notes:
619 
620 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
621           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
622 @*/
623 PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
624 {
625   PetscErrorCode ierr;
626 
627   PetscFunctionBegin;
628   *congruent = PETSC_FALSE;
629   if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) {
630     ierr = PetscArraycmp(mapa->range,mapb->range,mapa->size+1,congruent);CHKERRQ(ierr);
631   }
632   PetscFunctionReturn(0);
633 }
634 
635