xref: /petsc/src/vec/is/utils/pmap.c (revision 285fb4e2b69b3de46a0633bd0adc6a7f684caa1e)
1 
2 /*
3    This file contains routines for basic map object implementation.
4 */
5 
6 #include <petscis.h> /*I "petscis.h" I*/
7 #include <petscsf.h>
8 
9 /*@
10   PetscLayoutCreate - Allocates PetscLayout space and sets the map contents to the default.
11 
12   Collective on MPI_Comm
13 
14   Input Parameters:
15 + comm - the MPI communicator
16 - map - pointer to the map
17 
18   Level: advanced
19 
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:
29 
30 + PetscLayoutGetSize(PetscLayout,PetscInt *);
31 . PetscLayoutGetLocalSize(PetscLayout,PetscInt *);
32 . PetscLayoutGetRange(PetscLayout,PetscInt *rstart,PetscInt *rend);
33 . PetscLayoutGetRanges(PetscLayout,const PetscInt *range[]);
34 - PetscLayoutDestroy(PetscLayout*);
35 
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.
38 
39 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
40           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
41 
42 @*/
43 PetscErrorCode PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
44 {
45   PetscErrorCode ierr;
46 
47   PetscFunctionBegin;
48   ierr = PetscNew(map);CHKERRQ(ierr);
49 
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   PetscFunctionReturn(0);
58 }
59 
60 /*@
61   PetscLayoutDestroy - Frees a map object and frees its range if that exists.
62 
63   Collective on MPI_Comm
64 
65   Input Parameters:
66 . map - the PetscLayout
67 
68   Level: developer
69 
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.
73 
74 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(),
75           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
76 
77 @*/
78 PetscErrorCode PetscLayoutDestroy(PetscLayout *map)
79 {
80   PetscErrorCode ierr;
81 
82   PetscFunctionBegin;
83   if (!*map) PetscFunctionReturn(0);
84   if (!(*map)->refcnt--) {
85     ierr = PetscFree((*map)->range);CHKERRQ(ierr);
86     ierr = ISLocalToGlobalMappingDestroy(&(*map)->mapping);CHKERRQ(ierr);
87     ierr = PetscFree((*map));CHKERRQ(ierr);
88   }
89   *map = NULL;
90   PetscFunctionReturn(0);
91 }
92 
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.
96 
97   Collective on MPI_Comm
98 
99   Input Parameters:
100 . map - pointer to the map
101 
102   Level: developer
103 
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 *);
111 
112 
113   If the local size, global size are already set and range exists then this does nothing.
114 
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;
122   PetscErrorCode ierr;
123 
124   PetscFunctionBegin;
125   if ((map->n >= 0) && (map->N >= 0) && (map->range)) PetscFunctionReturn(0);
126 
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   }
133 
134   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
135   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
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   ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr);
139   map->n = map->n*PetscAbs(map->bs);
140   map->N = map->N*PetscAbs(map->bs);
141   if (!map->range) {
142     ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
143   }
144   ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRQ(ierr);
145 
146   map->range[0] = 0;
147   for (p = 2; p <= size; p++) map->range[p] += map->range[p-1];
148 
149   map->rstart = map->range[rank];
150   map->rend   = map->range[rank+1];
151   PetscFunctionReturn(0);
152 }
153 
154 /*@
155   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
156 
157   Collective on PetscLayout
158 
159   Input Parameter:
160 . in - input PetscLayout to be duplicated
161 
162   Output Parameter:
163 . out - the copy
164 
165   Level: developer
166 
167   Notes:
168     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
169 
170 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
171 @*/
172 PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
173 {
174   PetscMPIInt    size;
175   PetscErrorCode ierr;
176   MPI_Comm       comm = in->comm;
177 
178   PetscFunctionBegin;
179   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
180   ierr = PetscLayoutCreate(comm,out);CHKERRQ(ierr);
181   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
182   ierr = PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));CHKERRQ(ierr);
183   ierr = PetscMalloc1(size+1,&(*out)->range);CHKERRQ(ierr);
184   ierr = PetscMemcpy((*out)->range,in->range,(size+1)*sizeof(PetscInt));CHKERRQ(ierr);
185 
186   (*out)->refcnt = 0;
187   PetscFunctionReturn(0);
188 }
189 
190 /*@
191   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
192 
193   Collective on PetscLayout
194 
195   Input Parameter:
196 . in - input PetscLayout to be copied
197 
198   Output Parameter:
199 . out - the reference location
200 
201   Level: developer
202 
203   Notes:
204     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
205 
206   If the out location already contains a PetscLayout it is destroyed
207 
208 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
209 @*/
210 PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
211 {
212   PetscErrorCode ierr;
213 
214   PetscFunctionBegin;
215   in->refcnt++;
216   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
217   *out = in;
218   PetscFunctionReturn(0);
219 }
220 
221 /*@
222   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
223 
224   Collective on PetscLayout
225 
226   Input Parameter:
227 + in - input PetscLayout
228 - ltog - the local to global mapping
229 
230 
231   Level: developer
232 
233   Notes:
234     PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
235 
236   If the ltog location already contains a PetscLayout it is destroyed
237 
238 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
239 @*/
240 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
241 {
242   PetscErrorCode ierr;
243   PetscInt       bs;
244 
245   PetscFunctionBegin;
246   ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr);
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   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
249   ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr);
250   in->mapping = ltog;
251   PetscFunctionReturn(0);
252 }
253 
254 /*@
255   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
256 
257   Collective on PetscLayout
258 
259   Input Parameters:
260 + map - pointer to the map
261 - n - the local size
262 
263   Level: developer
264 
265   Notes:
266   Call this after the call to PetscLayoutCreate()
267 
268 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
269           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
270 @*/
271 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
272 {
273   PetscFunctionBegin;
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   PetscFunctionReturn(0);
277 }
278 
279 /*@C
280      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
281 
282     Not Collective
283 
284    Input Parameters:
285 .    map - pointer to the map
286 
287    Output Parameters:
288 .    n - the local size
289 
290    Level: developer
291 
292     Notes:
293        Call this after the call to PetscLayoutSetUp()
294 
295     Fortran Notes:
296       Not available from Fortran
297 
298 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
299           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
300 
301 @*/
302 PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
303 {
304   PetscFunctionBegin;
305   *n = map->n;
306   PetscFunctionReturn(0);
307 }
308 
309 /*@
310   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
311 
312   Logically Collective on PetscLayout
313 
314   Input Parameters:
315 + map - pointer to the map
316 - n - the global size
317 
318   Level: developer
319 
320   Notes:
321   Call this after the call to PetscLayoutCreate()
322 
323 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
324           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
325 @*/
326 PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
327 {
328   PetscFunctionBegin;
329   map->N = n;
330   PetscFunctionReturn(0);
331 }
332 
333 /*@
334   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
335 
336   Not Collective
337 
338   Input Parameters:
339 . map - pointer to the map
340 
341   Output Parameters:
342 . n - the global size
343 
344   Level: developer
345 
346   Notes:
347   Call this after the call to PetscLayoutSetUp()
348 
349 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
350           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
351 @*/
352 PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
353 {
354   PetscFunctionBegin;
355   *n = map->N;
356   PetscFunctionReturn(0);
357 }
358 
359 /*@
360   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
361 
362   Logically Collective on PetscLayout
363 
364   Input Parameters:
365 + map - pointer to the map
366 - bs - the size
367 
368   Level: developer
369 
370   Notes:
371   Call this after the call to PetscLayoutCreate()
372 
373 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
374           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
375 @*/
376 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
377 {
378   PetscFunctionBegin;
379   if (bs < 0) PetscFunctionReturn(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;
383     PetscErrorCode ierr;
384 
385     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);CHKERRQ(ierr);
386     if (obs > 1) {
387       ierr = ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);CHKERRQ(ierr);
388     }
389   }
390   map->bs = bs;
391   PetscFunctionReturn(0);
392 }
393 
394 /*@
395   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
396 
397   Not Collective
398 
399   Input Parameters:
400 . map - pointer to the map
401 
402   Output Parameters:
403 . bs - the size
404 
405   Level: developer
406 
407   Notes:
408   Call this after the call to PetscLayoutSetUp()
409 
410 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
411           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
412 @*/
413 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
414 {
415   PetscFunctionBegin;
416   *bs = PetscAbs(map->bs);
417   PetscFunctionReturn(0);
418 }
419 
420 /*@
421   PetscLayoutGetRange - gets the range of values owned by this process
422 
423   Not Collective
424 
425   Input Parameters:
426 . map - pointer to the map
427 
428   Output Parameters:
429 + rstart - first index owned by this process
430 - rend   - one more than the last index owned by this process
431 
432   Level: developer
433 
434   Notes:
435   Call this after the call to PetscLayoutSetUp()
436 
437 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
438           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
439 @*/
440 PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
441 {
442   PetscFunctionBegin;
443   if (rstart) *rstart = map->rstart;
444   if (rend)   *rend   = map->rend;
445   PetscFunctionReturn(0);
446 }
447 
448 /*@C
449      PetscLayoutGetRanges - gets the range of values owned by all processes
450 
451     Not Collective
452 
453    Input Parameters:
454 .    map - pointer to the map
455 
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)
459 
460    Level: developer
461 
462     Notes:
463        Call this after the call to PetscLayoutSetUp()
464 
465     Fortran Notes:
466       Not available from Fortran
467 
468 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
469           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
470 
471 @*/
472 PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
473 {
474   PetscFunctionBegin;
475   *range = map->range;
476   PetscFunctionReturn(0);
477 }
478 
479 /*@C
480    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
481 
482    Collective
483 
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
491 
492    Level: intermediate
493 
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
497 
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 {
502   PetscErrorCode ierr;
503   PetscInt       i,nroots;
504   PetscSFNode    *remote;
505 
506   PetscFunctionBegin;
507   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
508   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
509   for (i=0; i<nleaves; i++) {
510     PetscInt owner = -1;
511     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
512     remote[i].rank  = owner;
513     remote[i].index = iremote[i] - layout->range[owner];
514   }
515   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
516   PetscFunctionReturn(0);
517 }
518 
519 /*@
520   PetscLayoutCompare - Compares two layouts
521 
522   Not Collective
523 
524   Input Parameters:
525 + mapa - pointer to the first map
526 - mapb - pointer to the second map
527 
528   Output Parameters:
529 . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
530 
531   Level: beginner
532 
533   Notes:
534 
535 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
536           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
537 @*/
538 PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
539 {
540   PetscErrorCode ierr;
541   PetscMPIInt    sizea,sizeb;
542 
543   PetscFunctionBegin;
544   *congruent = PETSC_FALSE;
545   ierr = MPI_Comm_size(mapa->comm,&sizea);CHKERRQ(ierr);
546   ierr = MPI_Comm_size(mapb->comm,&sizeb);CHKERRQ(ierr);
547   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
548     ierr = PetscMemcmp(mapa->range,mapb->range,(sizea+1)*sizeof(PetscInt),congruent);CHKERRQ(ierr);
549   }
550   PetscFunctionReturn(0);
551 }
552