xref: /petsc/src/vec/is/utils/pmap.c (revision fe998a80077c9ee0917a39496df43fc256e1b478)
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   in->mapping = ltog;
276   PetscFunctionReturn(0);
277 }
278 
279 /*@C
280      PetscLayoutSetLocalSize - Sets the local size for a PetscLayout object.
281 
282     Collective on PetscLayout
283 
284    Input Parameters:
285 +    map - pointer to the map
286 -    n - the local size
287 
288    Level: developer
289 
290     Notes:
291        Call this after the call to PetscLayoutCreate()
292 
293     Fortran Notes:
294       Not available from Fortran
295 
296 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
297           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
298 
299 @*/
300 #undef __FUNCT__
301 #define __FUNCT__ "PetscLayoutSetLocalSize"
302 PetscErrorCode  PetscLayoutSetLocalSize(PetscLayout map,PetscInt n)
303 {
304   PetscFunctionBegin;
305   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);
306   map->n = n;
307   PetscFunctionReturn(0);
308 }
309 
310 /*@C
311      PetscLayoutGetLocalSize - Gets the local size for a PetscLayout object.
312 
313     Not Collective
314 
315    Input Parameters:
316 .    map - pointer to the map
317 
318    Output Parameters:
319 .    n - the local size
320 
321    Level: developer
322 
323     Notes:
324        Call this after the call to PetscLayoutSetUp()
325 
326     Fortran Notes:
327       Not available from Fortran
328 
329 .seealso: PetscLayoutCreate(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutGetLocalSize(), PetscLayoutSetUp()
330           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
331 
332 @*/
333 #undef __FUNCT__
334 #define __FUNCT__ "PetscLayoutGetLocalSize"
335 PetscErrorCode  PetscLayoutGetLocalSize(PetscLayout map,PetscInt *n)
336 {
337   PetscFunctionBegin;
338   *n = map->n;
339   PetscFunctionReturn(0);
340 }
341 
342 /*@C
343      PetscLayoutSetSize - Sets the global size for a PetscLayout object.
344 
345     Logically Collective on PetscLayout
346 
347    Input Parameters:
348 +    map - pointer to the map
349 -    n - the global size
350 
351    Level: developer
352 
353     Notes:
354        Call this after the call to PetscLayoutCreate()
355 
356     Fortran Notes:
357       Not available from Fortran
358 
359 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
360           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
361 
362 @*/
363 #undef __FUNCT__
364 #define __FUNCT__ "PetscLayoutSetSize"
365 PetscErrorCode  PetscLayoutSetSize(PetscLayout map,PetscInt n)
366 {
367   PetscFunctionBegin;
368   map->N = n;
369   PetscFunctionReturn(0);
370 }
371 
372 /*@C
373      PetscLayoutGetSize - Gets the global size for a PetscLayout object.
374 
375     Not Collective
376 
377    Input Parameters:
378 .    map - pointer to the map
379 
380    Output Parameters:
381 .    n - the global size
382 
383    Level: developer
384 
385     Notes:
386        Call this after the call to PetscLayoutSetUp()
387 
388     Fortran Notes:
389       Not available from Fortran
390 
391 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
392           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetBlockSize()
393 
394 @*/
395 #undef __FUNCT__
396 #define __FUNCT__ "PetscLayoutGetSize"
397 PetscErrorCode  PetscLayoutGetSize(PetscLayout map,PetscInt *n)
398 {
399   PetscFunctionBegin;
400   *n = map->N;
401   PetscFunctionReturn(0);
402 }
403 
404 /*@C
405      PetscLayoutSetBlockSize - Sets the block size for a PetscLayout object.
406 
407     Logically Collective on PetscLayout
408 
409    Input Parameters:
410 +    map - pointer to the map
411 -    bs - the size
412 
413    Level: developer
414 
415     Notes:
416        Call this after the call to PetscLayoutCreate()
417 
418     Fortran Notes:
419       Not available from Fortran
420 
421 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutGetBlockSize(),
422           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
423 
424 @*/
425 #undef __FUNCT__
426 #define __FUNCT__ "PetscLayoutSetBlockSize"
427 PetscErrorCode  PetscLayoutSetBlockSize(PetscLayout map,PetscInt bs)
428 {
429   PetscFunctionBegin;
430   if (bs < 0) PetscFunctionReturn(0);
431   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);
432   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);
433   if (map->mapping) {
434     PetscInt       lbs;
435     PetscErrorCode ierr;
436 
437     ierr = ISLocalToGlobalMappingGetBlockSize(map->mapping,&lbs);CHKERRQ(ierr);
438     if (lbs != bs) SETERRQ2(map->comm,PETSC_ERR_PLIB,"Blocksize of localtoglobalmapping %D must match that of layout %D",lbs,bs);
439   }
440   map->bs = bs;
441   PetscFunctionReturn(0);
442 }
443 
444 /*@C
445      PetscLayoutGetBlockSize - Gets the block size for a PetscLayout object.
446 
447     Not Collective
448 
449    Input Parameters:
450 .    map - pointer to the map
451 
452    Output Parameters:
453 .    bs - the size
454 
455    Level: developer
456 
457     Notes:
458        Call this after the call to PetscLayoutSetUp()
459 
460     Fortran Notes:
461       Not available from Fortran
462 
463 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(), PetscLayoutSetUp()
464           PetscLayoutGetRange(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize()
465 
466 @*/
467 #undef __FUNCT__
468 #define __FUNCT__ "PetscLayoutGetBlockSize"
469 PetscErrorCode  PetscLayoutGetBlockSize(PetscLayout map,PetscInt *bs)
470 {
471   PetscFunctionBegin;
472   *bs = PetscAbs(map->bs);
473   PetscFunctionReturn(0);
474 }
475 
476 
477 /*@C
478      PetscLayoutGetRange - gets the range of values owned by this process
479 
480     Not Collective
481 
482    Input Parameters:
483 .    map - pointer to the map
484 
485    Output Parameters:
486 +    rstart - first index owned by this process
487 -    rend - one more than the last index owned by this process
488 
489    Level: developer
490 
491     Notes:
492        Call this after the call to PetscLayoutSetUp()
493 
494     Fortran Notes:
495       Not available from Fortran
496 
497 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
498           PetscLayoutGetSize(), PetscLayoutGetRanges(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
499 
500 @*/
501 #undef __FUNCT__
502 #define __FUNCT__ "PetscLayoutGetRange"
503 PetscErrorCode  PetscLayoutGetRange(PetscLayout map,PetscInt *rstart,PetscInt *rend)
504 {
505   PetscFunctionBegin;
506   if (rstart) *rstart = map->rstart;
507   if (rend)   *rend   = map->rend;
508   PetscFunctionReturn(0);
509 }
510 
511 /*@C
512      PetscLayoutGetRanges - gets the range of values owned by all processes
513 
514     Not Collective
515 
516    Input Parameters:
517 .    map - pointer to the map
518 
519    Output Parameters:
520 .    range - start of each processors range of indices (the final entry is one more then the
521              last index on the last process)
522 
523    Level: developer
524 
525     Notes:
526        Call this after the call to PetscLayoutSetUp()
527 
528     Fortran Notes:
529       Not available from Fortran
530 
531 .seealso: PetscLayoutCreate(), PetscLayoutSetLocalSize(), PetscLayoutGetLocalSize(), PetscLayoutSetSize(),
532           PetscLayoutGetSize(), PetscLayoutGetRange(), PetscLayoutSetBlockSize(), PetscLayoutGetSize(), PetscLayoutSetUp()
533 
534 @*/
535 #undef __FUNCT__
536 #define __FUNCT__ "PetscLayoutGetRanges"
537 PetscErrorCode  PetscLayoutGetRanges(PetscLayout map,const PetscInt *range[])
538 {
539   PetscFunctionBegin;
540   *range = map->range;
541   PetscFunctionReturn(0);
542 }
543 
544 #undef __FUNCT__
545 #define __FUNCT__ "PetscSFSetGraphLayout"
546 /*@C
547    PetscSFSetGraphLayout - Set a parallel star forest via global indices and a PetscLayout
548 
549    Collective
550 
551    Input Arguments:
552 +  sf - star forest
553 .  layout - PetscLayout defining the global space
554 .  nleaves - number of leaf vertices on the current process, each of these references a root on any process
555 .  ilocal - locations of leaves in leafdata buffers, pass NULL for contiguous storage
556 -  iremote - remote locations of root vertices for each leaf on the current process
557 
558    Level: intermediate
559 
560 .seealso: PetscSFCreate(), PetscSFView(), PetscSFSetGraph(), PetscSFGetGraph()
561 @*/
562 PetscErrorCode PetscSFSetGraphLayout(PetscSF sf,PetscLayout layout,PetscInt nleaves,const PetscInt *ilocal,PetscCopyMode localmode,const PetscInt *iremote)
563 {
564   PetscErrorCode ierr;
565   PetscInt       i,nroots;
566   PetscSFNode    *remote;
567 
568   PetscFunctionBegin;
569   ierr = PetscLayoutGetLocalSize(layout,&nroots);CHKERRQ(ierr);
570   ierr = PetscMalloc1(nleaves,&remote);CHKERRQ(ierr);
571   for (i=0; i<nleaves; i++) {
572     PetscInt owner = -1;
573     ierr = PetscLayoutFindOwner(layout,iremote[i],&owner);CHKERRQ(ierr);
574     remote[i].rank  = owner;
575     remote[i].index = iremote[i] - layout->range[owner];
576   }
577   ierr = PetscSFSetGraph(sf,nroots,nleaves,ilocal,localmode,remote,PETSC_OWN_POINTER);CHKERRQ(ierr);
578   PetscFunctionReturn(0);
579 }
580 
581