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