xref: /petsc/src/vec/is/utils/pmap.c (revision bb1d7374b64f295b2ed5ff23b89435d65e905a54)
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  = 0;
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) {
134       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Local matrix size %D must be divisible by blocksize %D",map->n,map->bs);
135     }
136   }
137   if (map->N > 0 && map->bs > 1) {
138     if (map->N % map->bs) {
139       SETERRQ2(map->comm,PETSC_ERR_PLIB,"Global matrix size %D must be divisible by blocksize %D",map->N,map->bs);
140     }
141   }
142 
143   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
144   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
145   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
146   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
147   ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr);
148   map->n = map->n*PetscAbs(map->bs);
149   map->N = map->N*PetscAbs(map->bs);
150   if (!map->range) {
151     ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
152   }
153   ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRQ(ierr);
154 
155   map->range[0] = 0;
156   for (p = 2; p <= size; p++) map->range[p] += map->range[p-1];
157 
158   map->rstart = map->range[rank];
159   map->rend   = map->range[rank+1];
160   PetscFunctionReturn(0);
161 }
162 
163 #undef __FUNCT__
164 #define __FUNCT__ "PetscLayoutDuplicate"
165 /*@
166   PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
167 
168   Collective on PetscLayout
169 
170   Input Parameter:
171 . in - input PetscLayout to be duplicated
172 
173   Output Parameter:
174 . out - the copy
175 
176   Level: developer
177 
178   Notes: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
179 
180 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
181 @*/
182 PetscErrorCode PetscLayoutDuplicate(PetscLayout in,PetscLayout *out)
183 {
184   PetscMPIInt    size;
185   PetscErrorCode ierr;
186   MPI_Comm       comm = in->comm;
187 
188   PetscFunctionBegin;
189   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
190   ierr = PetscLayoutCreate(comm,out);CHKERRQ(ierr);
191   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
192   ierr = PetscMemcpy(*out,in,sizeof(struct _n_PetscLayout));CHKERRQ(ierr);
193   ierr = PetscMalloc1(size+1,&(*out)->range);CHKERRQ(ierr);
194   ierr = PetscMemcpy((*out)->range,in->range,(size+1)*sizeof(PetscInt));CHKERRQ(ierr);
195 
196   (*out)->refcnt = 0;
197   PetscFunctionReturn(0);
198 }
199 
200 #undef __FUNCT__
201 #define __FUNCT__ "PetscLayoutReference"
202 /*@
203   PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
204 
205   Collective on PetscLayout
206 
207   Input Parameter:
208 . in - input PetscLayout to be copied
209 
210   Output Parameter:
211 . out - the reference location
212 
213   Level: developer
214 
215   Notes: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
216 
217   If the out location already contains a PetscLayout it is destroyed
218 
219 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
220 @*/
221 PetscErrorCode PetscLayoutReference(PetscLayout in,PetscLayout *out)
222 {
223   PetscErrorCode ierr;
224 
225   PetscFunctionBegin;
226   in->refcnt++;
227   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
228   *out = in;
229   PetscFunctionReturn(0);
230 }
231 
232 #undef __FUNCT__
233 #define __FUNCT__ "PetscLayoutSetISLocalToGlobalMapping"
234 /*@
235   PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
236 
237   Collective on PetscLayout
238 
239   Input Parameter:
240 + in - input PetscLayout
241 - ltog - the local to global mapping
242 
243 
244   Level: developer
245 
246   Notes: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
247 
248   If the ltog location already contains a PetscLayout it is destroyed
249 
250 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
251 @*/
252 PetscErrorCode PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
253 {
254   PetscErrorCode ierr;
255   PetscInt       bs;
256 
257   PetscFunctionBegin;
258   ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr);
259   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);
260   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
261   ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr);
262   in->mapping = ltog;
263   PetscFunctionReturn(0);
264 }
265 
266 #undef __FUNCT__
267 #define __FUNCT__ "PetscLayoutSetLocalSize"
268 /*@
269   PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
270 
271   Collective on PetscLayout
272 
273   Input Parameters:
274 + map - pointer to the map
275 - n - the local size
276 
277   Level: developer
278 
279   Notes:
280   Call this after the call to PetscLayoutCreate()
281 
282 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
283           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
284 @*/
285 PetscErrorCode PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
286 {
287   PetscFunctionBegin;
288   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);
289   map->n = n;
290   PetscFunctionReturn(0);
291 }
292 
293 /*@C
294      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
295 
296     Not Collective
297 
298    Input Parameters:
299 .    map - pointer to the map
300 
301    Output Parameters:
302 .    n - the local size
303 
304    Level: developer
305 
306     Notes:
307        Call this after the call to PetscLayoutSetUp()
308 
309     Fortran Notes:
310       Not available from Fortran
311 
312 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
313           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
314 
315 @*/
316 #undef __FUNCT__
317 #define __FUNCT__ "PetscLayoutGetLocalSize"
318 PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
319 {
320   PetscFunctionBegin;
321   *n = map->n;
322   PetscFunctionReturn(0);
323 }
324 
325 #undef __FUNCT__
326 #define __FUNCT__ "PetscLayoutSetSize"
327 /*@
328   PetscLayoutSetSize - Sets the global size for a PetscLayout object.
329 
330   Logically Collective on PetscLayout
331 
332   Input Parameters:
333 + map - pointer to the map
334 - n - the global size
335 
336   Level: developer
337 
338   Notes:
339   Call this after the call to PetscLayoutCreate()
340 
341 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
342           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
343 @*/
344 PetscErrorCode PetscLayoutSetSize(PetscLayout map,PetscInt n)
345 {
346   PetscFunctionBegin;
347   map->N = n;
348   PetscFunctionReturn(0);
349 }
350 
351 #undef __FUNCT__
352 #define __FUNCT__ "PetscLayoutGetSize"
353 /*@
354   PetscLayoutGetSize - Gets the global size for a PetscLayout object.
355 
356   Not Collective
357 
358   Input Parameters:
359 . map - pointer to the map
360 
361   Output Parameters:
362 . n - the global size
363 
364   Level: developer
365 
366   Notes:
367   Call this after the call to PetscLayoutSetUp()
368 
369 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
370           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
371 @*/
372 PetscErrorCode PetscLayoutGetSize(PetscLayout map,PetscInt *n)
373 {
374   PetscFunctionBegin;
375   *n = map->N;
376   PetscFunctionReturn(0);
377 }
378 
379 #undef __FUNCT__
380 #define __FUNCT__ "PetscLayoutSetBlockSize"
381 /*@
382   PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
383 
384   Logically Collective on PetscLayout
385 
386   Input Parameters:
387 + map - pointer to the map
388 - bs - the size
389 
390   Level: developer
391 
392   Notes:
393   Call this after the call to PetscLayoutCreate()
394 
395 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
396           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
397 @*/
398 PetscErrorCode PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
399 {
400   PetscFunctionBegin;
401   if (bs < 0) PetscFunctionReturn(0);
402   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);
403   if (map->range && map->bs > 0 && map->bs != bs) SETERRQ2(map->comm,PETSC_ERR_ARG_INCOMP,"Cannot change block size %D to %D",map->bs,bs);
404   if (map->mapping) {
405     PetscInt       lbs;
406     PetscErrorCode ierr;
407 
408     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&lbs);CHKERRQ(ierr);
409     if (lbs != bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Blocksize of localtoglobalmapping %D must match that of layout %D",lbs,bs);
410   }
411   map->bs = bs;
412   PetscFunctionReturn(0);
413 }
414 
415 #undef __FUNCT__
416 #define __FUNCT__ "PetscLayoutGetBlockSize"
417 /*@
418   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
419 
420   Not Collective
421 
422   Input Parameters:
423 . map - pointer to the map
424 
425   Output Parameters:
426 . bs - the size
427 
428   Level: developer
429 
430   Notes:
431   Call this after the call to PetscLayoutSetUp()
432 
433 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
434           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
435 @*/
436 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
437 {
438   PetscFunctionBegin;
439   *bs = PetscAbs(map->bs);
440   PetscFunctionReturn(0);
441 }
442 
443 #undef __FUNCT__
444 #define __FUNCT__ "PetscLayoutGetRange"
445 /*@
446   PetscLayoutGetRange - gets the range of values owned by this process
447 
448   Not Collective
449 
450   Input Parameters:
451 . map - pointer to the map
452 
453   Output Parameters:
454 + rstart - first index owned by this process
455 - rend   - one more than the last index owned by this process
456 
457   Level: developer
458 
459   Notes:
460   Call this after the call to PetscLayoutSetUp()
461 
462 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
463           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
464 @*/
465 PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
466 {
467   PetscFunctionBegin;
468   if (rstart) *rstart = map->rstart;
469   if (rend)   *rend   = map->rend;
470   PetscFunctionReturn(0);
471 }
472 
473 /*@C
474      PetscLayoutGetRanges - gets the range of values owned by all processes
475 
476     Not Collective
477 
478    Input Parameters:
479 .    map - pointer to the map
480 
481    Output Parameters:
482 .    range - start of each processors range of indices (the final entry is one more then the
483              last index on the last process)
484 
485    Level: developer
486 
487     Notes:
488        Call this after the call to PetscLayoutSetUp()
489 
490     Fortran Notes:
491       Not available from Fortran
492 
493 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
494           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
495 
496 @*/
497 #undef __FUNCT__
498 #define __FUNCT__ "PetscLayoutGetRanges"
499 PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
500 {
501   PetscFunctionBegin;
502   *range = map->range;
503   PetscFunctionReturn(0);
504 }
505 
506 #undef __FUNCT__
507 #define __FUNCT__ "PetscSFSetGraphLayout"
508 /*@C
509    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
510 
511    Collective
512 
513    Input Arguments:
514 +  sf - star forest
515 .  layout - PetscLayout defining the global space
516 .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
517 .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
518 -  iremote - remote locations of root vertices for each leaf on the current process
519 
520    Level: intermediate
521 
522 .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
523 @*/
524 PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
525 {
526   PetscErrorCode ierr;
527   PetscInt       i,nroots;
528   PetscSFNode    *remote;
529 
530   PetscFunctionBegin;
531   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
532   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
533   for (i=0; i<nleaves; i++) {
534     PetscInt owner = -1;
535     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
536     remote[i].rank  = owner;
537     remote[i].index = iremote[i] - layout->range[owner];
538   }
539   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
540   PetscFunctionReturn(0);
541 }
542 
543