Actual source code: pmap.c
2: /*
3: This file contains routines for basic map object implementation.
4: */
6: #include <petsc/private/isimpl.h>
8: /*@
9: PetscLayoutCreate - Allocates PetscLayout space and sets the PetscLayout contents to the default.
11: Collective
13: Input Parameters:
14: . comm - the MPI communicator
16: Output Parameters:
17: . map - the new PetscLayout
19: Level: advanced
21: Notes:
22: Typical calling sequence
23: .vb
24: PetscLayoutCreate(MPI_Comm,PetscLayout *);
25: PetscLayoutSetBlockSize(PetscLayout,bs);
26: PetscLayoutSetSize(PetscLayout,N); // or PetscLayoutSetLocalSize(PetscLayout,n);
27: PetscLayoutSetUp(PetscLayout);
28: .ve
29: Alternatively,
30: $ PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
32: Optionally use any of the following:
34: + PetscLayoutGetSize(PetscLayout,PetscInt *);
35: . PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
36: . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
37: . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
38: - PetscLayoutDestroy(PetscLayout*);
40: The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is often not needed in
41: user codes unless you really gain something in their use.
43: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
44: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(),
45: PetscLayoutCreateFromSizes()
47: @*/
48: PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
49: {
53: PetscNew(map);
54: MPI_Comm_size(comm, &(*map)->size);
55: (*map)->comm = comm;
56: (*map)->bs = -1;
57: (*map)->n = -1;
58: (*map)->N = -1;
59: (*map)->range = NULL;
60: (*map)->range_alloc = PETSC_TRUE;
61: (*map)->rstart = 0;
62: (*map)->rend = 0;
63: (*map)->setupcalled = PETSC_FALSE;
64: (*map)->oldn = -1;
65: (*map)->oldN = -1;
66: (*map)->oldbs = -1;
67: return(0);
68: }
70: /*@
71: PetscLayoutCreateFromSizes - Allocates PetscLayout space, sets the layout sizes, and sets the layout up.
73: Collective
75: Input Parameters:
76: + comm - the MPI communicator
77: . n - the local size (or PETSC_DECIDE)
78: . N - the global size (or PETSC_DECIDE)
79: - bs - the block size (or PETSC_DECIDE)
81: Output Parameters:
82: . map - the new PetscLayout
84: Level: advanced
86: Notes:
87: $ PetscLayoutCreateFromSizes(comm,n,N,bs,&layout);
88: is a shorthand for
89: .vb
90: PetscLayoutCreate(comm,&layout);
91: PetscLayoutSetLocalSize(layout,n);
92: PetscLayoutSetSize(layout,N);
93: PetscLayoutSetBlockSize(layout,bs);
94: PetscLayoutSetUp(layout);
95: .ve
97: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
98: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromRanges()
100: @*/
101: PetscErrorCode PetscLayoutCreateFromSizes(MPI_Comm comm,PetscInt n,PetscInt N,PetscInt bs,PetscLayout *map)
102: {
106: PetscLayoutCreate(comm, map);
107: PetscLayoutSetLocalSize(*map, n);
108: PetscLayoutSetSize(*map, N);
109: PetscLayoutSetBlockSize(*map, bs);
110: PetscLayoutSetUp(*map);
111: return(0);
112: }
114: /*@
115: PetscLayoutDestroy - Frees a map object and frees its range if that exists.
117: Collective
119: Input Parameters:
120: . map - the PetscLayout
122: Level: developer
124: Note:
125: The PetscLayout object and methods are intended to be used in the PETSc Vec and Mat implementions; it is
126: recommended they not be used in user codes unless you really gain something in their use.
128: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(),
129: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
131: @*/
132: PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
133: {
137: if (!*map) return(0);
138: if (!(*map)->refcnt--) {
139: if ((*map)->range_alloc) {PetscFree((*map)->range);}
140: ISLocalToGlobalMappingDestroy(&(*map)->mapping);
141: PetscFree((*map));
142: }
143: *map = NULL;
144: return(0);
145: }
147: /*@
148: PetscLayoutCreateFromRanges - Creates a new PetscLayout with the given ownership ranges and sets it up.
150: Collective
152: Input Parameters:
153: + comm - the MPI communicator
154: . range - the array of ownership ranges for each rank with length commsize+1
155: . mode - the copy mode for range
156: - bs - the block size (or PETSC_DECIDE)
158: Output Parameters:
159: . newmap - the new PetscLayout
161: Level: developer
163: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
164: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp(), PetscLayoutCreateFromSizes()
166: @*/
167: PetscErrorCode PetscLayoutCreateFromRanges(MPI_Comm comm,const PetscInt range[],PetscCopyMode mode,PetscInt bs,PetscLayout *newmap)
168: {
169: PetscLayout map;
170: PetscMPIInt rank;
174: MPI_Comm_rank(comm, &rank);
175: PetscLayoutCreate(comm, &map);
176: PetscLayoutSetBlockSize(map, bs);
177: switch (mode) {
178: case PETSC_COPY_VALUES:
179: PetscMalloc1(map->size+1, &map->range);
180: PetscArraycpy(map->range, range, map->size+1);
181: break;
182: case PETSC_USE_POINTER:
183: map->range_alloc = PETSC_FALSE;
184: default:
185: map->range = (PetscInt*) range;
186: break;
187: }
188: map->rstart = map->range[rank];
189: map->rend = map->range[rank+1];
190: map->n = map->rend - map->rstart;
191: map->N = map->range[map->size];
192: if (PetscDefined(USE_DEBUG)) { /* just check that n, N and bs are consistent */
193: PetscInt tmp;
194: MPIU_Allreduce(&map->n,&tmp,1,MPIU_INT,MPI_SUM,map->comm);
195: 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);
196: if (map->bs > 1) {
197: 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);
198: }
199: if (map->bs > 1) {
200: if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global size %D must be divisible by blocksize %D",map->N,map->bs);
201: }
202: }
203: /* lock the layout */
204: map->setupcalled = PETSC_TRUE;
205: map->oldn = map->n;
206: map->oldN = map->N;
207: map->oldbs = map->bs;
208: *newmap = map;
209: return(0);
210: }
212: /*@
213: PetscLayoutSetUp - given a map where you have set either the global or local
214: size sets up the map so that it may be used.
216: Collective
218: Input Parameters:
219: . map - pointer to the map
221: Level: developer
223: Notes:
224: Typical calling sequence
225: $ PetscLayoutCreate(MPI_Comm,PetscLayout *);
226: $ PetscLayoutSetBlockSize(PetscLayout,1);
227: $ PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
228: $ PetscLayoutSetUp(PetscLayout);
229: $ PetscLayoutGetSize(PetscLayout,PetscInt *);
231: If range exists, and local size is not set, everything gets computed from the range.
233: If the local size, global size are already set and range exists then this does nothing.
235: .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
236: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
237: @*/
238: PetscErrorCode PetscLayoutSetUp(PetscLayout map)
239: {
240: PetscMPIInt rank;
241: PetscInt p;
245: if (map->setupcalled && (map->n != map->oldn || map->N != map->oldN)) SETERRQ4(map->comm,PETSC_ERR_ARG_WRONGSTATE,"Layout is already setup with (local=%D,global=%D), cannot call setup again with (local=%D,global=%D)", map->oldn, map->oldN, map->n, map->N);
246: if (map->setupcalled) return(0);
248: if (map->n > 0 && map->bs > 1) {
249: 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);
250: }
251: if (map->N > 0 && map->bs > 1) {
252: if (map->N % map->bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global size %D must be divisible by blocksize %D",map->N,map->bs);
253: }
255: MPI_Comm_rank(map->comm, &rank);
256: if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
257: if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
258: PetscSplitOwnership(map->comm,&map->n,&map->N);
259: map->n = map->n*PetscAbs(map->bs);
260: map->N = map->N*PetscAbs(map->bs);
261: if (!map->range) {
262: PetscMalloc1(map->size+1, &map->range);
263: }
264: MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);
266: map->range[0] = 0;
267: for (p = 2; p <= map->size; p++) map->range[p] += map->range[p-1];
269: map->rstart = map->range[rank];
270: map->rend = map->range[rank+1];
272: /* lock the layout */
273: map->setupcalled = PETSC_TRUE;
274: map->oldn = map->n;
275: map->oldN = map->N;
276: map->oldbs = map->bs;
277: return(0);
278: }
280: /*@
281: PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
283: Collective on PetscLayout
285: Input Parameter:
286: . in - input PetscLayout to be duplicated
288: Output Parameter:
289: . out - the copy
291: Level: developer
293: Notes:
294: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
296: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
297: @*/
298: PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
299: {
301: MPI_Comm comm = in->comm;
304: PetscLayoutDestroy(out);
305: PetscLayoutCreate(comm,out);
306: PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));
307: if (in->range) {
308: PetscMalloc1((*out)->size+1,&(*out)->range);
309: PetscArraycpy((*out)->range,in->range,(*out)->size+1);
310: }
311: (*out)->refcnt = 0;
312: return(0);
313: }
315: /*@
316: PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
318: Collective on PetscLayout
320: Input Parameter:
321: . in - input PetscLayout to be copied
323: Output Parameter:
324: . out - the reference location
326: Level: developer
328: Notes:
329: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
331: If the out location already contains a PetscLayout it is destroyed
333: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
334: @*/
335: PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
336: {
340: in->refcnt++;
341: PetscLayoutDestroy(out);
342: *out = in;
343: return(0);
344: }
346: /*@
347: PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
349: Collective on PetscLayout
351: Input Parameter:
352: + in - input PetscLayout
353: - ltog - the local to global mapping
356: Level: developer
358: Notes:
359: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
361: If the ltog location already contains a PetscLayout it is destroyed
363: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
364: @*/
365: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
366: {
368: PetscInt bs;
371: ISLocalToGlobalMappingGetBlockSize(ltog,&bs);
372: if (in->bs > 0 && (bs != 1) && in->bs != bs) SETERRQ2(in->comm,PETSC_ERR_PLIB,"Blocksize of layout %D must match that of mapping %D (or the latter must be 1)",in->bs,bs);
373: PetscObjectReference((PetscObject)ltog);
374: ISLocalToGlobalMappingDestroy(&in->mapping);
375: in->mapping = ltog;
376: return(0);
377: }
379: /*@
380: PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
382: Collective on PetscLayout
384: Input Parameters:
385: + map - pointer to the map
386: - n - the local size
388: Level: developer
390: Notes:
391: Call this after the call to PetscLayoutCreate()
393: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
394: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
395: @*/
396: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
397: {
399: 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);
400: map->n = n;
401: return(0);
402: }
404: /*@C
405: PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
407: Not Collective
409: Input Parameters:
410: . map - pointer to the map
412: Output Parameters:
413: . n - the local size
415: Level: developer
417: Notes:
418: Call this after the call to PetscLayoutSetUp()
420: Fortran Notes:
421: Not available from Fortran
423: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
424: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
426: @*/
427: PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
428: {
430: *n = map->n;
431: return(0);
432: }
434: /*@
435: PetscLayoutSetSize - Sets the global size for a PetscLayout object.
437: Logically Collective on PetscLayout
439: Input Parameters:
440: + map - pointer to the map
441: - n - the global size
443: Level: developer
445: Notes:
446: Call this after the call to PetscLayoutCreate()
448: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
449: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
450: @*/
451: PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
452: {
454: map->N = n;
455: return(0);
456: }
458: /*@
459: PetscLayoutGetSize - Gets the global size for a PetscLayout object.
461: Not Collective
463: Input Parameters:
464: . map - pointer to the map
466: Output Parameters:
467: . n - the global size
469: Level: developer
471: Notes:
472: Call this after the call to PetscLayoutSetUp()
474: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
475: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
476: @*/
477: PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
478: {
480: *n = map->N;
481: return(0);
482: }
484: /*@
485: PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
487: Logically Collective on PetscLayout
489: Input Parameters:
490: + map - pointer to the map
491: - bs - the size
493: Level: developer
495: Notes:
496: Call this after the call to PetscLayoutCreate()
498: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
499: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
500: @*/
501: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
502: {
504: if (bs < 0) return(0);
505: 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);
506: if (map->mapping) {
507: PetscInt obs;
510: ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);
511: if (obs > 1) {
512: ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);
513: }
514: }
515: map->bs = bs;
516: return(0);
517: }
519: /*@
520: PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
522: Not Collective
524: Input Parameters:
525: . map - pointer to the map
527: Output Parameters:
528: . bs - the size
530: Level: developer
532: Notes:
533: Call this after the call to PetscLayoutSetUp()
535: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
536: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
537: @*/
538: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
539: {
541: *bs = PetscAbs(map->bs);
542: return(0);
543: }
545: /*@
546: PetscLayoutGetRange - gets the range of values owned by this process
548: Not Collective
550: Input Parameters:
551: . map - pointer to the map
553: Output Parameters:
554: + rstart - first index owned by this process
555: - rend - one more than the last index owned by this process
557: Level: developer
559: Notes:
560: Call this after the call to PetscLayoutSetUp()
562: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
563: PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
564: @*/
565: PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
566: {
568: if (rstart) *rstart = map->rstart;
569: if (rend) *rend = map->rend;
570: return(0);
571: }
573: /*@C
574: PetscLayoutGetRanges - gets the range of values owned by all processes
576: Not Collective
578: Input Parameters:
579: . map - pointer to the map
581: Output Parameters:
582: . range - start of each processors range of indices (the final entry is one more then the
583: last index on the last process)
585: Level: developer
587: Notes:
588: Call this after the call to PetscLayoutSetUp()
590: Fortran Notes:
591: Not available from Fortran
593: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
594: PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
596: @*/
597: PetscErrorCode PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
598: {
600: *range = map->range;
601: return(0);
602: }
604: /*@
605: PetscLayoutCompare - Compares two layouts
607: Not Collective
609: Input Parameters:
610: + mapa - pointer to the first map
611: - mapb - pointer to the second map
613: Output Parameters:
614: . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
616: Level: beginner
618: Notes:
620: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
621: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
622: @*/
623: PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
624: {
628: *congruent = PETSC_FALSE;
629: if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) {
630: PetscArraycmp(mapa->range,mapb->range,mapa->size+1,congruent);
631: }
632: return(0);
633: }