xref: /petsc/src/sys/utils/psplit.c (revision feff33ee0b5b037fa8f9f294dede656a2f85cc47)
1 
2 #include <petscsys.h>           /*I    "petscsys.h" I*/
3 
4 /*@
5     PetscSplitOwnershipBlock - Given a global (or local) length determines a local
6         (or global) length via a simple formula. Splits so each processors local size
7         is divisible by the block size.
8 
9    Collective on MPI_Comm (if N is PETSC_DECIDE)
10 
11    Input Parameters:
12 +    comm - MPI communicator that shares the object being divided
13 .    bs - block size
14 .    n - local length (or PETSC_DECIDE to have it set)
15 -    N - global length (or PETSC_DECIDE)
16 
17   Level: developer
18 
19    Notes:
20      n and N cannot be both PETSC_DECIDE
21 
22      If one processor calls this with N of PETSC_DECIDE then all processors
23      must, otherwise the program will hang.
24 
25 .seealso: PetscSplitOwnership()
26 
27 @*/
28 PetscErrorCode  PetscSplitOwnershipBlock(MPI_Comm comm,PetscInt bs,PetscInt *n,PetscInt *N)
29 {
30   PetscErrorCode ierr;
31   PetscMPIInt    size,rank;
32 
33   PetscFunctionBegin;
34   if (*N == PETSC_DECIDE && *n == PETSC_DECIDE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE");
35 
36   if (*N == PETSC_DECIDE) {
37     if (*n % bs != 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"local size %D not divisible by block size %D",*n,bs);
38     ierr = MPIU_Allreduce(n,N,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
39   } else if (*n == PETSC_DECIDE) {
40     PetscInt Nbs = *N/bs;
41     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
42     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
43     *n   = bs*(Nbs/size + ((Nbs % size) > rank));
44   }
45   PetscFunctionReturn(0);
46 }
47 
48 
49 /*@
50     PetscSplitOwnership - Given a global (or local) length determines a local
51         (or global) length via a simple formula
52 
53    Collective on MPI_Comm (if N is PETSC_DECIDE)
54 
55    Input Parameters:
56 +    comm - MPI communicator that shares the object being divided
57 .    n - local length (or PETSC_DECIDE to have it set)
58 -    N - global length (or PETSC_DECIDE)
59 
60   Level: developer
61 
62    Notes:
63      n and N cannot be both PETSC_DECIDE
64 
65      If one processor calls this with N of PETSC_DECIDE then all processors
66      must, otherwise the program will hang.
67 
68 .seealso: PetscSplitOwnershipBlock()
69 
70 @*/
71 PetscErrorCode  PetscSplitOwnership(MPI_Comm comm,PetscInt *n,PetscInt *N)
72 {
73   PetscErrorCode ierr;
74   PetscMPIInt    size,rank;
75 
76   PetscFunctionBegin;
77   if (*N == PETSC_DECIDE && *n == PETSC_DECIDE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Both n and N cannot be PETSC_DECIDE\n  likely a call to VecSetSizes() or MatSetSizes() is wrong.\nSee http://www.mcs.anl.gov/petsc/documentation/faq.html#split");
78 
79   if (*N == PETSC_DECIDE) {
80     ierr = MPIU_Allreduce(n,N,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
81   } else if (*n == PETSC_DECIDE) {
82     ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
83     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
84     *n   = *N/size + ((*N % size) > rank);
85 #if defined(PETSC_USE_DEBUG)
86   } else {
87     PetscInt tmp;
88     ierr = MPIU_Allreduce(n,&tmp,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr);
89     if (tmp != *N) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Sum of local lengths %D does not equal global length %D, my local length %D\n  likely a call to VecSetSizes() or MatSetSizes() is wrong.\nSee http://www.mcs.anl.gov/petsc/documentation/faq.html#split",tmp,*N,*n);
90 #endif
91   }
92   PetscFunctionReturn(0);
93 }
94 
95