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