Actual source code: pmap.c


  2: /*
  3:    This file contains routines for basic map object implementation.
  4: */

  6: #include <petsc/private/isimpl.h>

  8: /*@
  9:   PetscLayoutCreate - Allocates PetscLayout space and sets the PetscLayout contents to the default.

 11:   Collective

 13:   Input Parameters:
 14: . comm - the MPI communicator

 16:   Output Parameters:
 17: . map - the new PetscLayout

 19:   Level: advanced

 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);

 32:   Optionally use any of the following:

 34: + PetscLayoutGetSize(PetscLayout,PetscInt *);
 35: . PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
 36: . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
 37: . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
 38: - PetscLayoutDestroy(PetscLayout*);

 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.

 43: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
 44:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(),
 45:           PetscLayoutCreateFromSizes()

 47: @*/
 48: PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
 49: {

 53:   PetscNew(map);
 54:   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:   return(0);
 68: }

 70: /*@
 71:   PetscLayoutCreateFromSizes - Allocates PetscLayout space, sets the layout sizes, and sets the layout up.

 73:   Collective

 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)

 81:   Output Parameters:
 82: . map - the new PetscLayout

 84:   Level: advanced

 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

 97: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
 98:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromRanges()

100: @*/
101: PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm,PetscInt n,PetscInt N,PetscInt bs,PetscLayout *map)
102: {

106:   PetscLayoutCreate(comm, map);
107:   PetscLayoutSetLocalSize(*map, n);
108:   PetscLayoutSetSize(*map, N);
109:   PetscLayoutSetBlockSize(*map, bs);
110:   PetscLayoutSetUp(*map);
111:   return(0);
112: }

114: /*@
115:   PetscLayoutDestroy - Frees a map object and frees its range if that exists.

117:   Collective

119:   Input Parameters:
120: . map - the PetscLayout

122:   Level: developer

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.

128: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(),
129:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()

131: @*/
132: PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
133: {

137:   if (!*map) return(0);
138:   if (!(*map)->refcnt--) {
139:     if ((*map)->range_alloc) {PetscFree((*map)->range);}
140:     ISLocalToGlobalMappingDestroy(&(*map)->mapping);
141:     PetscFree((*map));
142:   }
143:   *map = NULL;
144:   return(0);
145: }

147: /*@
148:   PetscLayoutCreateFromRanges - Creates a new PetscLayout with the given ownership ranges and sets it up.

150:   Collective

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)

158:   Output Parameters:
159: . newmap - the new PetscLayout

161:   Level: developer

163: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
164:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromSizes()

166: @*/
167: PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm,const PetscInt range[],PetscCopyMode mode,PetscInt bs,PetscLayout *newmap)
168: {
169:   PetscLayout    map;
170:   PetscMPIInt    rank;

174:   MPI_Comm_rank(comm, &rank);
175:   PetscLayoutCreate(comm, &map);
176:   PetscLayoutSetBlockSize(map, bs);
177:   switch (mode) {
178:     case PETSC_COPY_VALUES:
179:       PetscMalloc1(map->size+1, &map->range);
180:       PetscArraycpy(map->range, range, map->size+1);
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:     MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);
195:     if (tmp != map->N) SETERRQ3(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 ".\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 %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT,map->n,map->bs);
198:     }
199:     if (map->bs > 1) {
200:       if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT,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:   return(0);
210: }

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.

216:   Collective

218:   Input Parameters:
219: . map - pointer to the map

221:   Level: developer

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 *);

231:   If range exists, and local size is not set, everything gets computed from the range.

233:   If the local size, global size are already set and range exists then this does nothing.

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;

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=%" PetscInt_FMT ",global=%" PetscInt_FMT "), cannot call setup again with (local=%" PetscInt_FMT ",global=%" PetscInt_FMT ")", map->oldn, map->oldN, map->n, map->N);
246:   if (map->setupcalled) return(0);

248:   if (map->n > 0 && map->bs > 1) {
249:     if (map->n % map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local size %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT,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 %" PetscInt_FMT " must be divisible by blocksize %" PetscInt_FMT,map->N,map->bs);
253:   }

255:   MPI_Comm_rank(map->comm, &rank);
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:   PetscSplitOwnership(map->comm,&map->n,&map->N);
259:   map->n = map->n*PetscAbs(map->bs);
260:   map->N = map->N*PetscAbs(map->bs);
261:   if (!map->range) {
262:     PetscMalloc1(map->size+1, &map->range);
263:   }
264:   MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);

266:   map->range[0] = 0;
267:   for (p = 2; p <= map->size; p++) map->range[p] += map->range[p-1];

269:   map->rstart = map->range[rank];
270:   map->rend   = map->range[rank+1];

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:   return(0);
278: }

280: /*@
281:   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.

283:   Collective on PetscLayout

285:   Input Parameter:
286: . in - input PetscLayout to be duplicated

288:   Output Parameter:
289: . out - the copy

291:   Level: developer

293:   Notes:
294:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

296: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
297: @*/
298: PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
299: {
301:   MPI_Comm       comm = in->comm;

304:   PetscLayoutDestroy(out);
305:   PetscLayoutCreate(comm,out);
306:   PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));
307:   if (in->range) {
308:     PetscMalloc1((*out)->size+1,&(*out)->range);
309:     PetscArraycpy((*out)->range,in->range,(*out)->size+1);
310:   }
311:   (*out)->refcnt = 0;
312:   return(0);
313: }

315: /*@
316:   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()

318:   Collective on PetscLayout

320:   Input Parameter:
321: . in - input PetscLayout to be copied

323:   Output Parameter:
324: . out - the reference location

326:   Level: developer

328:   Notes:
329:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

331:   If the out location already contains a PetscLayout it is destroyed

333: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
334: @*/
335: PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
336: {

340:   in->refcnt++;
341:   PetscLayoutDestroy(out);
342:   *out = in;
343:   return(0);
344: }

346: /*@
347:   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout

349:   Collective on PetscLayout

351:   Input Parameters:
352: + in - input PetscLayout
353: - ltog - the local to global mapping

355:   Level: developer

357:   Notes:
358:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

360:   If the ltog location already contains a PetscLayout it is destroyed

362: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
363: @*/
364: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
365: {

369:   if (ltog) {
370:     PetscInt bs;

372:     ISLocalToGlobalMappingGetBlockSize(ltog,&bs);
373:     if (in->bs > 0 && (bs != 1) && in->bs != bs) SETERRQ2(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);
374:     PetscObjectReference((PetscObject)ltog);
375:   }
376:   ISLocalToGlobalMappingDestroy(&in->mapping);
377:   in->mapping = ltog;
378:   return(0);
379: }

381: /*@
382:   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.

384:   Collective on PetscLayout

386:   Input Parameters:
387: + map - pointer to the map
388: - n - the local size

390:   Level: developer

392:   Notes:
393:   Call this after the call to PetscLayoutCreate()

395: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
396:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
397: @*/
398: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
399: {
401:   if (map->bs > 1 && n % map->bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT,n,map->bs);
402:   map->n = n;
403:   return(0);
404: }

406: /*@C
407:      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.

409:     Not Collective

411:    Input Parameters:
412: .    map - pointer to the map

414:    Output Parameters:
415: .    n - the local size

417:    Level: developer

419:     Notes:
420:        Call this after the call to PetscLayoutSetUp()

422:     Fortran Notes:
423:       Not available from Fortran

425: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
426:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()

428: @*/
429: PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
430: {
432:   *n = map->n;
433:   return(0);
434: }

436: /*@
437:   PetscLayoutSetSize - Sets the global size for a PetscLayout object.

439:   Logically Collective on PetscLayout

441:   Input Parameters:
442: + map - pointer to the map
443: - n - the global size

445:   Level: developer

447:   Notes:
448:   Call this after the call to PetscLayoutCreate()

450: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
451:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
452: @*/
453: PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
454: {
456:   map->N = n;
457:   return(0);
458: }

460: /*@
461:   PetscLayoutGetSize - Gets the global size for a PetscLayout object.

463:   Not Collective

465:   Input Parameters:
466: . map - pointer to the map

468:   Output Parameters:
469: . n - the global size

471:   Level: developer

473:   Notes:
474:   Call this after the call to PetscLayoutSetUp()

476: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
477:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
478: @*/
479: PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
480: {
482:   *n = map->N;
483:   return(0);
484: }

486: /*@
487:   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.

489:   Logically Collective on PetscLayout

491:   Input Parameters:
492: + map - pointer to the map
493: - bs - the size

495:   Level: developer

497:   Notes:
498:   Call this after the call to PetscLayoutCreate()

500: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
501:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
502: @*/
503: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
504: {
506:   if (bs < 0) return(0);
507:   if (map->n > 0 && map->n % bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local size %" PetscInt_FMT " not compatible with block size %" PetscInt_FMT,map->n,bs);
508:   if (map->mapping) {
509:     PetscInt       obs;

512:     ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);
513:     if (obs > 1) {
514:       ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);
515:     }
516:   }
517:   map->bs = bs;
518:   return(0);
519: }

521: /*@
522:   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.

524:   Not Collective

526:   Input Parameters:
527: . map - pointer to the map

529:   Output Parameters:
530: . bs - the size

532:   Level: developer

534:   Notes:
535:   Call this after the call to PetscLayoutSetUp()

537: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
538:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
539: @*/
540: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
541: {
543:   *bs = PetscAbs(map->bs);
544:   return(0);
545: }

547: /*@
548:   PetscLayoutGetRange - gets the range of values owned by this process

550:   Not Collective

552:   Input Parameter:
553: . map - pointer to the map

555:   Output Parameters:
556: + rstart - first index owned by this process
557: - rend   - one more than the last index owned by this process

559:   Level: developer

561:   Notes:
562:   Call this after the call to PetscLayoutSetUp()

564: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
565:           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
566: @*/
567: PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
568: {
570:   if (rstart) *rstart = map->rstart;
571:   if (rend)   *rend   = map->rend;
572:   return(0);
573: }

575: /*@C
576:      PetscLayoutGetRanges - gets the range of values owned by all processes

578:     Not Collective

580:    Input Parameters:
581: .    map - pointer to the map

583:    Output Parameters:
584: .    range - start of each processors range of indices (the final entry is one more then the
585:              last index on the last process)

587:    Level: developer

589:     Notes:
590:        Call this after the call to PetscLayoutSetUp()

592:     Fortran Notes:
593:       Not available from Fortran

595: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
596:           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()

598: @*/
599: PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
600: {
602:   *range = map->range;
603:   return(0);
604: }

606: /*@
607:   PetscLayoutCompare - Compares two layouts

609:   Not Collective

611:   Input Parameters:
612: + mapa - pointer to the first map
613: - mapb - pointer to the second map

615:   Output Parameters:
616: . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise

618:   Level: beginner

620:   Notes:

622: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
623:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
624: @*/
625: PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
626: {

630:   *congruent = PETSC_FALSE;
631:   if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) {
632:     PetscArraycmp(mapa->range,mapb->range,mapa->size+1,congruent);
633:   }
634:   return(0);
635: }