MODFLOW 6  version 6.6.0.dev0
USGS Modular Hydrologic Model
MpiWorld.f90
Go to the documentation of this file.
2  use kindmodule, only: i4b, lgp
4  use mpi
5  implicit none
6  private
7 
8  public :: get_mpi_world
9  public :: mpi_stop
10  public :: check_mpi
11 
12  type, public :: mpiworldtype
13  integer(I4B) :: mpi_rank !< the id for this process
14  integer(I4B) :: world_size !< the total nr. of processes in the MPI job
15  integer(I4B), pointer :: comm => null() !< the MF6 communicator, either was it passed to
16  !! use through the API, or we created MPI_COMM_WORLD
17  contains
18  procedure :: has_comm => mpiw_has_comm
19  procedure :: set_comm => mpiw_set_comm
20  procedure :: init => mpiw_init
21  procedure :: begin_order => mpiw_begin_order
22  procedure :: end_order => mpiw_end_order
23  procedure :: destroy => mpiw_destroy
24  end type mpiworldtype
25 
26  ! singleton pattern
27  type(mpiworldtype), pointer :: global_mpi_world
28 
29 contains
30 
31  function get_mpi_world() result(world)
32  type(mpiworldtype), pointer :: world
33 
34  if (.not. associated(global_mpi_world)) then
35  allocate (global_mpi_world)
36  end if
37  world => global_mpi_world
38 
39  end function get_mpi_world
40 
41  !> @brief Returns true when a communicator has been set.
42  !<
43  function mpiw_has_comm(this) result(has_comm)
44  class(mpiworldtype) :: this
45  logical(LGP) :: has_comm
46 
47  has_comm = associated(this%comm)
48 
49  end function mpiw_has_comm
50 
51  !> @brief Sets a communicator on this world, can
52  !< be done only once.
53  subroutine mpiw_set_comm(this, comm)
54  class(mpiworldtype) :: this
55  integer(I4B) :: comm
56 
57  allocate (this%comm)
58  this%comm = comm
59 
60  end subroutine mpiw_set_comm
61 
62  subroutine mpiw_init(this)
63  class(mpiworldtype) :: this
64  ! local
65  integer :: ierr
66 
67  call mpi_comm_size(this%comm, this%world_size, ierr)
68  call mpi_comm_rank(this%comm, this%mpi_rank, ierr)
69  nr_procs = this%world_size
70  proc_id = this%mpi_rank
71 
72  end subroutine mpiw_init
73 
74  subroutine mpiw_begin_order(this)
75  class(mpiworldtype) :: this
76  ! local
77  integer :: buffer
78  integer :: status(MPI_STATUS_SIZE)
79  integer :: ierr
80 
81  if (this%mpi_rank > 0) then
82  call mpi_recv(buffer, 1, mpi_integer, this%mpi_rank - 1, this%mpi_rank, &
83  this%comm, status, ierr)
84  end if
85 
86  end subroutine mpiw_begin_order
87 
88  subroutine mpiw_end_order(this)
89  class(mpiworldtype) :: this
90  ! local
91  integer :: ierr
92 
93  if (this%mpi_rank < this%world_size - 1) then
94  call mpi_send(this%mpi_rank, 1, mpi_integer, this%mpi_rank + 1, &
95  this%mpi_rank + 1, this%comm, ierr)
96  end if
97 
98  end subroutine mpiw_end_order
99 
100  subroutine mpiw_destroy(this)
101  class(mpiworldtype) :: this
102 
103  if (associated(this%comm)) then
104  deallocate (this%comm)
105  end if
106 
107  if (associated(global_mpi_world)) then
108  deallocate (global_mpi_world)
109  end if
110 
111  end subroutine mpiw_destroy
112 
113  !> @brief Check the MPI error code, report, and
114  !< terminate when not MPI_SUCCESS
115  subroutine check_mpi(mpi_error_code)
116  use simmodule, only: store_error
117  integer :: mpi_error_code
118  ! local
119  character(len=1024) :: mpi_err_msg
120  integer :: err_len
121  integer :: ierr
122 
123  if (mpi_error_code /= mpi_success) then
124  call mpi_error_string(mpi_error_code, mpi_err_msg, err_len, ierr)
125  call store_error("Internal error: "//trim(mpi_err_msg), terminate=.true.)
126  end if
127 
128  end subroutine check_mpi
129 
130  subroutine mpi_stop(status)
131  integer(I4B) :: status
132  ! local
133  type(mpiworldtype), pointer :: mpi_world
134  integer :: ierr
135 
136  mpi_world => get_mpi_world()
137  write (*, *) "" ! empty line
138  call mpi_abort(mpi_world%comm, status, ierr)
139 
140  end subroutine mpi_stop
141 
142 end module mpiworldmodule
subroutine init()
Definition: GridSorting.f90:24
This module defines variable data types.
Definition: kind.f90:8
type(mpiworldtype) function, pointer, public get_mpi_world()
Definition: MpiWorld.f90:32
subroutine mpiw_end_order(this)
Definition: MpiWorld.f90:89
logical(lgp) function mpiw_has_comm(this)
Returns true when a communicator has been set.
Definition: MpiWorld.f90:44
subroutine mpiw_set_comm(this, comm)
Sets a communicator on this world, can.
Definition: MpiWorld.f90:54
subroutine, public mpi_stop(status)
Definition: MpiWorld.f90:131
subroutine mpiw_begin_order(this)
Definition: MpiWorld.f90:75
type(mpiworldtype), pointer global_mpi_world
Definition: MpiWorld.f90:27
subroutine mpiw_init(this)
Definition: MpiWorld.f90:63
subroutine, public check_mpi(mpi_error_code)
Check the MPI error code, report, and.
Definition: MpiWorld.f90:116
subroutine mpiw_destroy(this)
Definition: MpiWorld.f90:101
This module contains simulation methods.
Definition: Sim.f90:10
subroutine, public store_error(msg, terminate)
Store an error message.
Definition: Sim.f90:92
This module contains simulation variables.
Definition: SimVariables.f90:9
integer(i4b) nr_procs
integer(i4b) proc_id