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 Parameters:
352: + in - input PetscLayout
353: - ltog - the local to global mapping
355: Level: developer
357: Notes:
358: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
360: If the ltog location already contains a PetscLayout it is destroyed
362: .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
363: @*/
364: PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
365: {
367: PetscInt bs;
370: ISLocalToGlobalMappingGetBlockSize(ltog,&bs);
371: 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);
372: PetscObjectReference((PetscObject)ltog);
373: ISLocalToGlobalMappingDestroy(&in->mapping);
374: in->mapping = ltog;
375: return(0);
376: }
378: /*@
379: PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
381: Collective on PetscLayout
383: Input Parameters:
384: + map - pointer to the map
385: - n - the local size
387: Level: developer
389: Notes:
390: Call this after the call to PetscLayoutCreate()
392: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
393: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
394: @*/
395: PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
396: {
398: 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);
399: map->n = n;
400: return(0);
401: }
403: /*@C
404: PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
406: Not Collective
408: Input Parameters:
409: . map - pointer to the map
411: Output Parameters:
412: . n - the local size
414: Level: developer
416: Notes:
417: Call this after the call to PetscLayoutSetUp()
419: Fortran Notes:
420: Not available from Fortran
422: .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
423: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
425: @*/
426: PetscErrorCode PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
427: {
429: *n = map->n;
430: return(0);
431: }
433: /*@
434: PetscLayoutSetSize - Sets the global size for a PetscLayout object.
436: Logically Collective on PetscLayout
438: Input Parameters:
439: + map - pointer to the map
440: - n - the global size
442: Level: developer
444: Notes:
445: Call this after the call to PetscLayoutCreate()
447: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
448: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
449: @*/
450: PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
451: {
453: map->N = n;
454: return(0);
455: }
457: /*@
458: PetscLayoutGetSize - Gets the global size for a PetscLayout object.
460: Not Collective
462: Input Parameters:
463: . map - pointer to the map
465: Output Parameters:
466: . n - the global size
468: Level: developer
470: Notes:
471: Call this after the call to PetscLayoutSetUp()
473: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
474: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
475: @*/
476: PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
477: {
479: *n = map->N;
480: return(0);
481: }
483: /*@
484: PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
486: Logically Collective on PetscLayout
488: Input Parameters:
489: + map - pointer to the map
490: - bs - the size
492: Level: developer
494: Notes:
495: Call this after the call to PetscLayoutCreate()
497: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
498: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
499: @*/
500: PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
501: {
503: if (bs < 0) return(0);
504: 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);
505: if (map->mapping) {
506: PetscInt obs;
509: ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);
510: if (obs > 1) {
511: ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);
512: }
513: }
514: map->bs = bs;
515: return(0);
516: }
518: /*@
519: PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
521: Not Collective
523: Input Parameters:
524: . map - pointer to the map
526: Output Parameters:
527: . bs - the size
529: Level: developer
531: Notes:
532: Call this after the call to PetscLayoutSetUp()
534: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
535: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
536: @*/
537: PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
538: {
540: *bs = PetscAbs(map->bs);
541: return(0);
542: }
544: /*@
545: PetscLayoutGetRange - gets the range of values owned by this process
547: Not Collective
549: Input Parameter:
550: . map - pointer to the map
552: Output Parameters:
553: + rstart - first index owned by this process
554: - rend - one more than the last index owned by this process
556: Level: developer
558: Notes:
559: Call this after the call to PetscLayoutSetUp()
561: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
562: PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
563: @*/
564: PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
565: {
567: if (rstart) *rstart = map->rstart;
568: if (rend) *rend = map->rend;
569: return(0);
570: }
572: /*@C
573: PetscLayoutGetRanges - gets the range of values owned by all processes
575: Not Collective
577: Input Parameters:
578: . map - pointer to the map
580: Output Parameters:
581: . range - start of each processors range of indices (the final entry is one more then the
582: last index on the last process)
584: Level: developer
586: Notes:
587: Call this after the call to PetscLayoutSetUp()
589: Fortran Notes:
590: Not available from Fortran
592: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
593: PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
595: @*/
596: PetscErrorCode PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
597: {
599: *range = map->range;
600: return(0);
601: }
603: /*@
604: PetscLayoutCompare - Compares two layouts
606: Not Collective
608: Input Parameters:
609: + mapa - pointer to the first map
610: - mapb - pointer to the second map
612: Output Parameters:
613: . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
615: Level: beginner
617: Notes:
619: .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
620: PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
621: @*/
622: PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
623: {
627: *congruent = PETSC_FALSE;
628: if (mapa->N == mapb->N && mapa->range && mapb->range && mapa->size == mapb->size) {
629: PetscArraycmp(mapa->range,mapb->range,mapa->size+1,congruent);
630: }
631: return(0);
632: }