PB3D [2.47]
Ideal linear high-n MHD stability in 3-D
Loading...
Searching...
No Matches
MPI_vars.f90
Go to the documentation of this file.
1!------------------------------------------------------------------------------!
2!> Variables pertaining to MPI.
3!------------------------------------------------------------------------------!
4module mpi_vars
5#include <PB3D_macros.h>
8 use mpi
9
10 implicit none
11 private
12 public init_lock, dealloc_lock, &
14
15 !> lock type
16 !!
17 !! There is a blocking (BL) and a nonblocking (NB) version where the former
18 !! requires an exclusive lock and the latter a shared one. This is saved in
19 !! the variable \c blocking.
20 !!
21 !! NB processes that get the lock directly on request (meaning that there
22 !! were no other processes in the queue) notify directly all the next NB
23 !! processes after gaining access. It also sets their status to active. When
24 !! a NB process gains the lock when notified after waiting, it does not have
25 !! to check for other NB processes, as this has been done by the notifying
26 !! process.
27 !!
28 !! A BL process retains exclusive access upon receipt of the lock. Similarly
29 !! to NB processes, if the receipt was direct on request, the status is set
30 !! to active, but only of this NB process.
31 !!
32 !! When returning the lock, all BL processes and NB that find themselves to
33 !! be the last active NB process, scan the waiting list and pass the lock
34 !! preferably to another BL process to notify. If not available, it searches
35 !! for all the NB processes to notify together.
36 !!
37 !! The advantage of prefering BL processes after finishing a process is that
38 !! this way NB processes are accumulated, and then quickly finished
39 !! afterwards.
40 !!
41 !! \note Every process in the waiting queue will eventually receive a
42 !! notification.
43 !!
44 !! Scheme:
45 !! <table>
46 !! <tr> <th> <th> request access <th> gain acces <th> return access
47 !! <tr> <th> BL
48 !! <td> <ul><li> add to queue <li> wait </ul>
49 !! <td> if direct: <ul><li> activate </ul>
50 !! <td> <ul><li> remove from queue <li> find next BL/NB
51 !! <li> notify <li> activate all </ul>
52 !! <tr> <th> NB
53 !! <td> <ul><li> add to queue <li> wait </ul>
54 !! <td> if direct: <ul><li> find next NB </ul>
55 !! for all next NB: <ul> <li> notify <li> activate </ul>
56 !! <td> always: <ul><li> remove from queue </ul>
57 !! if last NB: <ul><li> find next BL/NB
58 !! <li> notify <li> activate all </ul>
59 !! </table>
60 !! with preference BL > NB(s).
61 !!
62 !! \see This is based on an extension of the ideas in \c RossAtomicIO.
63 type, public :: lock_type
64 integer, allocatable :: wl(:) !< waiting list
65 integer :: wl_win !< window to waiting list
66 integer :: wu_tag !< wakeup tag
67 logical :: blocking !< is a normal blocking process
68 contains
69 !> initialize
70 procedure :: init => init_lock !< initialize
71 !> deallocate
72 procedure :: dealloc => dealloc_lock !< deallocate
73 end type lock_type
74
75 ! global variables
76 type(lock_type) :: hdf5_lock !< HDF5 lock
77
78contains
79 !> Initializes a lock.
80 !!
81 !! \note
82 !! -# Should be called collectively.
83 !! -# Every lock should have a unique wakeup tag.
84 !!
85 !! \return ierr
86 integer function init_lock(lock_loc,wu_tag) result(ierr)
87 use num_vars, only: n_procs, rank
88
89 character(*), parameter :: rout_name = 'init_lock'
90
91 ! input / output
92 class(lock_type), intent(inout) :: lock_loc !< lock
93 integer, intent(in) :: wu_tag !< wakeup tag
94
95 ! local variables
96 integer(kind=MPI_ADDRESS_KIND) :: intlb ! lower bound of int type
97 integer(kind=MPI_ADDRESS_KIND) :: intex ! extent of int type
98
99 ! initialize ierr
100 ierr = 0
101
102 call mpi_type_get_extent(mpi_integer,intlb,intex,ierr)
103 chckerr('Failed to get extent of int')
104
105 if (rank.eq.0) then ! master
106 allocate(lock_loc%wl(n_procs))
107
108 lock_loc%wl = 0
109 call mpi_win_create(lock_loc%wl,n_procs*intex,int(intex),&
110 &mpi_info_null,mpi_comm_world,lock_loc%wl_win,ierr)
111 chckerr('Failed to create window to lock_loc')
112 else
113 allocate(lock_loc%wl(0))
114
115 call mpi_win_create(lock_loc%wl,0*intex,int(intex),mpi_info_null,&
116 &mpi_comm_world,lock_loc%wl_win,ierr)
117 chckerr('Failed to create window to lock_loc')
118 end if
119
120 lock_loc%wu_tag = wu_tag
121
122 ! set fences
123 call mpi_win_fence(0,lock_loc%wl_win,ierr)
124 chckerr('Couldn''t set fence')
125 end function init_lock
126
127 !> Deallocates a lock.
128 !!
129 !! \note Should be called collectively.
130 !!
131 !! \return ierr
132 integer function dealloc_lock(lock_loc) result(ierr)
133 character(*), parameter :: rout_name = 'dealloc_lock'
134
135 ! input / output
136 class(lock_type), intent(inout) :: lock_loc !< lock
137
138 ! initialize ierr
139 ierr = 0
140
141 ! free lock window
142 call mpi_win_free(lock_loc%wl_win,ierr)
143 chckerr('Failed to free window to HDF5_lock')
144
145 ! deallocate lock
146 deallocate(lock_loc%wl)
147 end function dealloc_lock
148end module mpi_vars
Variables pertaining to MPI.
Definition MPI_vars.f90:4
type(lock_type), public hdf5_lock
HDF5 lock.
Definition MPI_vars.f90:76
integer function, public init_lock(lock_loc, wu_tag)
Initializes a lock.
Definition MPI_vars.f90:87
integer function, public dealloc_lock(lock_loc)
Deallocates a lock.
Definition MPI_vars.f90:133
Numerical variables used by most other modules.
Definition num_vars.f90:4
integer, parameter, public dp
double precision
Definition num_vars.f90:46
character(len=7), public script_dir
directory where to save scripts for plots
Definition num_vars.f90:154
integer, public n_procs
nr. of MPI processes
Definition num_vars.f90:69
integer, parameter, public max_str_ln
maximum length of strings
Definition num_vars.f90:50
character(len=5), public plot_dir
directory where to save plots
Definition num_vars.f90:153
integer, public rank
MPI rank.
Definition num_vars.f90:68
character(len=4), public data_dir
directory where to save data for plots
Definition num_vars.f90:155
Operations on strings.
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
elemental character(len=max_str_ln) function, public r2str(k)
Convert a real (double) to string.
elemental character(len=max_str_ln) function, public r2strt(k)
Convert a real (double) to string.