MODFLOW 6  version 6.5.0.dev2
MODFLOW 6 Code Documentation
MpiUnitCache.f90
Go to the documentation of this file.
2  use kindmodule, only: i4b, lgp
3  use listmodule
6  use mpi
7  implicit none
8  private
9 
10  integer(I4B), public, parameter :: no_cached_value = -1
11 
12  type, public :: mpiunitcachetype
13  ! private
14  type(stlvecint), private :: cached_ranks
15  type(stlvecint), private :: cached_messages
16  integer(I4B), private :: nr_stages
17  integer(I4B), private :: nr_msg_types
18  contains
19  procedure :: init => cc_init
20  procedure :: get_cached => cc_get_cached
21  procedure :: cache => mc_cache
22  procedure :: destroy => cc_destroy
23  ! private
24  procedure, private :: is_rank_cached
25  procedure, private :: add_rank_cache
26  procedure, private :: get_rank_index
27  procedure, private :: get_msg_index
28  end type mpiunitcachetype
29 
30 contains
31 
32  !> @brief Initialize the unit cache.
33  !<
34  subroutine cc_init(this, nr_stages, nr_msg_types)
35  class(mpiunitcachetype) :: this
36  integer(I4B) :: nr_stages !< number of (simulation) stages
37  integer(I4B) :: nr_msg_types !< number of message types to be cached during a stage
38 
39  this%nr_stages = nr_stages
40  this%nr_msg_types = nr_msg_types
41  call this%cached_ranks%init()
42  call this%cached_messages%init()
43 
44  end subroutine cc_init
45 
46  !> @brief Get the cached mpi type for this rank and
47  !< stage. Equal to NO_CACHED_VALUE when not present.
48  function cc_get_cached(this, rank, stage, msg_id) result(mpi_type)
49  class(mpiunitcachetype) :: this
50  integer(I4B) :: rank
51  integer(I4B) :: stage
52  integer(I4B) :: msg_id
53  integer :: mpi_type
54  ! local
55  integer(I4B) :: msg_idx
56 
57  mpi_type = no_cached_value
58  msg_idx = this%get_msg_index(rank, stage, msg_id)
59  if (msg_idx > 0) then
60  mpi_type = this%cached_messages%at(msg_idx)
61  end if
62 
63  end function cc_get_cached
64 
65  !> @brief Cache the mpi datatype for this particular
66  !! rank and stage. The datatype should be committed
67  !< to the type database externally.
68  subroutine mc_cache(this, rank, stage, msg_id, mpi_type)
69  class(mpiunitcachetype) :: this
70  integer(I4B) :: rank
71  integer(I4B) :: stage
72  integer(I4B) :: msg_id
73  integer :: mpi_type
74  ! local
75  integer(I4B) :: msg_idx
76 
77  ! add if rank not present in cache yet
78  if (.not. this%is_rank_cached(rank)) then
79  call this%add_rank_cache(rank)
80  end if
81 
82  ! rank has been added to cache, now set
83  ! mpi datatype for this stage's message:
84  msg_idx = this%get_msg_index(rank, stage, msg_id)
85  call this%cached_messages%set(msg_idx, mpi_type)
86 
87  end subroutine mc_cache
88 
89  function is_rank_cached(this, rank) result(in_cache)
90  class(mpiunitcachetype) :: this
91  integer(I4B) :: rank
92  logical(LGP) :: in_cache
93 
94  in_cache = this%cached_ranks%contains(rank)
95 
96  end function is_rank_cached
97 
98  subroutine add_rank_cache(this, rank)
99  class(mpiunitcachetype) :: this
100  integer(I4B) :: rank
101  ! local
102  integer(I4B) :: i, j
103 
104  call this%cached_ranks%push_back(rank)
105  do i = 1, this%nr_stages
106  do j = 1, this%nr_msg_types
107  call this%cached_messages%push_back(no_cached_value)
108  end do
109  end do
110 
111  end subroutine add_rank_cache
112 
113  !> @Brief returns -1 when not present
114  !<
115  function get_rank_index(this, rank) result(rank_index)
116  class(mpiunitcachetype) :: this
117  integer(I4B) :: rank
118  integer(I4B) :: rank_index
119 
120  rank_index = this%cached_ranks%get_index(rank)
121 
122  end function get_rank_index
123 
124  !> @Brief returns -1 when not present
125  !<
126  function get_msg_index(this, rank, stage, msg_id) result(msg_index)
127  class(mpiunitcachetype) :: this
128  integer(I4B) :: rank
129  integer(I4B) :: stage
130  integer(I4B) :: msg_id
131  integer(I4B) :: msg_index
132  ! local
133  integer(I4B) :: rank_idx
134  integer(I4B) :: rank_offset, stage_offset
135 
136  msg_index = -1
137  rank_idx = this%get_rank_index(rank)
138  if (rank_idx < 1) return
139 
140  rank_offset = (rank_idx - 1) * (this%nr_stages * this%nr_msg_types)
141  stage_offset = (stage - 1) * this%nr_msg_types
142  msg_index = rank_offset + stage_offset + msg_id
143 
144  end function get_msg_index
145 
146  !> @brief Clean up the unit cache.
147  !<
148  subroutine cc_destroy(this)
149  class(mpiunitcachetype) :: this
150  ! local
151  integer(I4B) :: i
152  integer :: mpi_type, ierr
153 
154  do i = 1, this%cached_messages%size
155  mpi_type = this%cached_messages%at(i)
156  if (mpi_type /= no_cached_value) then
157  call mpi_type_free(mpi_type, ierr)
158  end if
159  end do
160 
161  call this%cached_ranks%destroy()
162  call this%cached_messages%destroy()
163 
164  end subroutine cc_destroy
165 
166 end module
subroutine init()
Definition: GridSorting.f90:24
This module defines variable data types.
Definition: kind.f90:8
subroutine cc_destroy(this)
Clean up the unit cache.
integer(i4b) function get_msg_index(this, rank, stage, msg_id)
@Brief returns -1 when not present
subroutine add_rank_cache(this, rank)
logical(lgp) function is_rank_cached(this, rank)
subroutine cc_init(this, nr_stages, nr_msg_types)
Initialize the unit cache.
subroutine mc_cache(this, rank, stage, msg_id, mpi_type)
Cache the mpi datatype for this particular rank and stage. The datatype should be committed.
integer(i4b), parameter, public no_cached_value
integer function cc_get_cached(this, rank, stage, msg_id)
Get the cached mpi type for this rank and.
integer(i4b) function get_rank_index(this, rank)
@Brief returns -1 when not present
integer(i4b), parameter, public nr_sim_stages
before exchange formulate (per solution)
Definition: SimStages.f90:24
subroutine destroy(this)
Definition: STLVecInt.f90:170