Actual source code: pmap.c
petsc-3.10.5 2019-03-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: /*@
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: }