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