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