Actual source code: pmap.c

petsc-3.10.5 2019-03-28
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: /*@
 94:   PetscLayoutSetUp - given a map where you have set either the global or local
 95:                      size sets up the map so that it may be used.

 97:   Collective on MPI_Comm

 99:   Input Parameters:
100: . map - pointer to the map

102:   Level: developer

104:   Notes:
105:     Typical calling sequence
106: $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
107: $ PetscLayoutSetBlockSize(PetscLayout,1);
108: $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
109: $ PetscLayoutSetUp(PetscLayout);
110: $ PetscLayoutGetSize(PetscLayout,PetscInt *);


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

115: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
116:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
117: @*/
118: PetscErrorCode PetscLayoutSetUp(PetscLayout map)
119: {
120:   PetscMPIInt    rank,size;
121:   PetscInt       p;

125:   if ((map->n >= 0) && (map->N >= 0) && (map->range)) return(0);

127:   if (map->n > 0 && map->bs > 1) {
128:     if (map->n % map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local matrix size %D must be divisible by blocksize %D",map->n,map->bs);
129:   }
130:   if (map->N > 0 && map->bs > 1) {
131:     if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global matrix size %D must be divisible by blocksize %D",map->N,map->bs);
132:   }

134:   MPI_Comm_size(map->comm, &size);
135:   MPI_Comm_rank(map->comm, &rank);
136:   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
137:   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
138:   PetscSplitOwnership(map->comm,&map->n,&map->N);
139:   map->n = map->n*PetscAbs(map->bs);
140:   map->N = map->N*PetscAbs(map->bs);
141:   if (!map->range) {
142:     PetscMalloc1(size+1, &map->range);
143:   }
144:   MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);

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

149:   map->rstart = map->range[rank];
150:   map->rend   = map->range[rank+1];
151:   return(0);
152: }

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

157:   Collective on PetscLayout

159:   Input Parameter:
160: . in - input PetscLayout to be duplicated

162:   Output Parameter:
163: . out - the copy

165:   Level: developer

167:   Notes:
168:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

170: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
171: @*/
172: PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
173: {
174:   PetscMPIInt    size;
176:   MPI_Comm       comm = in->comm;

179:   PetscLayoutDestroy(out);
180:   PetscLayoutCreate(comm,out);
181:   MPI_Comm_size(comm,&size);
182:   PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));
183:   PetscMalloc1(size+1,&(*out)->range);
184:   PetscMemcpy((*out)->range,in->range,(size+1)*sizeof(PetscInt));

186:   (*out)->refcnt = 0;
187:   return(0);
188: }

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

193:   Collective on PetscLayout

195:   Input Parameter:
196: . in - input PetscLayout to be copied

198:   Output Parameter:
199: . out - the reference location

201:   Level: developer

203:   Notes:
204:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

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

208: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
209: @*/
210: PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
211: {

215:   in->refcnt++;
216:   PetscLayoutDestroy(out);
217:   *out = in;
218:   return(0);
219: }

221: /*@
222:   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout

224:   Collective on PetscLayout

226:   Input Parameter:
227: + in - input PetscLayout
228: - ltog - the local to global mapping


231:   Level: developer

233:   Notes:
234:     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout

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

238: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
239: @*/
240: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
241: {
243:   PetscInt       bs;

246:   ISLocalToGlobalMappingGetBlockSize(ltog,&bs);
247:   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);
248:   PetscObjectReference((PetscObject)ltog);
249:   ISLocalToGlobalMappingDestroy(&in->mapping);
250:   in->mapping = ltog;
251:   return(0);
252: }

254: /*@
255:   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.

257:   Collective on PetscLayout

259:   Input Parameters:
260: + map - pointer to the map
261: - n - the local size

263:   Level: developer

265:   Notes:
266:   Call this after the call to PetscLayoutCreate()

268: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
269:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
270: @*/
271: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
272: {
274:   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);
275:   map->n = n;
276:   return(0);
277: }

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

282:     Not Collective

284:    Input Parameters:
285: .    map - pointer to the map

287:    Output Parameters:
288: .    n - the local size

290:    Level: developer

292:     Notes:
293:        Call this after the call to PetscLayoutSetUp()

295:     Fortran Notes:
296:       Not available from Fortran

298: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
299:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()

301: @*/
302: PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
303: {
305:   *n = map->n;
306:   return(0);
307: }

309: /*@
310:   PetscLayoutSetSize - Sets the global size for a PetscLayout object.

312:   Logically Collective on PetscLayout

314:   Input Parameters:
315: + map - pointer to the map
316: - n - the global size

318:   Level: developer

320:   Notes:
321:   Call this after the call to PetscLayoutCreate()

323: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
324:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
325: @*/
326: PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
327: {
329:   map->N = n;
330:   return(0);
331: }

333: /*@
334:   PetscLayoutGetSize - Gets the global size for a PetscLayout object.

336:   Not Collective

338:   Input Parameters:
339: . map - pointer to the map

341:   Output Parameters:
342: . n - the global size

344:   Level: developer

346:   Notes:
347:   Call this after the call to PetscLayoutSetUp()

349: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
350:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
351: @*/
352: PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
353: {
355:   *n = map->N;
356:   return(0);
357: }

359: /*@
360:   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.

362:   Logically Collective on PetscLayout

364:   Input Parameters:
365: + map - pointer to the map
366: - bs - the size

368:   Level: developer

370:   Notes:
371:   Call this after the call to PetscLayoutCreate()

373: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
374:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
375: @*/
376: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
377: {
379:   if (bs < 0) return(0);
380:   if (map->n > 0 && map->n % bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Local size %D not compatible with block size %D",map->n,bs);
381:   if (map->mapping) {
382:     PetscInt       obs;

385:     ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);
386:     if (obs > 1) {
387:       ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);
388:     }
389:   }
390:   map->bs = bs;
391:   return(0);
392: }

394: /*@
395:   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.

397:   Not Collective

399:   Input Parameters:
400: . map - pointer to the map

402:   Output Parameters:
403: . bs - the size

405:   Level: developer

407:   Notes:
408:   Call this after the call to PetscLayoutSetUp()

410: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
411:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
412: @*/
413: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
414: {
416:   *bs = PetscAbs(map->bs);
417:   return(0);
418: }

420: /*@
421:   PetscLayoutGetRange - gets the range of values owned by this process

423:   Not Collective

425:   Input Parameters:
426: . map - pointer to the map

428:   Output Parameters:
429: + rstart - first index owned by this process
430: - rend   - one more than the last index owned by this process

432:   Level: developer

434:   Notes:
435:   Call this after the call to PetscLayoutSetUp()

437: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
438:           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
439: @*/
440: PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
441: {
443:   if (rstart) *rstart = map->rstart;
444:   if (rend)   *rend   = map->rend;
445:   return(0);
446: }

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

451:     Not Collective

453:    Input Parameters:
454: .    map - pointer to the map

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

460:    Level: developer

462:     Notes:
463:        Call this after the call to PetscLayoutSetUp()

465:     Fortran Notes:
466:       Not available from Fortran

468: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
469:           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()

471: @*/
472: PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
473: {
475:   *range = map->range;
476:   return(0);
477: }

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

482:    Collective

484:    Input Arguments:
485: +  sf - star forest
486: .  layout - PetscLayout defining the global space
487: .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
488: .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
489: .  localmode - copy mode for ilocal
490: -  iremote - remote locations of root vertices for each leaf on the current process

492:    Level: intermediate

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

498: .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
499: @*/
500: PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
501: {
503:   PetscInt       i,nroots;
504:   PetscSFNode    *remote;

507:   PetscLayoutGetLocalSize(layout,&nroots);
508:   PetscMalloc1(nleaves,&remote);
509:   for (i=0; i<nleaves; i++) {
510:     PetscInt owner = -1;
511:     PetscLayoutFindOwner(layout,iremote[i],&owner);
512:     remote[i].rank  = owner;
513:     remote[i].index = iremote[i] - layout->range[owner];
514:   }
515:   PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);
516:   return(0);
517: }

519: /*@
520:   PetscLayoutCompare - Compares two layouts

522:   Not Collective

524:   Input Parameters:
525: + mapa - pointer to the first map
526: - mapb - pointer to the second map

528:   Output Parameters:
529: . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise

531:   Level: beginner

533:   Notes:

535: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
536:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
537: @*/
538: PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
539: {
541:   PetscMPIInt    sizea,sizeb;

544:   *congruent = PETSC_FALSE;
545:   MPI_Comm_size(mapa->comm,&sizea);
546:   MPI_Comm_size(mapb->comm,&sizeb);
547:   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
548:     PetscMemcmp(mapa->range,mapb->range,(sizea+1)*sizeof(PetscInt),congruent);
549:   }
550:   return(0);
551: }