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