Actual source code: pmap.c
petsc-3.11.4 2019-09-28
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: }