1e5c89e4eSSatish Balay 2c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/ 38ae1f613SSatish Balay #include <petsc/private/petscimpl.h> 4e5c89e4eSSatish Balay /* 5e5c89e4eSSatish Balay Note that tag of 0 is ok because comm is a private communicator 6e5c89e4eSSatish Balay generated below just for these routines. 7e5c89e4eSSatish Balay */ 8e5c89e4eSSatish Balay 99371c9d4SSatish Balay PETSC_INTERN PetscErrorCode PetscSequentialPhaseBegin_Private(MPI_Comm comm, int ng) { 10e5c89e4eSSatish Balay PetscMPIInt rank, size, tag = 0; 11e5c89e4eSSatish Balay MPI_Status status; 12e5c89e4eSSatish Balay 13e5c89e4eSSatish Balay PetscFunctionBegin; 149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 15e5c89e4eSSatish Balay if (size == 1) PetscFunctionReturn(0); 169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 17*48a46eb9SPierre Jolivet if (rank) PetscCallMPI(MPI_Recv(NULL, 0, MPI_INT, rank - 1, tag, comm, &status)); 18e5c89e4eSSatish Balay /* Send to the next process in the group unless we are the last process */ 19*48a46eb9SPierre Jolivet if ((rank % ng) < ng - 1 && rank != size - 1) PetscCallMPI(MPI_Send(NULL, 0, MPI_INT, rank + 1, tag, comm)); 20e5c89e4eSSatish Balay PetscFunctionReturn(0); 21e5c89e4eSSatish Balay } 22e5c89e4eSSatish Balay 239371c9d4SSatish Balay PETSC_INTERN PetscErrorCode PetscSequentialPhaseEnd_Private(MPI_Comm comm, int ng) { 24e5c89e4eSSatish Balay PetscMPIInt rank, size, tag = 0; 25e5c89e4eSSatish Balay MPI_Status status; 26e5c89e4eSSatish Balay 27e5c89e4eSSatish Balay PetscFunctionBegin; 289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 30e5c89e4eSSatish Balay if (size == 1) PetscFunctionReturn(0); 31e5c89e4eSSatish Balay 32e5c89e4eSSatish Balay /* Send to the first process in the next group */ 33*48a46eb9SPierre Jolivet if ((rank % ng) == ng - 1 || rank == size - 1) PetscCallMPI(MPI_Send(NULL, 0, MPI_INT, (rank + 1) % size, tag, comm)); 34*48a46eb9SPierre Jolivet if (rank == 0) PetscCallMPI(MPI_Recv(NULL, 0, MPI_INT, size - 1, tag, comm, &status)); 35e5c89e4eSSatish Balay PetscFunctionReturn(0); 36e5c89e4eSSatish Balay } 37e5c89e4eSSatish Balay 38e5c89e4eSSatish Balay /* ---------------------------------------------------------------------*/ 39e5c89e4eSSatish Balay /* 40e5c89e4eSSatish Balay The variable Petsc_Seq_keyval is used to indicate an MPI attribute that 41e5c89e4eSSatish Balay is attached to a communicator that manages the sequential phase code below. 42e5c89e4eSSatish Balay */ 432fe4ef4aSBarry Smith PetscMPIInt Petsc_Seq_keyval = MPI_KEYVAL_INVALID; 44e5c89e4eSSatish Balay 45e30d2299SSatish Balay /*@ 46e5c89e4eSSatish Balay PetscSequentialPhaseBegin - Begins a sequential section of code. 47e5c89e4eSSatish Balay 48d083f849SBarry Smith Collective 49e5c89e4eSSatish Balay 50e5c89e4eSSatish Balay Input Parameters: 51e5c89e4eSSatish Balay + comm - Communicator to sequentialize. 52e5c89e4eSSatish Balay - ng - Number in processor group. This many processes are allowed to execute 53e5c89e4eSSatish Balay at the same time (usually 1) 54e5c89e4eSSatish Balay 55e5c89e4eSSatish Balay Level: intermediate 56e5c89e4eSSatish Balay 57e5c89e4eSSatish Balay Notes: 58e5c89e4eSSatish Balay PetscSequentialPhaseBegin() and PetscSequentialPhaseEnd() provide a 59e5c89e4eSSatish Balay way to force a section of code to be executed by the processes in 60e5c89e4eSSatish Balay rank order. Typically, this is done with 61e5c89e4eSSatish Balay .vb 62e5c89e4eSSatish Balay PetscSequentialPhaseBegin(comm, 1); 63e5c89e4eSSatish Balay <code to be executed sequentially> 64e5c89e4eSSatish Balay PetscSequentialPhaseEnd(comm, 1); 65e5c89e4eSSatish Balay .ve 66e5c89e4eSSatish Balay 67e5c89e4eSSatish Balay Often, the sequential code contains output statements (e.g., printf) to 68e5c89e4eSSatish Balay be executed. Note that you may need to flush the I/O buffers before 69e5c89e4eSSatish Balay calling PetscSequentialPhaseEnd(). Also, note that some systems do 70e5c89e4eSSatish Balay not propagate I/O in any order to the controling terminal (in other words, 71e5c89e4eSSatish Balay even if you flush the output, you may not get the data in the order 72e5c89e4eSSatish Balay that you want). 73e5c89e4eSSatish Balay 74db781477SPatrick Sanan .seealso: `PetscSequentialPhaseEnd()` 75e5c89e4eSSatish Balay 76e5c89e4eSSatish Balay @*/ 779371c9d4SSatish Balay PetscErrorCode PetscSequentialPhaseBegin(MPI_Comm comm, int ng) { 78e5c89e4eSSatish Balay PetscMPIInt size; 79e5c89e4eSSatish Balay MPI_Comm local_comm, *addr_local_comm; 80e5c89e4eSSatish Balay 81e5c89e4eSSatish Balay PetscFunctionBegin; 829566063dSJacob Faibussowitsch PetscCall(PetscSysInitializePackage()); 839566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 84e5c89e4eSSatish Balay if (size == 1) PetscFunctionReturn(0); 85e5c89e4eSSatish Balay 86e5c89e4eSSatish Balay /* Get the private communicator for the sequential operations */ 87*48a46eb9SPierre Jolivet if (Petsc_Seq_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Seq_keyval, NULL)); 88e5c89e4eSSatish Balay 899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_dup(comm, &local_comm)); 909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(1, &addr_local_comm)); 91a297a907SKarl Rupp 92e5c89e4eSSatish Balay *addr_local_comm = local_comm; 93a297a907SKarl Rupp 949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Seq_keyval, (void *)addr_local_comm)); 959566063dSJacob Faibussowitsch PetscCall(PetscSequentialPhaseBegin_Private(local_comm, ng)); 96e5c89e4eSSatish Balay PetscFunctionReturn(0); 97e5c89e4eSSatish Balay } 98e5c89e4eSSatish Balay 99e30d2299SSatish Balay /*@ 100e5c89e4eSSatish Balay PetscSequentialPhaseEnd - Ends a sequential section of code. 101e5c89e4eSSatish Balay 102d083f849SBarry Smith Collective 103e5c89e4eSSatish Balay 104e5c89e4eSSatish Balay Input Parameters: 105e5c89e4eSSatish Balay + comm - Communicator to sequentialize. 106e5c89e4eSSatish Balay - ng - Number in processor group. This many processes are allowed to execute 107e5c89e4eSSatish Balay at the same time (usually 1) 108e5c89e4eSSatish Balay 109e5c89e4eSSatish Balay Level: intermediate 110e5c89e4eSSatish Balay 111e5c89e4eSSatish Balay Notes: 112e5c89e4eSSatish Balay See PetscSequentialPhaseBegin() for more details. 113e5c89e4eSSatish Balay 114db781477SPatrick Sanan .seealso: `PetscSequentialPhaseBegin()` 115e5c89e4eSSatish Balay 116e5c89e4eSSatish Balay @*/ 1179371c9d4SSatish Balay PetscErrorCode PetscSequentialPhaseEnd(MPI_Comm comm, int ng) { 118e5c89e4eSSatish Balay PetscMPIInt size, flag; 119e5c89e4eSSatish Balay MPI_Comm local_comm, *addr_local_comm; 120e5c89e4eSSatish Balay 121e5c89e4eSSatish Balay PetscFunctionBegin; 1229566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 123e5c89e4eSSatish Balay if (size == 1) PetscFunctionReturn(0); 124e5c89e4eSSatish Balay 1259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Seq_keyval, (void **)&addr_local_comm, &flag)); 12628b400f6SJacob Faibussowitsch PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Wrong MPI communicator; must pass in one used with PetscSequentialPhaseBegin()"); 127e5c89e4eSSatish Balay local_comm = *addr_local_comm; 128e5c89e4eSSatish Balay 1299566063dSJacob Faibussowitsch PetscCall(PetscSequentialPhaseEnd_Private(local_comm, ng)); 130e5c89e4eSSatish Balay 1319566063dSJacob Faibussowitsch PetscCall(PetscFree(addr_local_comm)); 1329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&local_comm)); 1339566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_delete_attr(comm, Petsc_Seq_keyval)); 134e5c89e4eSSatish Balay PetscFunctionReturn(0); 135e5c89e4eSSatish Balay } 1366ba4152bSMatthew G. Knepley 1376ba4152bSMatthew G. Knepley /*@C 1386ba4152bSMatthew G. Knepley PetscGlobalMinMaxInt - Get the global min/max from local min/max input 1396ba4152bSMatthew G. Knepley 140d083f849SBarry Smith Collective 1416ba4152bSMatthew G. Knepley 1426ba4152bSMatthew G. Knepley Input Parameter: 1436ba4152bSMatthew G. Knepley . minMaxVal - An array with the local min and max 1446ba4152bSMatthew G. Knepley 1456ba4152bSMatthew G. Knepley Output Parameter: 1466ba4152bSMatthew G. Knepley . minMaxValGlobal - An array with the global min and max 1476ba4152bSMatthew G. Knepley 1486ba4152bSMatthew G. Knepley Level: beginner 1496ba4152bSMatthew G. Knepley 150db781477SPatrick Sanan .seealso: `PetscSplitOwnership()` 1516ba4152bSMatthew G. Knepley @*/ 1529371c9d4SSatish Balay PetscErrorCode PetscGlobalMinMaxInt(MPI_Comm comm, const PetscInt minMaxVal[2], PetscInt minMaxValGlobal[2]) { 15358b5cd2aSSatish Balay PetscInt sendbuf[3], recvbuf[3]; 1546ba4152bSMatthew G. Knepley 1556ba4152bSMatthew G. Knepley PetscFunctionBegin; 15658b5cd2aSSatish Balay sendbuf[0] = -minMaxVal[0]; /* Note that -PETSC_MIN_INT = PETSC_MIN_INT */ 15758b5cd2aSSatish Balay sendbuf[1] = minMaxVal[1]; 15858b5cd2aSSatish Balay sendbuf[2] = (minMaxVal[0] == PETSC_MIN_INT) ? 1 : 0; /* Are there PETSC_MIN_INT in minMaxVal[0]? */ 1599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Allreduce(sendbuf, recvbuf, 3, MPIU_INT, MPI_MAX, comm)); 16058b5cd2aSSatish Balay minMaxValGlobal[0] = recvbuf[2] ? PETSC_MIN_INT : -recvbuf[0]; 16158b5cd2aSSatish Balay minMaxValGlobal[1] = recvbuf[1]; 1626ba4152bSMatthew G. Knepley PetscFunctionReturn(0); 1636ba4152bSMatthew G. Knepley } 1646ba4152bSMatthew G. Knepley 1656ba4152bSMatthew G. Knepley /*@C 1666ba4152bSMatthew G. Knepley PetscGlobalMinMaxReal - Get the global min/max from local min/max input 1676ba4152bSMatthew G. Knepley 168d083f849SBarry Smith Collective 1696ba4152bSMatthew G. Knepley 1706ba4152bSMatthew G. Knepley Input Parameter: 1716ba4152bSMatthew G. Knepley . minMaxVal - An array with the local min and max 1726ba4152bSMatthew G. Knepley 1736ba4152bSMatthew G. Knepley Output Parameter: 1746ba4152bSMatthew G. Knepley . minMaxValGlobal - An array with the global min and max 1756ba4152bSMatthew G. Knepley 1766ba4152bSMatthew G. Knepley Level: beginner 1776ba4152bSMatthew G. Knepley 178db781477SPatrick Sanan .seealso: `PetscSplitOwnership()` 1796ba4152bSMatthew G. Knepley @*/ 1809371c9d4SSatish Balay PetscErrorCode PetscGlobalMinMaxReal(MPI_Comm comm, const PetscReal minMaxVal[2], PetscReal minMaxValGlobal[2]) { 18158b5cd2aSSatish Balay PetscReal sendbuf[2]; 1826ba4152bSMatthew G. Knepley 1836ba4152bSMatthew G. Knepley PetscFunctionBegin; 18458b5cd2aSSatish Balay sendbuf[0] = -minMaxVal[0]; 18558b5cd2aSSatish Balay sendbuf[1] = minMaxVal[1]; 1861c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(sendbuf, minMaxValGlobal, 2, MPIU_REAL, MPIU_MAX, comm)); 18758b5cd2aSSatish Balay minMaxValGlobal[0] = -minMaxValGlobal[0]; 1886ba4152bSMatthew G. Knepley PetscFunctionReturn(0); 1896ba4152bSMatthew G. Knepley } 190