Actual source code: pmap.c

petsc-3.11.1 2019-04-17
Report Typos and Errors

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

  6:  #include <petscis.h>
  7:  #include <petscsf.h>

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

 12:   Collective on MPI_Comm

 14:   Input Parameters:
 15: + comm - the MPI communicator
 16: - map - pointer to the map

 18:   Level: advanced

 20:   Notes:
 21:   Typical calling sequence
 22: .vb
 23:        PetscLayoutCreate(MPI_Comm,PetscLayout *);
 24:        PetscLayoutSetBlockSize(PetscLayout,1);
 25:        PetscLayoutSetSize(PetscLayout,N) // or PetscLayoutSetLocalSize(PetscLayout,n);
 26:        PetscLayoutSetUp(PetscLayout);
 27: .ve
 28:   Optionally use any of the following:

 30: + PetscLayoutGetSize(PetscLayout,PetscInt *);
 31: . PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
 32: . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
 33: . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
 34: - PetscLayoutDestroy(PetscLayout*);

 36:   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is often not needed in
 37:   user codes unless you really gain something in their use.

 39: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
 40:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()

 42: @*/
 43: PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
 44: {

 48:   PetscNew(map);

 50:   (*map)->comm   = comm;
 51:   (*map)->bs     = -1;
 52:   (*map)->n      = -1;
 53:   (*map)->N      = -1;
 54:   (*map)->range  = NULL;
 55:   (*map)->rstart = 0;
 56:   (*map)->rend   = 0;
 57:   return(0);
 58: }

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

 63:   Collective on MPI_Comm

 65:   Input Parameters:
 66: . map - the PetscLayout

 68:   Level: developer

 70:   Note:
 71:   The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
 72:   recommended they not be used in user codes unless you really gain something in their use.

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

 77: @*/
 78: PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
 79: {

 83:   if (!*map) return(0);
 84:   if (!(*map)->refcnt--) {
 85:     PetscFree((*map)->range);
 86:     ISLocalToGlobalMappingDestroy(&(*map)->mapping);
 87:     PetscFree((*map));
 88:   }
 89:   *map = NULL;
 90:   return(0);
 91: }

 93: static PetscErrorCode PetscLayoutSetUp_SizesFromRanges_Private(PetscLayout map)
 94: {
 95:   PetscMPIInt    rank,size;

 99:   MPI_Comm_size(map->comm, &size);
100:   MPI_Comm_rank(map->comm, &rank);
101:   map->rstart = map->range[rank];
102:   map->rend   = map->range[rank+1];
103:   map->n      = map->rend - map->rstart;
104:   map->N      = map->range[size];
105: #if defined(PETSC_USE_DEBUG)
106:   /* just check that n, N and bs are consistent */
107:   {
108:     PetscInt tmp;
109:     MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);
110:     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);
111:   }
112:   if (map->bs > 1) {
113:     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);
114:   }
115:   if (map->bs > 1) {
116:     if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global size %D must be divisible by blocksize %D",map->N,map->bs);
117:   }
118: #endif
119:   return(0);
120: }

122: /*@
123:   PetscLayoutSetUp - given a map where you have set either the global or local
124:                      size sets up the map so that it may be used.

126:   Collective on MPI_Comm

128:   Input Parameters:
129: . map - pointer to the map

131:   Level: developer

133:   Notes:
134:     Typical calling sequence
135: $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
136: $ PetscLayoutSetBlockSize(PetscLayout,1);
137: $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
138: $ PetscLayoutSetUp(PetscLayout);
139: $ PetscLayoutGetSize(PetscLayout,PetscInt *);

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

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

145: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
146:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
147: @*/
148: PetscErrorCode PetscLayoutSetUp(PetscLayout map)
149: {
150:   PetscMPIInt    rank,size;
151:   PetscInt       p;

155:   if ((map->n >= 0) && (map->N >= 0) && (map->range)) return(0);
156:   if (map->range && map->n < 0) {
157:     PetscLayoutSetUp_SizesFromRanges_Private(map);
158:     return(0);
159:   }

161:   if (map->n > 0 && map->bs > 1) {
162:     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);
163:   }
164:   if (map->N > 0 && map->bs > 1) {
165:     if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global size %D must be divisible by blocksize %D",map->N,map->bs);
166:   }

168:   MPI_Comm_size(map->comm, &size);
169:   MPI_Comm_rank(map->comm, &rank);
170:   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
171:   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
172:   PetscSplitOwnership(map->comm,&map->n,&map->N);
173:   map->n = map->n*PetscAbs(map->bs);
174:   map->N = map->N*PetscAbs(map->bs);
175:   if (!map->range) {
176:     PetscMalloc1(size+1, &map->range);
177:   }
178:   MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);

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

183:   map->rstart = map->range[rank];
184:   map->rend   = map->range[rank+1];
185:   return(0);
186: }

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

191:   Collective on PetscLayout

193:   Input Parameter:
194: . in - input PetscLayout to be duplicated

196:   Output Parameter:
197: . out - the copy

199:   Level: developer

201:   Notes:
202:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

204: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
205: @*/
206: PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
207: {
208:   PetscMPIInt    size;
210:   MPI_Comm       comm = in->comm;

213:   PetscLayoutDestroy(out);
214:   PetscLayoutCreate(comm,out);
215:   MPI_Comm_size(comm,&size);
216:   PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));
217:   PetscMalloc1(size+1,&(*out)->range);
218:   PetscMemcpy((*out)->range,in->range,(size+1)*sizeof(PetscInt));

220:   (*out)->refcnt = 0;
221:   return(0);
222: }

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

227:   Collective on PetscLayout

229:   Input Parameter:
230: . in - input PetscLayout to be copied

232:   Output Parameter:
233: . out - the reference location

235:   Level: developer

237:   Notes:
238:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

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

242: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
243: @*/
244: PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
245: {

249:   in->refcnt++;
250:   PetscLayoutDestroy(out);
251:   *out = in;
252:   return(0);
253: }

255: /*@
256:   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout

258:   Collective on PetscLayout

260:   Input Parameter:
261: + in - input PetscLayout
262: - ltog - the local to global mapping


265:   Level: developer

267:   Notes:
268:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

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

272: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
273: @*/
274: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
275: {
277:   PetscInt       bs;

280:   ISLocalToGlobalMappingGetBlockSize(ltog,&bs);
281:   if (in->bs > 0 && in->bs != bs) SETERRQ2(in->comm,PETSC_ERR_PLIB,"Blocksize of layout %D must match that of mapping %D",in->bs,bs);
282:   PetscObjectReference((PetscObject)ltog);
283:   ISLocalToGlobalMappingDestroy(&in->mapping);
284:   in->mapping = ltog;
285:   return(0);
286: }

288: /*@
289:   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.

291:   Collective on PetscLayout

293:   Input Parameters:
294: + map - pointer to the map
295: - n - the local size

297:   Level: developer

299:   Notes:
300:   Call this after the call to PetscLayoutCreate()

302: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
303:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
304: @*/
305: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
306: {
308:   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);
309:   map->n = n;
310:   return(0);
311: }

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

316:     Not Collective

318:    Input Parameters:
319: .    map - pointer to the map

321:    Output Parameters:
322: .    n - the local size

324:    Level: developer

326:     Notes:
327:        Call this after the call to PetscLayoutSetUp()

329:     Fortran Notes:
330:       Not available from Fortran

332: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
333:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()

335: @*/
336: PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
337: {
339:   *n = map->n;
340:   return(0);
341: }

343: /*@
344:   PetscLayoutSetSize - Sets the global size for a PetscLayout object.

346:   Logically Collective on PetscLayout

348:   Input Parameters:
349: + map - pointer to the map
350: - n - the global size

352:   Level: developer

354:   Notes:
355:   Call this after the call to PetscLayoutCreate()

357: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
358:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
359: @*/
360: PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
361: {
363:   map->N = n;
364:   return(0);
365: }

367: /*@
368:   PetscLayoutGetSize - Gets the global size for a PetscLayout object.

370:   Not Collective

372:   Input Parameters:
373: . map - pointer to the map

375:   Output Parameters:
376: . n - the global size

378:   Level: developer

380:   Notes:
381:   Call this after the call to PetscLayoutSetUp()

383: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
384:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
385: @*/
386: PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
387: {
389:   *n = map->N;
390:   return(0);
391: }

393: /*@
394:   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.

396:   Logically Collective on PetscLayout

398:   Input Parameters:
399: + map - pointer to the map
400: - bs - the size

402:   Level: developer

404:   Notes:
405:   Call this after the call to PetscLayoutCreate()

407: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
408:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
409: @*/
410: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
411: {
413:   if (bs < 0) return(0);
414:   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);
415:   if (map->mapping) {
416:     PetscInt       obs;

419:     ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);
420:     if (obs > 1) {
421:       ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);
422:     }
423:   }
424:   map->bs = bs;
425:   return(0);
426: }

428: /*@
429:   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.

431:   Not Collective

433:   Input Parameters:
434: . map - pointer to the map

436:   Output Parameters:
437: . bs - the size

439:   Level: developer

441:   Notes:
442:   Call this after the call to PetscLayoutSetUp()

444: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
445:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
446: @*/
447: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
448: {
450:   *bs = PetscAbs(map->bs);
451:   return(0);
452: }

454: /*@
455:   PetscLayoutGetRange - gets the range of values owned by this process

457:   Not Collective

459:   Input Parameters:
460: . map - pointer to the map

462:   Output Parameters:
463: + rstart - first index owned by this process
464: - rend   - one more than the last index owned by this process

466:   Level: developer

468:   Notes:
469:   Call this after the call to PetscLayoutSetUp()

471: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
472:           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
473: @*/
474: PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
475: {
477:   if (rstart) *rstart = map->rstart;
478:   if (rend)   *rend   = map->rend;
479:   return(0);
480: }

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

485:     Not Collective

487:    Input Parameters:
488: .    map - pointer to the map

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

494:    Level: developer

496:     Notes:
497:        Call this after the call to PetscLayoutSetUp()

499:     Fortran Notes:
500:       Not available from Fortran

502: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
503:           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()

505: @*/
506: PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
507: {
509:   *range = map->range;
510:   return(0);
511: }

513: /*@C
514:    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout

516:    Collective

518:    Input Arguments:
519: +  sf - star forest
520: .  layout - PetscLayout defining the global space
521: .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
522: .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
523: .  localmode - copy mode for ilocal
524: -  iremote - remote locations of root vertices for each leaf on the current process

526:    Level: intermediate

528:    Developers Note: Local indices which are the identity permutation in the range [0,nleaves) are discarded as they
529:    encode contiguous storage. In such case, if localmode is PETSC_OWN_POINTER, the memory is deallocated as it is not
530:    needed

532: .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
533: @*/
534: PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
535: {
537:   PetscInt       i,nroots;
538:   PetscSFNode    *remote;

541:   PetscLayoutGetLocalSize(layout,&nroots);
542:   PetscMalloc1(nleaves,&remote);
543:   for (i=0; i<nleaves; i++) {
544:     PetscInt owner = -1;
545:     PetscLayoutFindOwner(layout,iremote[i],&owner);
546:     remote[i].rank  = owner;
547:     remote[i].index = iremote[i] - layout->range[owner];
548:   }
549:   PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);
550:   return(0);
551: }

553: /*@
554:   PetscLayoutCompare - Compares two layouts

556:   Not Collective

558:   Input Parameters:
559: + mapa - pointer to the first map
560: - mapb - pointer to the second map

562:   Output Parameters:
563: . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise

565:   Level: beginner

567:   Notes:

569: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
570:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
571: @*/
572: PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
573: {
575:   PetscMPIInt    sizea,sizeb;

578:   *congruent = PETSC_FALSE;
579:   MPI_Comm_size(mapa->comm,&sizea);
580:   MPI_Comm_size(mapb->comm,&sizeb);
581:   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
582:     PetscMemcmp(mapa->range,mapb->range,(sizea+1)*sizeof(PetscInt),congruent);
583:   }
584:   return(0);
585: }