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