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