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