Actual source code: pmap.c

petsc-3.7.7 2017-09-25
Report Typos and Errors
  2: /*
  3:    This file contains routines for basic map object implementation.
  4: */

  6: #include <petscis.h> /*I "petscis.h" I*/
  7: #include <petscsf.h>

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

 14:   Collective on MPI_Comm

 16:   Input Parameters:
 17: + comm - the MPI communicator
 18: - map - pointer to the map

 20:   Level: advanced

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

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

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

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

 44: @*/
 45: PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
 46: {

 50:   PetscNew(map);

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

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

 67:   Collective on MPI_Comm

 69:   Input Parameters:
 70: . map - the PetscLayout

 72:   Level: developer

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

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

 81: @*/
 82: PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
 83: {

 87:   if (!*map) return(0);
 88:   if (!(*map)->refcnt--) {
 89:     PetscFree((*map)->range);
 90:     ISLocalToGlobalMappingDestroy(&(*map)->mapping);
 91:     PetscFree((*map));
 92:   }
 93:   *map = NULL;
 94:   return(0);
 95: }

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

103:   Collective on MPI_Comm

105:   Input Parameters:
106: . map - pointer to the map

108:   Level: developer

110:   Notes: Typical calling sequence
111: $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
112: $ PetscLayoutSetBlockSize(PetscLayout,1);
113: $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
114: $ PetscLayoutSetUp(PetscLayout);
115: $ PetscLayoutGetSize(PetscLayout,PetscInt *);


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

120: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
121:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
122: @*/
123: PetscErrorCode PetscLayoutSetUp(PetscLayout map)
124: {
125:   PetscMPIInt    rank,size;
126:   PetscInt       p;

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

132:   if (map->n > 0 && map->bs > 1) {
133:     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);
134:   }
135:   if (map->N > 0 && map->bs > 1) {
136:     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);
137:   }

139:   MPI_Comm_size(map->comm, &size);
140:   MPI_Comm_rank(map->comm, &rank);
141:   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
142:   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
143:   PetscSplitOwnership(map->comm,&map->n,&map->N);
144:   map->n = map->n*PetscAbs(map->bs);
145:   map->N = map->N*PetscAbs(map->bs);
146:   if (!map->range) {
147:     PetscMalloc1(size+1, &map->range);
148:   }
149:   MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);

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

154:   map->rstart = map->range[rank];
155:   map->rend   = map->range[rank+1];
156:   return(0);
157: }

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

164:   Collective on PetscLayout

166:   Input Parameter:
167: . in - input PetscLayout to be duplicated

169:   Output Parameter:
170: . out - the copy

172:   Level: developer

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

176: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
177: @*/
178: PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
179: {
180:   PetscMPIInt    size;
182:   MPI_Comm       comm = in->comm;

185:   PetscLayoutDestroy(out);
186:   PetscLayoutCreate(comm,out);
187:   MPI_Comm_size(comm,&size);
188:   PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));
189:   PetscMalloc1(size+1,&(*out)->range);
190:   PetscMemcpy((*out)->range,in->range,(size+1)*sizeof(PetscInt));

192:   (*out)->refcnt = 0;
193:   return(0);
194: }

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

201:   Collective on PetscLayout

203:   Input Parameter:
204: . in - input PetscLayout to be copied

206:   Output Parameter:
207: . out - the reference location

209:   Level: developer

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

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

215: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
216: @*/
217: PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
218: {

222:   in->refcnt++;
223:   PetscLayoutDestroy(out);
224:   *out = in;
225:   return(0);
226: }

230: /*@
231:   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout

233:   Collective on PetscLayout

235:   Input Parameter:
236: + in - input PetscLayout
237: - ltog - the local to global mapping


240:   Level: developer

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

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

246: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
247: @*/
248: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
249: {
251:   PetscInt       bs;

254:   ISLocalToGlobalMappingGetBlockSize(ltog,&bs);
255:   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);
256:   PetscObjectReference((PetscObject)ltog);
257:   ISLocalToGlobalMappingDestroy(&in->mapping);
258:   in->mapping = ltog;
259:   return(0);
260: }

264: /*@
265:   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.

267:   Collective on PetscLayout

269:   Input Parameters:
270: + map - pointer to the map
271: - n - the local size

273:   Level: developer

275:   Notes:
276:   Call this after the call to PetscLayoutCreate()

278: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
279:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
280: @*/
281: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
282: {
284:   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);
285:   map->n = n;
286:   return(0);
287: }

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

292:     Not Collective

294:    Input Parameters:
295: .    map - pointer to the map

297:    Output Parameters:
298: .    n - the local size

300:    Level: developer

302:     Notes:
303:        Call this after the call to PetscLayoutSetUp()

305:     Fortran Notes:
306:       Not available from Fortran

308: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
309:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()

311: @*/
314: PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
315: {
317:   *n = map->n;
318:   return(0);
319: }

323: /*@
324:   PetscLayoutSetSize - Sets the global size for a PetscLayout object.

326:   Logically Collective on PetscLayout

328:   Input Parameters:
329: + map - pointer to the map
330: - n - the global size

332:   Level: developer

334:   Notes:
335:   Call this after the call to PetscLayoutCreate()

337: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
338:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
339: @*/
340: PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
341: {
343:   map->N = n;
344:   return(0);
345: }

349: /*@
350:   PetscLayoutGetSize - Gets the global size for a PetscLayout object.

352:   Not Collective

354:   Input Parameters:
355: . map - pointer to the map

357:   Output Parameters:
358: . n - the global size

360:   Level: developer

362:   Notes:
363:   Call this after the call to PetscLayoutSetUp()

365: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
366:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
367: @*/
368: PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
369: {
371:   *n = map->N;
372:   return(0);
373: }

377: /*@
378:   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.

380:   Logically Collective on PetscLayout

382:   Input Parameters:
383: + map - pointer to the map
384: - bs - the size

386:   Level: developer

388:   Notes:
389:   Call this after the call to PetscLayoutCreate()

391: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
392:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
393: @*/
394: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
395: {
397:   if (bs < 0) return(0);
398:   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);
399:   if (map->range && map->bs > 0 && map->bs != bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Cannot change block size %D to %D",map->bs,bs);
400:   if (map->mapping) {
401:     PetscInt       lbs;

404:     ISLocalToGlobalMappingGetBlockSize(map->mapping,&lbs);
405:     if (lbs != bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Blocksize of localtoglobalmapping %D must match that of layout %D",lbs,bs);
406:   }
407:   map->bs = bs;
408:   return(0);
409: }

413: /*@
414:   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.

416:   Not Collective

418:   Input Parameters:
419: . map - pointer to the map

421:   Output Parameters:
422: . bs - the size

424:   Level: developer

426:   Notes:
427:   Call this after the call to PetscLayoutSetUp()

429: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
430:           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
431: @*/
432: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
433: {
435:   *bs = PetscAbs(map->bs);
436:   return(0);
437: }

441: /*@
442:   PetscLayoutGetRange - gets the range of values owned by this process

444:   Not Collective

446:   Input Parameters:
447: . map - pointer to the map

449:   Output Parameters:
450: + rstart - first index owned by this process
451: - rend   - one more than the last index owned by this process

453:   Level: developer

455:   Notes:
456:   Call this after the call to PetscLayoutSetUp()

458: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
459:           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
460: @*/
461: PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
462: {
464:   if (rstart) *rstart = map->rstart;
465:   if (rend)   *rend   = map->rend;
466:   return(0);
467: }

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

472:     Not Collective

474:    Input Parameters:
475: .    map - pointer to the map

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

481:    Level: developer

483:     Notes:
484:        Call this after the call to PetscLayoutSetUp()

486:     Fortran Notes:
487:       Not available from Fortran

489: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
490:           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()

492: @*/
495: PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
496: {
498:   *range = map->range;
499:   return(0);
500: }

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

507:    Collective

509:    Input Arguments:
510: +  sf - star forest
511: .  layout - PetscLayout defining the global space
512: .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
513: .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
514: -  iremote - remote locations of root vertices for each leaf on the current process

516:    Level: intermediate

518: .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
519: @*/
520: PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
521: {
523:   PetscInt       i,nroots;
524:   PetscSFNode    *remote;

527:   PetscLayoutGetLocalSize(layout,&nroots);
528:   PetscMalloc1(nleaves,&remote);
529:   for (i=0; i<nleaves; i++) {
530:     PetscInt owner = -1;
531:     PetscLayoutFindOwner(layout,iremote[i],&owner);
532:     remote[i].rank  = owner;
533:     remote[i].index = iremote[i] - layout->range[owner];
534:   }
535:   PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);
536:   return(0);
537: }