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