xref: /petsc/src/vec/is/utils/pmap.c (revision 7ae38d14048e535a346ba522ffbdb8e04ba6fa16)
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     PetscInt       obs;
401     PetscErrorCode ierr;
402 
403     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&obs);CHKERRQ(ierr);
404     if (obs > 1) {
405       ierr = ISLocalToGlobalMappingSetBlockSize(map->mapping,bs);CHKERRQ(ierr);
406     }
407   }
408   map->bs = bs;
409   PetscFunctionReturn(0);
410 }
411 
412 #undef __FUNCT__
413 #define __FUNCT__ "PetscLayoutGetBlockSize"
414 /*@
415   PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
416 
417   Not Collective
418 
419   Input Parameters:
420 . map - pointer to the map
421 
422   Output Parameters:
423 . bs - the size
424 
425   Level: developer
426 
427   Notes:
428   Call this after the call to PetscLayoutSetUp()
429 
430 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
431           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
432 @*/
433 PetscErrorCode PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
434 {
435   PetscFunctionBegin;
436   *bs = PetscAbs(map->bs);
437   PetscFunctionReturn(0);
438 }
439 
440 #undef __FUNCT__
441 #define __FUNCT__ "PetscLayoutGetRange"
442 /*@
443   PetscLayoutGetRange - gets the range of values owned by this process
444 
445   Not Collective
446 
447   Input Parameters:
448 . map - pointer to the map
449 
450   Output Parameters:
451 + rstart - first index owned by this process
452 - rend   - one more than the last index owned by this process
453 
454   Level: developer
455 
456   Notes:
457   Call this after the call to PetscLayoutSetUp()
458 
459 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
460           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
461 @*/
462 PetscErrorCode PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
463 {
464   PetscFunctionBegin;
465   if (rstart) *rstart = map->rstart;
466   if (rend)   *rend   = map->rend;
467   PetscFunctionReturn(0);
468 }
469 
470 /*@C
471      PetscLayoutGetRanges - gets the range of values owned by all processes
472 
473     Not Collective
474 
475    Input Parameters:
476 .    map - pointer to the map
477 
478    Output Parameters:
479 .    range - start of each processors range of indices (the final entry is one more then the
480              last index on the last process)
481 
482    Level: developer
483 
484     Notes:
485        Call this after the call to PetscLayoutSetUp()
486 
487     Fortran Notes:
488       Not available from Fortran
489 
490 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
491           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
492 
493 @*/
494 #undef __FUNCT__
495 #define __FUNCT__ "PetscLayoutGetRanges"
496 PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
497 {
498   PetscFunctionBegin;
499   *range = map->range;
500   PetscFunctionReturn(0);
501 }
502 
503 #undef __FUNCT__
504 #define __FUNCT__ "PetscSFSetGraphLayout"
505 /*@C
506    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
507 
508    Collective
509 
510    Input Arguments:
511 +  sf - star forest
512 .  layout - PetscLayout defining the global space
513 .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
514 .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
515 -  iremote - remote locations of root vertices for each leaf on the current process
516 
517    Level: intermediate
518 
519 .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
520 @*/
521 PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
522 {
523   PetscErrorCode ierr;
524   PetscInt       i,nroots;
525   PetscSFNode    *remote;
526 
527   PetscFunctionBegin;
528   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
529   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
530   for (i=0; i<nleaves; i++) {
531     PetscInt owner = -1;
532     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
533     remote[i].rank  = owner;
534     remote[i].index = iremote[i] - layout->range[owner];
535   }
536   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
537   PetscFunctionReturn(0);
538 }
539 
540 #undef __FUNCT__
541 #define __FUNCT__ "PetscLayoutCompare"
542 /*@
543   PetscLayoutCompare - Compares two layouts
544 
545   Not Collective
546 
547   Input Parameters:
548 + mapa - pointer to the first map
549 - mapb - pointer to the second map
550 
551   Output Parameters:
552 . congruent - PETSC_TRUE if the two layouts are congruent, PETSC_FALSE otherwise
553 
554   Level: beginner
555 
556   Notes:
557 
558 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
559           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
560 @*/
561 PetscErrorCode PetscLayoutCompare(PetscLayout mapa,PetscLayout mapb,PetscBool *congruent)
562 {
563   PetscErrorCode ierr;
564   PetscMPIInt    sizea,sizeb;
565 
566   PetscFunctionBegin;
567   *congruent = PETSC_FALSE;
568   ierr = MPI_Comm_size(mapa->comm,&sizea);CHKERRQ(ierr);
569   ierr = MPI_Comm_size(mapb->comm,&sizeb);CHKERRQ(ierr);
570   if (mapa->N == mapb->N && mapa->range && mapb->range && sizea == sizeb) {
571     ierr = PetscMemcmp(mapa->range,mapb->range,(sizea+1)*sizeof(PetscInt),congruent);CHKERRQ(ierr);
572   }
573   PetscFunctionReturn(0);
574 }
575