-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathparallel_class.f
More file actions
258 lines (208 loc) · 6.46 KB
/
Copy pathparallel_class.f
File metadata and controls
258 lines (208 loc) · 6.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
! Parallel class for QuickPIC Open Source 1.0
! update: 04/18/2016
module parallel_class
use mpi
use omp_lib
implicit none
private
public :: parallel
type parallel
private
! nvp: number of MPI nodes
! idproc: processor id
! kstrt: idproc+1
! mreal = default datatype for reals
! mint = default datatype for integers
! mcplx = default datatype for complex type
! mdouble = default double precision type
! lworld = MPI_COMM_WORLD communicator
integer :: nvp
integer :: idproc
integer :: kstrt
integer :: mreal, mint, mcplx, mdouble, lworld
contains
generic :: new => init_parallel
generic :: del => end_parallel
procedure :: getnvp
procedure :: getidproc
procedure :: getkstrt
procedure :: getlworld
procedure :: getmreal
procedure :: getmint
procedure :: getmdouble
procedure :: getmcplx
procedure, private :: init_parallel
procedure, private :: end_parallel
end type parallel
contains
!
function getnvp(this)
implicit none
class(parallel), intent(in) :: this
integer :: getnvp
getnvp = this%nvp
end function getnvp
!
function getidproc(this)
implicit none
class(parallel), intent(in) :: this
integer :: getidproc
getidproc = this%idproc
end function getidproc
!
function getkstrt(this)
implicit none
class(parallel), intent(in) :: this
integer :: getkstrt
getkstrt = this%kstrt
end function getkstrt
!
function getlworld(this)
implicit none
class(parallel), intent(in) :: this
integer :: getlworld
getlworld = this%lworld
end function getlworld
!
function getmint(this)
implicit none
class(parallel), intent(in) :: this
integer :: getmint
getmint = this%mint
end function getmint
!
function getmreal(this)
implicit none
class(parallel), intent(in) :: this
integer :: getmreal
getmreal = this%mreal
end function getmreal
!
function getmdouble(this)
implicit none
class(parallel), intent(in) :: this
integer :: getmdouble
getmdouble = this%mdouble
end function getmdouble
!
function getmcplx(this)
implicit none
class(parallel), intent(in) :: this
integer :: getmcplx
getmcplx = this%mcplx
end function getmcplx
!
subroutine init_parallel(this)
implicit none
class(parallel), intent(inout) :: this
! nvpp = number of shared memory threads (0=default)
integer :: nvpp = 1
! initialize for shared memory parallel processing using openmp
call init_omp(nvpp)
! initialize for distributed memory parallel processing using mpi
call ppinit2(this%idproc,this%nvp,this%lworld,&
&this%mint,this%mreal,this%mdouble,this%mcplx)
this%kstrt = this%idproc + 1
end subroutine init_parallel
!
subroutine ppinit2(idproc,nvp,lworld,mint,mreal,mdouble,mcplx)
! this subroutine initializes parallel processing using mpi
implicit none
integer, intent(inout) :: idproc, nvp
integer, intent(inout) :: lworld,mint,mreal,mdouble,mcplx
! nproc = number of real or virtual processors obtained
! mreal = default datatype for reals
! mint = default datatype for integers
! mcplx = default datatype for complex type
! mdouble = default double precision type
! lworld = MPI_COMM_WORLD communicator
! local data
integer :: ierror, ndprec, idprec
integer :: iprec
logical :: flag
real :: prec
integer :: nproc
! ndprec = (0,1) = (no,yes) use (normal,autodouble) precision
if (digits(prec) > 24) then
ndprec = 1
else
ndprec = 0
endif
! idprec = (0,1) = (no,yes) use (normal,autodouble) integer precision
if (digits(iprec) > 31) then
idprec = 1
else
idprec = 0
endif
! this segment is used for mpi computers
! indicate whether MPI_INIT has been called
call MPI_INITIALIZED(flag,ierror)
if (.not.flag) then
! initialize the MPI execution environment
call MPI_INIT(ierror)
if (ierror /= 0) stop
endif
lworld = MPI_COMM_WORLD
! determine the rank of the calling process in the communicator
call MPI_COMM_RANK(lworld,idproc,ierror)
! determine the size of the group associated with a communicator
call MPI_COMM_SIZE(lworld,nproc,ierror)
! set default datatypes
mint = MPI_INTEGER
mdouble = MPI_DOUBLE_PRECISION
! single precision real
if (ndprec==0) then
mreal = MPI_REAL
mcplx = MPI_COMPLEX
! double precision real
else
mreal = MPI_DOUBLE_PRECISION
mcplx = MPI_DOUBLE_COMPLEX
endif
! single precision integer
! if (idprec==0) then
! mint = MPI_INTEGER
! double precision integer
! else
! mint = MPI_INTEGER8
! endif
! operators
nvp = nproc
end subroutine ppinit2
!
subroutine init_omp(nth)
! initialize openmp library
! use nth threads if nth > 0; otherwise, use the number found
implicit none
integer, intent(in) :: nth
! local data
integer :: ncpus, nthreads
! determine how many processors are available
ncpus = omp_get_num_procs()
print *, 'number of cpus found = ', ncpus
nthreads = omp_get_max_threads()
print *, 'maximum number of threads = ', nthreads
if (nth > 0) nthreads = nth
call omp_set_num_threads(nthreads)
print *, 'using ', nthreads, ' thread(s)'
end subroutine init_omp
!
subroutine end_parallel(this)
! this subroutine terminates parallel processing
implicit none
class(parallel), intent(inout) :: this
! lworld = MPI_COMM_WORLD communicator
! local data
integer :: ierror
logical :: flag
! indicate whether MPI_INIT has been called
call MPI_INITIALIZED(flag,ierror)
if (flag) then
! synchronize processes
call MPI_BARRIER(this%getlworld(),ierror)
! terminate MPI execution environment
call MPI_FINALIZE(ierror)
endif
end subroutine end_parallel
!
end module parallel_class