35 type(model_state_type),
target,
intent(inout) :: current_state
37 character(len=STRING_LENGTH) :: method
39 method=options_get_string(current_state%options_database,
"decomposition_method")
41 if (method .eq.
"onedim")
then
43 else if (method .eq.
"twodim")
then
47 if (method .ne.
"serial")
call log_log(log_warn,
"Decomposition method "//trim(method)//&
48 " not recognised so defaulting to serial")
58 type(model_state_type),
intent(inout) :: current_state
61 integer,
dimension(2) :: coords, distributed_dims
63 current_state%local_grid%active = current_state%global_grid%active
64 current_state%local_grid%dimensions = current_state%global_grid%dimensions
66 if (current_state%global_grid%dimensions .ne. 3)
then
67 call log_master_log(log_warn,
"Two dimension decomposition selected with only "// &
68 trim(conv_to_string(current_state%global_grid%dimensions)) //
" so defaulting to one dimension instead")
73 distributed_dims= (/0,0/)
74 call mpi_dims_create(current_state%parallel%processes, 2, distributed_dims, ierr)
76 current_state%parallel%dim_sizes(z_index)=1
77 current_state%parallel%dim_sizes(y_index) = distributed_dims(1)
78 current_state%parallel%dim_sizes(x_index) = distributed_dims(2)
81 current_state%parallel%dim_sizes(x_index)))
then
82 call log_master_log(log_warn,
"Defaulting to one dimension decomposition due to solution size too small")
87 call mpi_cart_create(current_state%parallel%monc_communicator, 2, (/distributed_dims(1), distributed_dims(2)/),&
88 (/.false., .false./), .false., current_state%parallel%neighbour_comm, ierr)
89 call mpi_cart_coords(current_state%parallel%neighbour_comm, current_state%parallel%my_rank, 2, coords, ierr)
96 current_state%global_grid%active(y_index)), distributed_dims(1), coords(1))
98 current_state%global_grid%active(x_index)), distributed_dims(2), coords(2))
105 if (log_get_logging_level() .ge. log_debug)
then
106 call log_log(log_debug,
"PID "//trim(conv_to_string(current_state%parallel%my_rank))//
": y="//&
107 trim(conv_to_string(current_state%parallel%my_coords(y_index)))//&
108 " x="//trim(conv_to_string(current_state%parallel%my_coords(x_index)))//
" ny-1="//&
109 trim(conv_to_string(current_state%local_grid%neighbours(y_index,1)))//&
110 " ny+1="//trim(conv_to_string(current_state%local_grid%neighbours(y_index,3)))//
" nx-1="//&
111 trim(conv_to_string(current_state%local_grid%neighbours(x_index,1)))//
" nx+1="//&
112 trim(conv_to_string(current_state%local_grid%neighbours(x_index,3))))
126 type(model_state_type),
intent(inout) :: current_state
127 integer,
intent(in) :: y_procs, x_procs, coords(2)
129 integer :: ierr, i, halo_depth
131 current_state%parallel%wrapped_around=.false.
133 call mpi_cart_shift(current_state%parallel%neighbour_comm, 0, 1, current_state%local_grid%neighbours(y_index,1), &
134 current_state%local_grid%neighbours(y_index,3), ierr)
135 if (current_state%local_grid%neighbours(y_index,1) .lt. 0)
then
136 call mpi_cart_rank(current_state%parallel%neighbour_comm,&
137 (/y_procs-1, coords(2)/), current_state%local_grid%neighbours(y_index,1), ierr)
138 current_state%parallel%wrapped_around(y_index, 1)=.true.
141 if (current_state%local_grid%neighbours(y_index,3) .lt. 0)
then
142 call mpi_cart_rank(current_state%parallel%neighbour_comm, &
143 (/0, coords(2)/), current_state%local_grid%neighbours(y_index,3), ierr)
144 current_state%parallel%wrapped_around(y_index, 2)=.true.
148 call mpi_cart_shift(current_state%parallel%neighbour_comm, 1, 1, &
149 current_state%local_grid%neighbours(x_index,1), &
150 current_state%local_grid%neighbours(x_index,3), ierr)
151 if (current_state%local_grid%neighbours(x_index,1) .lt. 0)
then
152 call mpi_cart_rank(current_state%parallel%neighbour_comm, &
153 (/coords(1), x_procs-1/), current_state%local_grid%neighbours(x_index,1), ierr)
154 current_state%parallel%wrapped_around(x_index, 1)=.true.
156 if (current_state%local_grid%neighbours(x_index,3) .lt. 0)
then
157 call mpi_cart_rank(current_state%parallel%neighbour_comm, &
158 (/coords(1), 0/), current_state%local_grid%neighbours(x_index,3), ierr)
159 current_state%parallel%wrapped_around(x_index, 2)=.true.
163 halo_depth = options_get_integer(current_state%options_database,
"halo_depth")
165 do i = 1, halo_depth -1
166 current_state%local_grid%neighbours(y_index,i+1) = &
167 current_state%local_grid%neighbours(y_index,i)
168 current_state%local_grid%neighbours(y_index,i+halo_depth + 1) = &
169 current_state%local_grid%neighbours(y_index,i+halo_depth)
170 current_state%local_grid%neighbours(x_index,i+1) = &
171 current_state%local_grid%neighbours(x_index,i)
172 current_state%local_grid%neighbours(x_index,i+halo_depth + 1) = &
173 current_state%local_grid%neighbours(x_index,i+halo_depth)
176 call mpi_cart_rank(current_state%parallel%neighbour_comm, &
177 (/merge(coords(1)-1, y_procs-1, coords(1) .ge. 1), &
178 merge(coords(2)-1, x_procs-1, coords(2) .ge. 1)/), &
179 current_state%local_grid%corner_neighbours(1,1), ierr)
180 call mpi_cart_rank(current_state%parallel%neighbour_comm, &
181 (/merge(coords(1)-1, y_procs-1, coords(1) .ge. 1), &
182 merge(coords(2)+1, 0, coords(2) .lt. x_procs-1)/), &
183 current_state%local_grid%corner_neighbours(2,1), ierr)
184 call mpi_cart_rank(current_state%parallel%neighbour_comm, &
185 (/merge(coords(1)+1, 0, coords(1) .lt. y_procs-1), &
186 merge(coords(2)-1, x_procs-1, coords(2) .ge. 1)/), &
187 current_state%local_grid%corner_neighbours(3,1), ierr)
188 call mpi_cart_rank(current_state%parallel%neighbour_comm, &
189 (/merge(coords(1)+1, 0, coords(1) .lt. y_procs-1), &
190 merge(coords(2)+1, 0, coords(2) .lt. x_procs-1)/), &
191 current_state%local_grid%corner_neighbours(4,1), ierr)
194 current_state%local_grid%corner_neighbours(:,2)=current_state%local_grid%corner_neighbours(:,1)
203 type(model_state_type),
intent(inout) :: current_state
204 integer,
intent(in) :: y_dims, x_dims
206 if (current_state%global_grid%active(y_index))
then
207 if (floor(real(current_state%global_grid%size(y_index)) / y_dims) .lt. 2)
then
212 if (current_state%global_grid%active(x_index))
then
213 if (floor(real(current_state%global_grid%size(x_index)) / x_dims) .lt. 2)
then
228 type(model_state_type),
intent(inout) :: current_state
229 integer,
intent(in) :: dim, dim_size, dim_my_rank, dim_processes
231 integer :: dimension_division, dimension_extra
233 dimension_division = dim_size / dim_processes
234 dimension_extra = dim_size - (dimension_division * dim_processes)
236 current_state%local_grid%start(dim) = dimension_division*dim_my_rank + merge(dimension_extra, dim_my_rank, &
237 dimension_extra .lt. dim_my_rank) + 1
238 current_state%local_grid%end(dim) = (current_state%local_grid%start(dim)-1) + dimension_division + &
239 merge(1, 0, dim_my_rank .lt. dimension_extra)
240 current_state%local_grid%size(dim)=(current_state%local_grid%end(dim) - current_state%local_grid%start(dim)) + 1
241 current_state%parallel%my_coords(dim) = dim_my_rank
248 type(model_state_type),
intent(inout) :: current_state
250 current_state%local_grid%start(z_index) = 1
251 current_state%local_grid%end(z_index) = current_state%global_grid%size(z_index)
252 current_state%local_grid%size(z_index) = current_state%global_grid%size(z_index)
253 current_state%parallel%my_coords(z_index) = 0
254 current_state%parallel%dim_sizes(z_index) = 1
263 type(model_state_type),
intent(inout) :: current_state
265 integer :: x_size, y_size, split_size, dimension_division, dimension_extra
269 current_state%parallel%wrapped_around=.false.
271 x_size = merge(current_state%global_grid%size(x_index), 1, current_state%global_grid%active(x_index))
272 y_size = merge(current_state%global_grid%size(y_index), 1, current_state%global_grid%active(y_index))
274 split_size = merge(x_size, y_size, x_size .gt. y_size)
275 dimension_division = split_size / current_state%parallel%processes
276 dimension_extra = split_size - (dimension_division * current_state%parallel%processes)
278 current_state%local_grid%active = current_state%global_grid%active
279 current_state%local_grid%dimensions = current_state%global_grid%dimensions
280 current_state%parallel%neighbour_comm = current_state%parallel%monc_communicator
283 if (x_size .gt. y_size)
then
285 current_state%local_grid%start(y_index)=1
286 current_state%local_grid%end(y_index)=y_size
287 current_state%local_grid%size(y_index)=y_size
288 current_state%parallel%my_coords(y_index)=0
289 current_state%parallel%dim_sizes(y_index)=1
290 current_state%local_grid%start(x_index)=dimension_division*current_state%parallel%my_rank+merge(&
291 dimension_extra, current_state%parallel%my_rank, dimension_extra .lt. current_state%parallel%my_rank) + 1
292 current_state%local_grid%end(x_index)=(current_state%local_grid%start(x_index)-1) + dimension_division + merge(&
293 1, 0, current_state%parallel%my_rank .lt. dimension_extra)
294 current_state%local_grid%size(x_index)=(current_state%local_grid%end(x_index) - current_state%local_grid%start(x_index)) + 1
295 current_state%parallel%my_coords(x_index) = current_state%parallel%my_rank
296 current_state%parallel%dim_sizes(x_index) = current_state%parallel%processes
297 current_state%local_grid%neighbours(y_index,:) = current_state%parallel%my_rank
299 current_state%local_grid%neighbours(x_index,1:2) = merge(current_state%parallel%my_rank, current_state%parallel%processes, &
300 current_state%parallel%my_rank .gt. 0) - 1
301 current_state%parallel%wrapped_around(x_index, 1)=&
302 current_state%local_grid%neighbours(x_index,1)==current_state%parallel%processes-1
303 current_state%local_grid%neighbours(x_index,3:4) = merge(current_state%parallel%my_rank+1, 0, &
304 current_state%parallel%my_rank .lt. current_state%parallel%processes-1)
305 current_state%parallel%wrapped_around(x_index, 2)=current_state%local_grid%neighbours(x_index,3)==0
306 current_state%local_grid%corner_neighbours(1,:)=current_state%local_grid%neighbours(x_index,1)
307 current_state%local_grid%corner_neighbours(3,:)=current_state%local_grid%neighbours(x_index,1)
308 current_state%local_grid%corner_neighbours(2,:)=current_state%local_grid%neighbours(x_index,3)
309 current_state%local_grid%corner_neighbours(4,:)=current_state%local_grid%neighbours(x_index,3)
310 current_state%parallel%wrapped_around(y_index, :)=.true.
313 current_state%local_grid%start(x_index)=1
314 current_state%local_grid%end(x_index)=x_size
315 current_state%local_grid%size(x_index)=x_size
316 current_state%parallel%my_coords(x_index)=0
317 current_state%parallel%dim_sizes(x_index)=1
318 current_state%local_grid%start(y_index)=dimension_division*current_state%parallel%my_rank+merge(&
319 dimension_extra, current_state%parallel%my_rank, dimension_extra .lt. current_state%parallel%my_rank) + 1
320 current_state%local_grid%end(y_index)=(current_state%local_grid%start(y_index)-1) + dimension_division + merge(&
321 1, 0, current_state%parallel%my_rank .lt. dimension_extra)
322 current_state%local_grid%size(y_index)=(current_state%local_grid%end(y_index) - current_state%local_grid%start(y_index)) + 1
323 current_state%parallel%my_coords(y_index)=current_state%parallel%my_rank
324 current_state%parallel%dim_sizes(y_index) = current_state%parallel%processes
325 current_state%local_grid%neighbours(x_index,:) = current_state%parallel%my_rank
326 current_state%local_grid%neighbours(y_index,1:2) = merge(current_state%parallel%my_rank, current_state%parallel%processes, &
327 current_state%parallel%my_rank .gt. 0) - 1
328 current_state%parallel%wrapped_around(y_index, 1)=&
329 current_state%local_grid%neighbours(y_index,1)==current_state%parallel%processes-1
330 current_state%local_grid%neighbours(y_index,3:4) = merge(current_state%parallel%my_rank+1, 0, &
331 current_state%parallel%my_rank .lt. current_state%parallel%processes-1)
332 current_state%parallel%wrapped_around(y_index, 2)=current_state%local_grid%neighbours(y_index,3)==0
333 current_state%local_grid%corner_neighbours(1:2,:)=current_state%local_grid%neighbours(y_index,1)
334 current_state%local_grid%corner_neighbours(3:4,:)=current_state%local_grid%neighbours(y_index,3)
335 current_state%parallel%wrapped_around(x_index, :)=.true.
347 type(model_state_type),
intent(inout) :: current_state
351 current_state%local_grid%active = current_state%global_grid%active
352 current_state%local_grid%dimensions = current_state%global_grid%dimensions
353 current_state%parallel%neighbour_comm = current_state%parallel%monc_communicator
356 current_state%local_grid%start(y_index)=1
357 current_state%local_grid%start(x_index)=1
358 current_state%parallel%my_coords(y_index)=0
359 current_state%parallel%my_coords(x_index)=0
360 current_state%parallel%dim_sizes(y_index)=0
361 current_state%parallel%dim_sizes(x_index)=0
363 current_state%local_grid%end(x_index)= &
364 merge(current_state%global_grid%size(x_index), 1, current_state%global_grid%active(x_index))
365 current_state%local_grid%size(x_index)=current_state%local_grid%end(x_index)
367 current_state%local_grid%end(y_index)=&
368 merge(current_state%global_grid%size(y_index), 1, current_state%global_grid%active(y_index))
369 current_state%local_grid%size(y_index)=current_state%local_grid%end(y_index)
371 current_state%local_grid%neighbours(x_index,:) = current_state%parallel%my_rank
372 current_state%local_grid%neighbours(y_index,:) = current_state%parallel%my_rank
373 current_state%local_grid%corner_neighbours=current_state%parallel%my_rank
375 current_state%parallel%wrapped_around=.true.
385 type(model_state_type),
intent(inout) :: current_state
386 character(len=*),
intent(in) :: decomp_name
388 if (log_get_logging_level() .le. log_debug)
then
389 call log_log(log_debug, decomp_name//
" rank="//trim(conv_to_string(current_state%parallel%my_rank))//&
390 ": W=("//trim(conv_to_string(current_state%local_grid%start(z_index)))//
"->"&
391 //trim(conv_to_string(current_state%local_grid%end(z_index)))//
") V=("//trim(conv_to_string(&
392 current_state%local_grid%start(y_index)))//
"->"//trim(conv_to_string(current_state%local_grid%end(&
393 y_index)))//
") U=("//trim(conv_to_string(current_state%local_grid%start(x_index)))//&
394 "->"//trim(conv_to_string(current_state%local_grid%end(x_index)))//
")")
395 call log_log(log_debug,
"Neighbours of "//trim(conv_to_string(current_state%parallel%my_rank))//
": y=(["//&
396 trim(conv_to_string(current_state%local_grid%neighbours(y_index,1)))//
"],["//&
397 trim(conv_to_string(current_state%local_grid%neighbours(y_index,2)))//
"]) x=(["//&
398 trim(conv_to_string(current_state%local_grid%neighbours(x_index,1)))//
","//&
399 trim(conv_to_string(current_state%local_grid%neighbours(x_index,2)))//
"],["//&
400 trim(conv_to_string(current_state%local_grid%neighbours(x_index,3)))//
","//&
401 trim(conv_to_string(current_state%local_grid%neighbours(x_index,4)))//
"])")
402 call log_master_log(log_debug,
"Halo size z="//&
403 trim(conv_to_string(current_state%local_grid%halo_size(z_index)))//&
404 " y="//trim(conv_to_string(current_state%local_grid%halo_size(y_index)))//
" x="//&
405 trim(conv_to_string(current_state%local_grid%halo_size(x_index))))
407 call log_master_log(log_info,
"Decomposed "//trim(conv_to_string(current_state%parallel%processes))//&
408 " processes via '"//decomp_name//
"' into z="//trim(conv_to_string(current_state%parallel%dim_sizes(&
409 z_index)))//
" y="//trim(conv_to_string(current_state%parallel%dim_sizes(y_index)))//
" x="//&
410 trim(conv_to_string(current_state%parallel%dim_sizes(x_index))))
417 type(local_grid_type),
intent(inout) :: local_grid
425 local_grid%local_domain_start_index(i) = local_grid%halo_size(i) + 1
426 local_grid%local_domain_end_index(i) = local_grid%halo_size(i) + local_grid%size(i)
441 type(model_state_type),
target,
intent(inout) :: current_state
442 integer :: n_dim, n_corners,total_halo_size_XY_dim
443 integer :: halo_depth
446 halo_depth = options_get_integer(current_state%options_database,
"halo_depth")
449 current_state%local_grid%halo_size(z_index) = 0
450 current_state%local_grid%halo_size(y_index) = halo_depth
451 current_state%local_grid%halo_size(x_index) = halo_depth
454 total_halo_size_xy_dim = current_state%local_grid%halo_size(x_index)*2
459 allocate(current_state%local_grid%neighbours(n_dim,total_halo_size_xy_dim), &
460 current_state%local_grid%corner_neighbours(n_corners,halo_depth))