xref: /petsc/src/vec/is/utils/pmap.c (revision cd5eaeb712f0bc77bdce843018b541db19340d1f)
1 
2 /*
3    This file contains routines for basic map object implementation.
4 */
5 
6 #include <petscvec.h>
7 #include <petscsf.h>
8 
9 #undef __FUNCT__
10 #define __FUNCT__ "PetscLayoutCreate"
11 /*@C
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     Fortran Notes:
42       Not available from Fortran
43 
44 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
45           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
46 
47 @*/
48 PetscErrorCode  PetscLayoutCreate(MPI_Comm comm,PetscLayout *map)
49 {
50   PetscErrorCode ierr;
51 
52   PetscFunctionBegin;
53   ierr = PetscNew(map);CHKERRQ(ierr);
54 
55   (*map)->comm   = comm;
56   (*map)->bs     = -1;
57   (*map)->n      = -1;
58   (*map)->N      = -1;
59   (*map)->range  = 0;
60   (*map)->rstart = 0;
61   (*map)->rend   = 0;
62   PetscFunctionReturn(0);
63 }
64 
65 /*@C
66      PetscLayoutDestroy - Frees a map object and frees its range if that exists.
67 
68     Collective on MPI_Comm
69 
70    Input Parameters:
71 .    map - the PetscLayout
72 
73    Level: developer
74 
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     Fortran Notes:
79       Not available from Fortran
80 
81 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutCreate(),
82           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutSetUp()
83 
84 @*/
85 #undef __FUNCT__
86 #define __FUNCT__ "PetscLayoutDestroy"
87 PetscErrorCode  PetscLayoutDestroy(PetscLayout *map)
88 {
89   PetscErrorCode ierr;
90 
91   PetscFunctionBegin;
92   if (!*map) PetscFunctionReturn(0);
93   if (!(*map)->refcnt--) {
94     ierr = PetscFree((*map)->range);CHKERRQ(ierr);
95     ierr = ISLocalToGlobalMappingDestroy(&(*map)->mapping);CHKERRQ(ierr);
96     ierr = PetscFree((*map));CHKERRQ(ierr);
97   }
98   *map = NULL;
99   PetscFunctionReturn(0);
100 }
101 
102 /*@C
103      PetscLayoutSetUp - given a map where you have set either the global or local
104            size sets up the map so that it may be used.
105 
106     Collective on MPI_Comm
107 
108    Input Parameters:
109 .    map - pointer to the map
110 
111    Level: developer
112 
113     Notes: Typical calling sequence
114        PetscLayoutCreate(MPI_Comm,PetscLayout *);
115        PetscLayoutSetBlockSize(PetscLayout,1);
116        PetscLayoutSetSize(PetscLayout,n) or PetscLayoutSetLocalSize(PetscLayout,N); or both
117        PetscLayoutSetUp(PetscLayout);
118        PetscLayoutGetSize(PetscLayout,PetscInt *);
119 
120 
121        If the local size, global size are already set and range exists then this does nothing.
122 
123     Fortran Notes:
124       Not available from Fortran
125 
126 .seealso: PetscLayoutSetLocalSize(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayout, PetscLayoutDestroy(),
127           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize(), PetscLayoutCreate()
128 
129 @*/
130 #undef __FUNCT__
131 #define __FUNCT__ "PetscLayoutSetUp"
132 PetscErrorCode  PetscLayoutSetUp(PetscLayout map)
133 {
134   PetscMPIInt    rank,size;
135   PetscInt       p;
136   PetscErrorCode ierr;
137 
138   PetscFunctionBegin;
139   if ((map->n >= 0) && (map->N >= 0) && (map->range)) PetscFunctionReturn(0);
140 
141   ierr = MPI_Comm_size(map->comm, &size);CHKERRQ(ierr);
142   ierr = MPI_Comm_rank(map->comm, &rank);CHKERRQ(ierr);
143   if (map->n > 0) map->n = map->n/PetscAbs(map->bs);
144   if (map->N > 0) map->N = map->N/PetscAbs(map->bs);
145   ierr = PetscSplitOwnership(map->comm,&map->n,&map->N);CHKERRQ(ierr);
146   map->n = map->n*PetscAbs(map->bs);
147   map->N = map->N*PetscAbs(map->bs);
148   if (!map->range) {
149     ierr = PetscMalloc1(size+1, &map->range);CHKERRQ(ierr);
150   }
151   ierr = MPI_Allgather(&map->n, 1, MPIU_INT, map->range+1, 1, MPIU_INT, map->comm);CHKERRQ(ierr);
152 
153   map->range[0] = 0;
154   for (p = 2; p <= size; p++) map->range[p] += map->range[p-1];
155 
156   map->rstart = map->range[rank];
157   map->rend   = map->range[rank+1];
158   PetscFunctionReturn(0);
159 }
160 
161 #undef __FUNCT__
162 #define __FUNCT__ "PetscLayoutDuplicate"
163 /*@C
164 
165     PetscLayoutDuplicate - creates a new PetscLayout with the same information as a given one. If the PetscLayout already exists it is destroyed first.
166 
167      Collective on PetscLayout
168 
169     Input Parameter:
170 .     in - input PetscLayout to be duplicated
171 
172     Output Parameter:
173 .     out - the copy
174 
175    Level: developer
176 
177     Notes: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
178 
179 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutReference()
180 
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 /*@C
203 
204     PetscLayoutReference - Causes a PETSc Vec or Mat to share a PetscLayout with one that already exists. Used by Vec/MatDuplicate_XXX()
205 
206      Collective on PetscLayout
207 
208     Input Parameter:
209 .     in - input PetscLayout to be copied
210 
211     Output Parameter:
212 .     out - the reference location
213 
214    Level: developer
215 
216     Notes: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
217 
218     If the out location already contains a PetscLayout it is destroyed
219 
220 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
221 
222 @*/
223 PetscErrorCode  PetscLayoutReference(PetscLayout in,PetscLayout *out)
224 {
225   PetscErrorCode ierr;
226 
227   PetscFunctionBegin;
228   in->refcnt++;
229   ierr = PetscLayoutDestroy(out);CHKERRQ(ierr);
230   *out = in;
231   PetscFunctionReturn(0);
232 }
233 
234 #undef __FUNCT__
235 #define __FUNCT__ "PetscLayoutSetISLocalToGlobalMapping"
236 /*@C
237 
238     PetscLayoutSetISLocalToGlobalMapping - sets a ISLocalGlobalMapping into a PetscLayout
239 
240      Collective on PetscLayout
241 
242     Input Parameter:
243 +     in - input PetscLayout
244 -     ltog - the local to global mapping
245 
246 
247    Level: developer
248 
249     Notes: PetscLayoutSetUp() does not need to be called on the resulting PetscLayout
250 
251     If the ltog location already contains a PetscLayout it is destroyed
252 
253 .seealso: PetscLayoutCreate(), PetscLayoutDestroy(), PetscLayoutSetUp(), PetscLayoutDuplicate()
254 
255 @*/
256 PetscErrorCode  PetscLayoutSetISLocalToGlobalMapping(PetscLayout in,ISLocalToGlobalMapping ltog)
257 {
258   PetscErrorCode ierr;
259   PetscInt       bs;
260 
261   PetscFunctionBegin;
262   ierr = ISLocalToGlobalMappingGetBlockSize(ltog,&bs);CHKERRQ(ierr);
263   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);
264   ierr = PetscObjectReference((PetscObject)ltog);CHKERRQ(ierr);
265   ierr = ISLocalToGlobalMappingDestroy(&in->mapping);CHKERRQ(ierr);
266   in->mapping = ltog;
267   PetscFunctionReturn(0);
268 }
269 
270 /*@C
271      PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
272 
273     Collective on PetscLayout
274 
275    Input Parameters:
276 +    map - pointer to the map
277 -    n - the local size
278 
279    Level: developer
280 
281     Notes:
282        Call this after the call to PetscLayoutCreate()
283 
284     Fortran Notes:
285       Not available from Fortran
286 
287 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
288           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
289 
290 @*/
291 #undef __FUNCT__
292 #define __FUNCT__ "PetscLayoutSetLocalSize"
293 PetscErrorCode  PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
294 {
295   PetscFunctionBegin;
296   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);
297   map->n = n;
298   PetscFunctionReturn(0);
299 }
300 
301 /*@C
302      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
303 
304     Not Collective
305 
306    Input Parameters:
307 .    map - pointer to the map
308 
309    Output Parameters:
310 .    n - the local size
311 
312    Level: developer
313 
314     Notes:
315        Call this after the call to PetscLayoutSetUp()
316 
317     Fortran Notes:
318       Not available from Fortran
319 
320 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
321           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
322 
323 @*/
324 #undef __FUNCT__
325 #define __FUNCT__ "PetscLayoutGetLocalSize"
326 PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
327 {
328   PetscFunctionBegin;
329   *n = map->n;
330   PetscFunctionReturn(0);
331 }
332 
333 /*@C
334      PetscLayoutSetSize - Sets the global size for a PetscLayout object.
335 
336     Logically Collective on PetscLayout
337 
338    Input Parameters:
339 +    map - pointer to the map
340 -    n - the global size
341 
342    Level: developer
343 
344     Notes:
345        Call this after the call to PetscLayoutCreate()
346 
347     Fortran Notes:
348       Not available from Fortran
349 
350 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
351           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
352 
353 @*/
354 #undef __FUNCT__
355 #define __FUNCT__ "PetscLayoutSetSize"
356 PetscErrorCode  PetscLayoutSetSize(PetscLayout map,PetscInt n)
357 {
358   PetscFunctionBegin;
359   map->N = n;
360   PetscFunctionReturn(0);
361 }
362 
363 /*@C
364      PetscLayoutGetSize - Gets the global size for a PetscLayout object.
365 
366     Not Collective
367 
368    Input Parameters:
369 .    map - pointer to the map
370 
371    Output Parameters:
372 .    n - the global size
373 
374    Level: developer
375 
376     Notes:
377        Call this after the call to PetscLayoutSetUp()
378 
379     Fortran Notes:
380       Not available from Fortran
381 
382 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
383           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
384 
385 @*/
386 #undef __FUNCT__
387 #define __FUNCT__ "PetscLayoutGetSize"
388 PetscErrorCode  PetscLayoutGetSize(PetscLayout map,PetscInt *n)
389 {
390   PetscFunctionBegin;
391   *n = map->N;
392   PetscFunctionReturn(0);
393 }
394 
395 /*@C
396      PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
397 
398     Logically Collective on PetscLayout
399 
400    Input Parameters:
401 +    map - pointer to the map
402 -    bs - the size
403 
404    Level: developer
405 
406     Notes:
407        Call this after the call to PetscLayoutCreate()
408 
409     Fortran Notes:
410       Not available from Fortran
411 
412 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
413           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
414 
415 @*/
416 #undef __FUNCT__
417 #define __FUNCT__ "PetscLayoutSetBlockSize"
418 PetscErrorCode  PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
419 {
420   PetscFunctionBegin;
421   if (bs < 0) PetscFunctionReturn(0);
422   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);
423   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);
424   if (map->mapping) {
425     PetscInt       lbs;
426     PetscErrorCode ierr;
427 
428     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&lbs);CHKERRQ(ierr);
429     if (lbs != bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Blocksize of localtoglobalmapping %D must match that of layout %D",lbs,bs);
430   }
431   map->bs = bs;
432   PetscFunctionReturn(0);
433 }
434 
435 /*@C
436      PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
437 
438     Not Collective
439 
440    Input Parameters:
441 .    map - pointer to the map
442 
443    Output Parameters:
444 .    bs - the size
445 
446    Level: developer
447 
448     Notes:
449        Call this after the call to PetscLayoutSetUp()
450 
451     Fortran Notes:
452       Not available from Fortran
453 
454 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
455           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
456 
457 @*/
458 #undef __FUNCT__
459 #define __FUNCT__ "PetscLayoutGetBlockSize"
460 PetscErrorCode  PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
461 {
462   PetscFunctionBegin;
463   *bs = PetscAbs(map->bs);
464   PetscFunctionReturn(0);
465 }
466 
467 
468 /*@C
469      PetscLayoutGetRange - gets the range of values owned by this process
470 
471     Not Collective
472 
473    Input Parameters:
474 .    map - pointer to the map
475 
476    Output Parameters:
477 +    rstart - first index owned by this process
478 -    rend - one more than the last index owned by this process
479 
480    Level: developer
481 
482     Notes:
483        Call this after the call to PetscLayoutSetUp()
484 
485     Fortran Notes:
486       Not available from Fortran
487 
488 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
489           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
490 
491 @*/
492 #undef __FUNCT__
493 #define __FUNCT__ "PetscLayoutGetRange"
494 PetscErrorCode  PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
495 {
496   PetscFunctionBegin;
497   if (rstart) *rstart = map->rstart;
498   if (rend)   *rend   = map->rend;
499   PetscFunctionReturn(0);
500 }
501 
502 /*@C
503      PetscLayoutGetRanges - gets the range of values owned by all processes
504 
505     Not Collective
506 
507    Input Parameters:
508 .    map - pointer to the map
509 
510    Output Parameters:
511 .    range - start of each processors range of indices (the final entry is one more then the
512              last index on the last process)
513 
514    Level: developer
515 
516     Notes:
517        Call this after the call to PetscLayoutSetUp()
518 
519     Fortran Notes:
520       Not available from Fortran
521 
522 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
523           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
524 
525 @*/
526 #undef __FUNCT__
527 #define __FUNCT__ "PetscLayoutGetRanges"
528 PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
529 {
530   PetscFunctionBegin;
531   *range = map->range;
532   PetscFunctionReturn(0);
533 }
534 
535 #undef __FUNCT__
536 #define __FUNCT__ "PetscSFSetGraphLayout"
537 /*@C
538    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
539 
540    Collective
541 
542    Input Arguments:
543 +  sf - star forest
544 .  layout - PetscLayout defining the global space
545 .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
546 .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
547 -  iremote - remote locations of root vertices for each leaf on the current process
548 
549    Level: intermediate
550 
551 .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
552 @*/
553 PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
554 {
555   PetscErrorCode ierr;
556   PetscInt       i,nroots;
557   PetscSFNode    *remote;
558 
559   PetscFunctionBegin;
560   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
561   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
562   for (i=0; i<nleaves; i++) {
563     PetscInt owner = -1;
564     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
565     remote[i].rank  = owner;
566     remote[i].index = iremote[i] - layout->range[owner];
567   }
568   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
569   PetscFunctionReturn(0);
570 }
571 
572