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