MONC
iterativesolver.F90
Go to the documentation of this file.
1 
4  use collections_mod, only : map_type
7  use state_mod, only : model_state_type
17  use mpi, only : mpi_max, mpi_sum, mpi_comm_world, mpi_request_null, mpi_statuses_ignore
18  implicit none
19 
20 #ifndef TEST_MODE
21  private
22 #endif
23 
26  real(kind=default_precision) :: n, s, e, w
27  real(kind=default_precision), dimension(:), allocatable :: u, d, p, lu_d, lu_u, vol
28  end type matrix_type
29 
31  integer :: max_iterations, & !< Maximum number of BiCGStab iterations
33  logical :: symm_prob
34 
35  real(kind=default_precision), parameter :: tiny = 1.0e-16
36 
38  real(kind=default_precision), dimension(:,:,:), allocatable :: psource, prev_p
39  logical :: first_run=.true.
40  type(matrix_type) :: a
41 
43 contains
44 
48  iterativesolver_get_descriptor%name="iterativesolver"
54 
57  subroutine initialisation_callback(current_state)
58  type(model_state_type), target, intent(inout) :: current_state
59 
60  if (.not. is_component_enabled(current_state%options_database, "diverr")) then
61  call log_master_log(log_error, "The iterative solver component requires the diverr component to be enabled")
62  end if
63 
64  tolerance=options_get_real(current_state%options_database, "tolerance")
65  max_iterations=options_get_integer(current_state%options_database, "max_iterations")
66  preconditioner_iterations=options_get_integer(current_state%options_database, "preconditioner_iterations")
67  symm_prob=options_get_logical(current_state%options_database, "symm_prob")
68 
69  call init_halo_communication(current_state, get_single_field_per_halo_cell, halo_swap_state, 1, .false.)
70 
71  allocate(psource(current_state%local_grid%size(z_index) + current_state%local_grid%halo_size(z_index) * 2, &
72  current_state%local_grid%size(y_index) + current_state%local_grid%halo_size(y_index) * 2, &
73  current_state%local_grid%size(x_index) + current_state%local_grid%halo_size(x_index) * 2),&
74  prev_p(current_state%local_grid%size(z_index) + current_state%local_grid%halo_size(z_index) * 2, &
75  current_state%local_grid%size(y_index) + current_state%local_grid%halo_size(y_index) * 2, &
76  current_state%local_grid%size(x_index) + current_state%local_grid%halo_size(x_index) * 2))
77 
78  a=create_problem_matrix(current_state%local_grid%size(z_index))
79  call set_matrix_for_poisson(current_state%global_grid%configuration, a, current_state%local_grid%size(z_index))
80  end subroutine initialisation_callback
81 
84  subroutine timestep_callback(current_state)
85  type(model_state_type), target, intent(inout) :: current_state
86 
87  integer :: i_strt, i_end, j_strt, j_end, k_end
88 
89  i_strt = current_state%local_grid%local_domain_start_index(x_index)
90  i_end = current_state%local_grid%local_domain_end_index(x_index)
91  j_strt = current_state%local_grid%local_domain_start_index(y_index)
92  j_end = current_state%local_grid%local_domain_end_index(y_index)
93  k_end = current_state%local_grid%size(z_index)
94 
95  call complete_psrce_calculation(current_state, current_state%local_grid%halo_size(y_index), &
96  current_state%local_grid%halo_size(x_index))
97 
98  call initiate_nonblocking_halo_swap(current_state, halo_swap_state, copy_p_to_halo_buffer)
99  call deduce_global_divmax(current_state)
100  call complete_nonblocking_halo_swap(current_state, halo_swap_state, perform_local_data_copy_for_p, copy_halo_buffer_to_p)
101 
102  psource=current_state%p%data
103  if (first_run) then
104  ! If first timestep then initial guess is zero
105  current_state%p%data=0.0_default_precision
106  first_run=.false.
107  else
108  ! Initial guess is set to previous timesteps p
109  current_state%p%data=prev_p
110  end if
111 
112  if (symm_prob) then
113  call cg_solver(current_state, a, current_state%p%data, psource, i_strt, i_end, j_strt, j_end, k_end)
114  else
115  call bicgstab(current_state, a, current_state%p%data, psource, i_strt, i_end, j_strt, j_end, k_end)
116  end if
117 
118  prev_p=current_state%p%data
119  end subroutine timestep_callback
120 
123  subroutine finalisation_callback(current_state)
124  type(model_state_type), target, intent(inout) :: current_state
125 
126  call finalise_halo_communication(halo_swap_state)
127  deallocate(psource, prev_p, a%u, a%d, a%p, a%lu_u, a%lu_d, a%vol)
128  end subroutine finalisation_callback
129 
135  subroutine bicgstab(current_state, A, x, b, i_strt, i_end, j_strt, j_end, k_end)
136  type(model_state_type), target, intent(inout) :: current_state
137  type(matrix_type), intent(inout) :: A
138  real(kind=default_precision), dimension(:,:,:), intent(inout) :: x
139  real(kind=default_precision), dimension(:,:,:), intent(in) :: b
140  integer, intent(in) :: i_strt, i_end, j_strt, j_end, k_end
141 
142  integer :: it, i, j, k
143  real(kind=default_precision) :: sc_err, alf, omg, nrm, my_rho, bet, tt, ts, ss, err, init_err, inner_prod_results(3)
144  real(kind=default_precision), dimension(current_state%local_grid%size(Z_INDEX) + & current_state%local_grid%halo_size(Z_INDEX) * 2, & current_state%local_grid%size(Y_INDEX) + current_state%local_grid%halo_size(Y_INDEX) * 2, & current_state%local_grid%size(X_INDEX) + current_state%local_grid%halo_size(X_INDEX) * 2) :: ax, r, cr, pp, v, t, s, cs
145 
146  ! Calculate scale factor for error
147  sc_err = sqrt(inner_prod(current_state, b, b, i_strt, i_end, j_strt, j_end, k_end))
148  sc_err = max(sc_err, 0.0001_default_precision)
149 
150  ! Calculate initial residual
151  call calc_ax(current_state, a, x, ax)
152 
153  do i = i_strt, i_end
154  do j = j_strt, j_end
155  do k = 2, k_end
156  r(k,j,i) = b(k,j,i) - ax(k,j,i)
157  cr(k,j,i) = r(k,j,i)
158  end do
159  end do
160  end do
161 
162  my_rho = inner_prod(current_state, r, r, i_strt, i_end, j_strt, j_end, k_end)
163  err = sqrt(my_rho)/sc_err
164  init_err = err
165 
166  alf = 1.0_default_precision
167  omg = 1.0_default_precision
168  nrm = 1.0_default_precision
169 
170  if (err .ge. tolerance) then
171  do it=1, max_iterations
172  if (it > 1) my_rho = inner_prod(current_state, r, cr, i_strt, i_end, j_strt, j_end, k_end)
173  bet = (my_rho/nrm) * (alf/omg)
174  if (it == 1) then
175  call precond(current_state, a, pp, r, preconditioner_iterations)
176  else
177  do i = i_strt, i_end
178  do j = j_strt, j_end
179  do k = 2, k_end
180  t(k,j,i) = r(k,j,i) - bet*omg*v(k,j,i)
181  end do
182  end do
183  end do
184  call precond(current_state, a, s, t, preconditioner_iterations)
185  do i = i_strt, i_end
186  do j = j_strt, j_end
187  do k = 2, k_end
188  pp(k,j,i) = s(k,j,i) + bet*pp(k,j,i)
189  end do
190  end do
191  end do
192  end if
193  call calc_ax(current_state, a, pp, v)
194  nrm = inner_prod(current_state, cr, v, i_strt, i_end, j_strt, j_end, k_end)
195  alf = my_rho / nrm
196 
197  do i = i_strt, i_end
198  do j = j_strt, j_end
199  do k = 2, k_end
200  s(k,j,i) = r(k,j,i) - alf*v(k,j,i)
201  end do
202  end do
203  end do
204 
205  call precond(current_state, a, cs, s, preconditioner_iterations)
206  call calc_ax(current_state, a, cs, t)
207 
208  inner_prod_results=inner_prod_three_way(current_state, t, s, i_strt, i_end, j_strt, j_end, k_end)
209  tt = inner_prod_results(1)
210  ts = inner_prod_results(2)
211  ss = inner_prod_results(3)
212  omg = ts/tt
213  x = x + alf*pp + omg*cs
214  do i = i_strt, i_end
215  do j = j_strt, j_end
216  do k = 2, k_end
217  r(k,j,i) = s(k,j,i) - omg*t(k,j,i)
218  end do
219  end do
220  end do
221  nrm = my_rho
222 
223  if (abs(omg) < tiny) then
224  call log_log(log_warn, "Convergence problem, omega="//conv_to_string(omg))
225  endif
226 
227  err = sqrt(ss - 2*omg*ts + omg**2 *tt)/sc_err
228  if (err < tolerance) exit
229  end do
230  end if
231 
232  if (err > tolerance) then
233  call log_log(log_warn, "Convergence failed, RNorm="//conv_to_string(err, exponent=.true.))
234  else if (current_state%parallel%my_rank==0 .and. log_get_logging_level() .eq. log_debug) then
235  call log_log(log_debug, "Converged in "//trim(conv_to_string(it))//" iterations with RNorm="//&
236  trim(conv_to_string(err, 5, .true.))//" initial norm="//trim(conv_to_string(init_err, 5, .true.)))
237  end if
238  end subroutine bicgstab
239 
245  subroutine cg_solver(current_state, A, x, b, i_strt, i_end, j_strt, j_end, k_end)
246  type(model_state_type), target, intent(inout) :: current_state
247  type(matrix_type), intent(inout) :: A
248  real(kind=default_precision), dimension(:,:,:), intent(inout) :: x
249  real(kind=default_precision), dimension(:,:,:), intent(in) :: b
250  integer, intent(in) :: i_strt, i_end, j_strt, j_end, k_end
251 
252  integer :: it, k, i, j
253  real(kind=default_precision) :: sc_err, alf, bet, err, init_err, rho
254  real(kind=default_precision), dimension(current_state%local_grid%size(Z_INDEX) + & current_state%local_grid%halo_size(Z_INDEX) * 2, & current_state%local_grid%size(Y_INDEX) + current_state%local_grid%halo_size(Y_INDEX) * 2, & current_state%local_grid%size(X_INDEX) + current_state%local_grid%halo_size(X_INDEX) * 2) :: ax, r, z, p
255 
256  ! first rescale RHS for symmetry (this could be done when p_source is calculated
257  do i=current_state%local_grid%local_domain_start_index(x_index), current_state%local_grid%local_domain_end_index(x_index)
258  do j=current_state%local_grid%local_domain_start_index(y_index), current_state%local_grid%local_domain_end_index(y_index)
259 
260  r(1,j,i) = 0.0_default_precision
261  do k=2,current_state%local_grid%size(z_index)
262  r(k,j,i) = b(k,j,i) * a%vol(k)
263  end do
264  end do
265  end do
266 
267  ! Calculate scale factor for error
268 
269  call calc_ax(current_state, a, x, ax)
270 
271  sc_err = sqrt(inner_prod(current_state, r, r, i_strt, i_end, j_strt, j_end, k_end))
272  sc_err = max(sc_err, 0.0001_default_precision)
273  r = r - ax
274  init_err = sqrt(inner_prod(current_state, r, r, i_strt, i_end, j_strt, j_end, k_end))/sc_err
275 
276  do it=1, max_iterations
277  if( it == 1 ) then
278  call precond(current_state, a, p, r, preconditioner_iterations)
279  rho = inner_prod(current_state, p, r, i_strt, i_end, j_strt, j_end, k_end)
280  alf = rho
281  else
282  call precond(current_state, a, z, r, preconditioner_iterations)
283  alf = inner_prod(current_state, z, r, i_strt, i_end, j_strt, j_end, k_end)
284  bet = alf/rho
285  rho = alf
286  p = z + bet*p
287  end if
288 
289  call calc_ax(current_state, a, p, ax)
290  alf = alf/inner_prod(current_state, p, ax, i_strt, i_end, j_strt, j_end, k_end)
291  x = x + alf*p
292  r = r - alf*ax
293 
294  err = sqrt(inner_prod(current_state, r, r, i_strt, i_end, j_strt, j_end, k_end))/sc_err
295  if (err < tolerance) exit
296  end do
297 
298  if( current_state%parallel%my_rank == 0 ) print*,it, err, init_err
299 
300  if (err > tolerance) then
301  call log_log(log_warn, "Convergence failed, RNorm="//conv_to_string(err, exponent=.true.))
302  else if (current_state%parallel%my_rank==0 .and. log_get_logging_level() .eq. log_debug) then
303  call log_log(log_debug, "Converged in "//trim(conv_to_string(it))//" iterations with RNorm="//&
304  trim(conv_to_string(err, 5, .true.))//" initial norm="//trim(conv_to_string(init_err, 5, .true.)))
305  end if
306  end subroutine cg_solver
307 
314  subroutine precond(current_state, A, s, r, preits)
315  type(model_state_type), target, intent(inout) :: current_state
316  real(kind=default_precision), dimension(:,:,:), intent(in) :: r
317  real(kind=default_precision), dimension(:,:,:), intent(inout) :: s
318  integer, intent(in) :: preits
319  type(matrix_type), intent(inout) :: A
320 
321  real(kind=default_precision), dimension(current_state%local_grid%size(Z_INDEX) + & current_state%local_grid%halo_size(Z_INDEX) * 2, current_state%local_grid%size(Y_INDEX) + & current_state%local_grid%halo_size(Y_INDEX) * 2, current_state%local_grid%size(X_INDEX) + & current_state%local_grid%halo_size(X_INDEX) * 2) :: t
322  real(kind=default_precision), dimension(current_state%local_grid%size(Z_INDEX)) :: s_k
323  integer :: it, i, j, k
324 
325  if (preits .lt. 0) then
326  s=r
327  return
328  end if
329 
330  do i=current_state%local_grid%local_domain_start_index(x_index), current_state%local_grid%local_domain_end_index(x_index)
331  do j=current_state%local_grid%local_domain_start_index(y_index), current_state%local_grid%local_domain_end_index(y_index)
332  s(1,j,i) = 0.0_default_precision
333  k=2
334  s(k,j,i)=r(k,j,i)*a%LU_d(k)
335  do k=3,current_state%local_grid%size(z_index)
336  s(k,j,i)=(r(k,j,i) - a%d(k)*s(k-1,j,i))*a%lu_d(k)
337  end do
338  do k=current_state%local_grid%size(z_index)-1, 2, -1
339  s(k,j,i)=s(k,j,i) - a%lu_u(k)*s(k+1,j,i)
340  end do
341  end do
342  end do
343 
344  do it=1, preits
345  call calc_ax(current_state, a, s, t)
346  do i=current_state%local_grid%local_domain_start_index(x_index), current_state%local_grid%local_domain_end_index(x_index)
347  do j=current_state%local_grid%local_domain_start_index(y_index), current_state%local_grid%local_domain_end_index(y_index)
348  k=2
349  s_k(k)=(r(k,j,i) - t(k,j,i))*a%lu_d(k)
350  do k=3,current_state%local_grid%size(z_index)
351  s_k(k)=(r(k,j,i) - t(k,j,i) - a%d(k)*s_k(k-1))*a%lu_d(k)
352  end do
353  k=current_state%local_grid%size(z_index)
354  s(k,j,i)=s(k,j,i)+s_k(k)
355  do k=current_state%local_grid%size(z_index)-1, 2, -1
356  s_k(k)=s_k(k) - a%lu_u(k)*s_k(k+1)
357  s(k,j,i)=s(k,j,i) + relaxation*s_k(k)
358  end do
359  end do
360  end do
361  end do
362  end subroutine precond
363 
369  subroutine calc_ax(current_state, A, x, Ax)
370  type(model_state_type), target, intent(inout) :: current_state
371  type(matrix_type), intent(in) :: A
372  real(kind=default_precision), dimension(:,:,:), target, intent(inout) :: x, ax
373 
374  integer :: i, k, j, n, istart, iend, jstart, jend
375  type(field_data_wrapper_type) :: source_data
376 
377  source_data%data=>x
378 
379  call initiate_nonblocking_halo_swap(current_state, halo_swap_state, &
380  copy_calc_ax_to_halo_buffer, source_data=(/source_data/))
381 
382  ax(1,:,:) = 0.0_default_precision
383  if (symm_prob) then
384  do n=1, 5
385  if (n==1) then
386  istart=current_state%local_grid%local_domain_start_index(x_index)+1
387  iend=current_state%local_grid%local_domain_end_index(x_index)-1
388  jstart=current_state%local_grid%local_domain_start_index(y_index)+1
389  jend=current_state%local_grid%local_domain_end_index(y_index)-1
390  else if (n==2) then
391  istart=current_state%local_grid%local_domain_start_index(x_index)
392  iend=current_state%local_grid%local_domain_start_index(x_index)
393  else if (n==3) then
394  istart=current_state%local_grid%local_domain_end_index(x_index)
395  iend=current_state%local_grid%local_domain_end_index(x_index)
396  else if (n==4) then
397  jstart=current_state%local_grid%local_domain_start_index(y_index)
398  jend=current_state%local_grid%local_domain_start_index(y_index)
399  istart=current_state%local_grid%local_domain_start_index(x_index)
400  iend=current_state%local_grid%local_domain_end_index(x_index)
401  else if (n==5) then
402  jstart=current_state%local_grid%local_domain_end_index(y_index)
403  jend=current_state%local_grid%local_domain_end_index(y_index)
404  end if
405  do i=istart, iend
406  do j=jstart, jend
407  k=2
408  ax(k,j,i)=a%vol(k)*(a%n*(x(k,j,i+1)+x(k,j,i-1))+a%e*(x(k,j+1,i)+x(k,j-1,i)))+ a%u(k)*x(k+1,j,i)+a%p(k)*x(k,j,i)
409  do k=3,current_state%local_grid%size(z_index)-1
410  ax(k,j,i)=a%vol(k)*(a%n*(x(k,j,i+1)+x(k,j,i-1))+a%e*(x(k,j+1,i)+x(k,j-1,i)))+&
411  a%u(k)*x(k+1,j,i)+a%d(k)*x(k-1,j,i)+a%p(k)*x(k,j,i)
412  end do
413  k=current_state%local_grid%size(z_index)
414  ax(k,j,i) = a%vol(k)*(a%n*(x(k,j,i+1)+x(k,j,i-1))+a%e*(x(k,j+1,i)+x(k,j-1,i)))+ a%d(k)*x(k-1,j,i)+a%p(k)*x(k,j,i)
415  end do
416  end do
417  if (n==1) then
418  call complete_nonblocking_halo_swap(current_state, halo_swap_state, perform_local_data_copy_for_calc_ax, &
419  copy_halo_buffer_to_calc_ax, source_data=(/source_data/))
420  end if
421  end do
422  else
423  do n=1, 5
424  if (n==1) then
425  istart=current_state%local_grid%local_domain_start_index(x_index)+1
426  iend=current_state%local_grid%local_domain_end_index(x_index)-1
427  jstart=current_state%local_grid%local_domain_start_index(y_index)+1
428  jend=current_state%local_grid%local_domain_end_index(y_index)-1
429  else if (n==2) then
430  istart=current_state%local_grid%local_domain_start_index(x_index)
431  iend=current_state%local_grid%local_domain_start_index(x_index)
432  else if (n==3) then
433  istart=current_state%local_grid%local_domain_end_index(x_index)
434  iend=current_state%local_grid%local_domain_end_index(x_index)
435  else if (n==4) then
436  jstart=current_state%local_grid%local_domain_start_index(y_index)
437  jend=current_state%local_grid%local_domain_start_index(y_index)
438  istart=current_state%local_grid%local_domain_start_index(x_index)
439  iend=current_state%local_grid%local_domain_end_index(x_index)
440  else if (n==5) then
441  jstart=current_state%local_grid%local_domain_end_index(y_index)
442  jend=current_state%local_grid%local_domain_end_index(y_index)
443  end if
444  do i=istart, iend
445  do j=jstart, jend
446  k=2
447  ax(k,j,i)=a%n*(x(k,j,i+1)+x(k,j,i-1))+a%e*(x(k,j+1,i)+x(k,j-1,i))+ a%u(k)*x(k+1,j,i)+a%p(k)*x(k,j,i)
448  do k=3,current_state%local_grid%size(z_index)-1
449  ax(k,j,i)=a%n*(x(k,j,i+1)+x(k,j,i-1))+a%e*(x(k,j+1,i)+x(k,j-1,i))+&
450  a%u(k)*x(k+1,j,i)+a%d(k)*x(k-1,j,i)+a%p(k)*x(k,j,i)
451  end do
452  k=current_state%local_grid%size(z_index)
453  ax(k,j,i) = a%n*(x(k,j,i+1)+x(k,j,i-1))+a%e*(x(k,j+1,i)+x(k,j-1,i))+ a%d(k)*x(k-1,j,i)+a%p(k)*x(k,j,i)
454  end do
455  end do
456  if (n==1) then
457  call complete_nonblocking_halo_swap(current_state, halo_swap_state, perform_local_data_copy_for_calc_ax, &
458  copy_halo_buffer_to_calc_ax, source_data=(/source_data/))
459  end if
460  end do
461  endif
462  end subroutine calc_ax
463 
469  real(kind=default_precision) function inner_prod(current_state, x, y, i_strt, i_end, j_strt, j_end, k_end)
470  type(model_state_type), target, intent(inout) :: current_state
471  real(kind=default_precision), dimension(:,:,:), intent(in) :: x, y
472  integer, intent(in) :: i_strt, i_end, j_strt, j_end, k_end
473 
474  real(kind=default_precision) :: local_sum, global_sum
475  integer :: ierr, i, j, k
476 
477  local_sum=0.0_default_precision
478 
479  do i=i_strt, i_end
480  do j=j_strt, j_end
481  do k=2, k_end
482  local_sum=local_sum+x(k,j,i)*y(k,j,i)
483  end do
484  end do
485  end do
486 
487  call mpi_allreduce(local_sum, global_sum, 1, precision_type, mpi_sum, current_state%parallel%monc_communicator, ierr)
488  inner_prod=global_sum
489  end function inner_prod
490 
497  function inner_prod_three_way(current_state, t, s, i_strt, i_end, j_strt, j_end, k_end)
498  type(model_state_type), target, intent(inout) :: current_state
499  integer, intent(in) :: i_strt, i_end, j_strt, j_end, k_end
500  real(kind=default_precision), dimension(:,:,:), intent(in) :: t, s
501  real(kind=default_precision), dimension(3) :: inner_prod_three_way
502 
503  real(kind=default_precision), dimension(3) :: local_sum, global_sum
504  integer :: ierr, i, j, k
505 
506  local_sum(1)=0.0_default_precision
507  local_sum(2)=0.0_default_precision
508  local_sum(3)=0.0_default_precision
509 
510  do i=i_strt, i_end
511  do j=j_strt, j_end
512  do k=2, k_end
513  local_sum(1)=local_sum(1)+t(k,j,i)*t(k,j,i)
514  local_sum(2)=local_sum(2)+t(k,j,i)*s(k,j,i)
515  local_sum(3)=local_sum(3)+s(k,j,i)*s(k,j,i)
516  end do
517  end do
518  end do
519 
520  call mpi_allreduce(local_sum, global_sum, 3, precision_type, mpi_sum, current_state%parallel%monc_communicator, ierr)
521  inner_prod_three_way=global_sum
522  end function inner_prod_three_way
523 
528  subroutine set_matrix_for_poisson(grid_configuration, A, z_size)
529  type(grid_configuration_type), intent(inout) :: grid_configuration
530  type(matrix_type), intent(inout) :: a
531  integer, intent(in) :: z_size
532 
533  integer :: k
534  real(kind=default_precision) :: d_sc, concat_scalars
535 
536  a%n=grid_configuration%horizontal%cx*grid_configuration%horizontal%cx
537  a%s=a%n
538  a%e=grid_configuration%horizontal%cy*grid_configuration%horizontal%cy
539  a%w=a%e
540  concat_scalars=a%n+a%s+a%e+a%w
541  do k=2, z_size
542  if (symm_prob) then
543  a%vol(k)=grid_configuration%vertical%dz(k)
544  d_sc=1.0/grid_configuration%vertical%rhon(k)
545  else
546  d_sc=grid_configuration%vertical%rdz(k) / grid_configuration%vertical%rhon(k)
547  a%vol(k)=1.0
548  endif
549 
550  if (k==z_size) then
551  a%u(k)=0.0_default_precision
552  else
553  a%u(k)=grid_configuration%vertical%rho(k)*grid_configuration%vertical%rdzn(k+1)
554  end if
555  if (k==2) then
556  a%d(k)=0.0_default_precision
557  else
558  a%d(k)=grid_configuration%vertical%rho(k-1)*grid_configuration%vertical%rdzn(k)
559  end if
560  a%p(k) = d_sc * (-(a%u(k) + a%d(k))) - concat_scalars * a%vol(k)
561  a%u(k)=d_sc * a%u(k)
562  a%d(k)=d_sc * a%d(k)
563  end do
564  k=2
565  a%lu_d(k)=1.0_default_precision/a%p(k)
566  a%lu_u(k)=a%lu_d(k)*a%u(k)
567  do k=3, z_size
568  a%lu_d(k)=1.0_default_precision/(a%p(k) - a%d(k)*a%lu_u(k-1))
569  a%lu_u(k)=a%u(k)*a%lu_d(k)
570  end do
571  end subroutine set_matrix_for_poisson
572 
575  subroutine deduce_global_divmax(current_state)
576  type(model_state_type), target, intent(inout) :: current_state
577 
578  integer :: ierr
579 
580  call mpi_allreduce(current_state%local_divmax, current_state%global_divmax, 1, precision_type, mpi_max, &
581  current_state%parallel%monc_communicator, ierr)
582  end subroutine deduce_global_divmax
583 
592  subroutine copy_p_to_halo_buffer(current_state, neighbour_description, dim, source_index, &
593  pid_location, current_page, source_data)
594  type(model_state_type), intent(inout) :: current_state
595  integer, intent(in) :: dim, pid_location, source_index
596  integer, intent(inout) :: current_page(:)
597  type(neighbour_description_type), intent(inout) :: neighbour_description
598  type(field_data_wrapper_type), dimension(:), intent(in), optional :: source_data
599 
600  call copy_field_to_buffer(current_state%local_grid, neighbour_description%send_halo_buffer, current_state%p%data, &
601  dim, source_index, current_page(pid_location))
602 
603  current_page(pid_location)=current_page(pid_location)+1
604  end subroutine copy_p_to_halo_buffer
605 
614  subroutine copy_calc_ax_to_halo_buffer(current_state, neighbour_description, dim, source_index, &
615  pid_location, current_page, source_data)
616  type(model_state_type), intent(inout) :: current_state
617  integer, intent(in) :: dim, pid_location, source_index
618  integer, intent(inout) :: current_page(:)
619  type(neighbour_description_type), intent(inout) :: neighbour_description
620  type(field_data_wrapper_type), dimension(:), intent(in), optional :: source_data
621 
622  type(field_data_wrapper_type) :: selected_source
623 
624  selected_source=source_data(1)
625 
626  call copy_field_to_buffer(current_state%local_grid, neighbour_description%send_halo_buffer, selected_source%data, &
627  dim, source_index, current_page(pid_location))
628 
629  current_page(pid_location)=current_page(pid_location)+1
630  end subroutine copy_calc_ax_to_halo_buffer
631 
640  subroutine copy_halo_buffer_to_p(current_state, neighbour_description, dim, target_index, &
641  neighbour_location, current_page, source_data)
642  type(model_state_type), intent(inout) :: current_state
643  integer, intent(in) :: dim, target_index, neighbour_location
644  integer, intent(inout) :: current_page(:)
645  type(neighbour_description_type), intent(inout) :: neighbour_description
646  type(field_data_wrapper_type), dimension(:), intent(in), optional :: source_data
647 
648  call copy_buffer_to_field(current_state%local_grid, neighbour_description%recv_halo_buffer, current_state%p%data, &
649  dim, target_index, current_page(neighbour_location))
650 
651  current_page(neighbour_location)=current_page(neighbour_location)+1
652  end subroutine copy_halo_buffer_to_p
653 
662  subroutine copy_halo_buffer_to_calc_ax(current_state, neighbour_description, dim, target_index, &
663  neighbour_location, current_page, source_data)
664  type(model_state_type), intent(inout) :: current_state
665  integer, intent(in) :: dim, target_index, neighbour_location
666  integer, intent(inout) :: current_page(:)
667  type(neighbour_description_type), intent(inout) :: neighbour_description
668  type(field_data_wrapper_type), dimension(:), intent(in), optional :: source_data
669 
670  type(field_data_wrapper_type) :: selected_source
671 
672  selected_source=source_data(1)
673 
674  call copy_buffer_to_field(current_state%local_grid, neighbour_description%recv_halo_buffer, selected_source%data, &
675  dim, target_index, current_page(neighbour_location))
676 
677  current_page(neighbour_location)=current_page(neighbour_location)+1
678  end subroutine copy_halo_buffer_to_calc_ax
679 
683  subroutine perform_local_data_copy_for_p(current_state, halo_depth, involve_corners, source_data)
684  type(model_state_type), intent(inout) :: current_state
685  integer, intent(in) :: halo_depth
686  logical, intent(in) :: involve_corners
687  type(field_data_wrapper_type), dimension(:), intent(in), optional :: source_data
688 
689  call perform_local_data_copy_for_field(current_state%p%data, current_state%local_grid, &
690  current_state%parallel%my_rank, halo_depth, involve_corners)
691  end subroutine perform_local_data_copy_for_p
692 
696  subroutine perform_local_data_copy_for_calc_ax(current_state, halo_depth, involve_corners, source_data)
697  type(model_state_type), intent(inout) :: current_state
698  integer, intent(in) :: halo_depth
699  logical, intent(in) :: involve_corners
700  type(field_data_wrapper_type), dimension(:), intent(in), optional :: source_data
701 
702  type(field_data_wrapper_type) :: selected_source
703 
704  selected_source=source_data(1)
705 
706  call perform_local_data_copy_for_field(selected_source%data, current_state%local_grid, &
707  current_state%parallel%my_rank, halo_depth, involve_corners)
709 
713  function create_problem_matrix(z_size)
714  integer, intent(in) :: z_size
715  type(matrix_type) :: create_problem_matrix
716 
717  allocate(create_problem_matrix%u(z_size), create_problem_matrix%d(z_size), create_problem_matrix%p(z_size), &
718  create_problem_matrix%lu_u(z_size), create_problem_matrix%lu_d(z_size), create_problem_matrix%vol(z_size))
719  end function create_problem_matrix
720 
726  subroutine complete_psrce_calculation(current_state, y_halo_size, x_halo_size)
727  type(model_state_type), target, intent(inout) :: current_state
728  integer, intent(in) :: y_halo_size, x_halo_size
729 
730  integer :: ierr, combined_handles(2), i, j, k
731 
732  combined_handles(1)=current_state%psrce_x_hs_recv_request
733  combined_handles(2)=current_state%psrce_y_hs_recv_request
734  call mpi_waitall(2, combined_handles, mpi_statuses_ignore, ierr)
735 
736  do j=current_state%local_grid%local_domain_start_index(y_index), current_state%local_grid%local_domain_end_index(y_index)
737  do k=2,current_state%local_grid%size(z_index)
738 #ifdef U_ACTIVE
739  current_state%p%data(k,j,x_halo_size+1)=current_state%p%data(k,j,x_halo_size+1)-&
740  current_state%psrce_recv_buffer_x(k-1,j-x_halo_size)
741 #endif
742 #ifdef V_ACTIVE
743  if (j .gt. y_halo_size+1) current_state%p%data(k, j, x_halo_size+1)=current_state%p%data(k, j, x_halo_size+1)-&
744  current_state%global_grid%configuration%horizontal%cy * current_state%sv%data(k, j-1, x_halo_size+1)
745 #endif
746  end do
747  end do
748 
749 #ifdef V_ACTIVE
750  do i=current_state%local_grid%local_domain_start_index(x_index), current_state%local_grid%local_domain_end_index(x_index)
751  do k=2,current_state%local_grid%size(z_index)
752  current_state%p%data(k,y_halo_size+1,i)=current_state%p%data(k,y_halo_size+1,i)-&
753  current_state%psrce_recv_buffer_y(k-1,i-y_halo_size)
754  end do
755  end do
756 #endif
757 
758  combined_handles(1)=current_state%psrce_x_hs_send_request
759  combined_handles(2)=current_state%psrce_y_hs_send_request
760  call mpi_waitall(2, combined_handles, mpi_statuses_ignore, ierr)
761  end subroutine complete_psrce_calculation
762 end module iterativesolver_mod
763 
registry_mod::is_component_enabled
logical function, public is_component_enabled(options_database, component_name)
Determines whether or not a specific component is registered and enabled.
Definition: registry.F90:334
iterativesolver_mod::halo_swap_state
type(halo_communication_type), save halo_swap_state
The halo swap state as initialised by that module.
Definition: iterativesolver.F90:37
logging_mod::log_error
integer, parameter, public log_error
Only log ERROR messages.
Definition: logging.F90:11
conversions_mod
Conversion between common inbuilt FORTRAN data types.
Definition: conversions.F90:5
collections_mod::map_type
Map data structure that holds string (length 20 maximum) key value pairs.
Definition: collections.F90:86
communication_types_mod::neighbour_description_type
Describes the neighbours of a process in a specific dimension and contains the communication buffers ...
Definition: communicationtypes.F90:20
iterativesolver_mod::perform_local_data_copy_for_p
subroutine perform_local_data_copy_for_p(current_state, halo_depth, involve_corners, source_data)
Does local data copying for P variable halo swap.
Definition: iterativesolver.F90:693
logging_mod::log_warn
integer, parameter, public log_warn
Log WARNING and ERROR messages.
Definition: logging.F90:12
halo_communication_mod
Provides the mechanism for halo swapping. This module contains the functionality required to determin...
Definition: halocommunication.F90:8
iterativesolver_mod::perform_local_data_copy_for_calc_ax
subroutine perform_local_data_copy_for_calc_ax(current_state, halo_depth, involve_corners, source_data)
Does a local data copy for halo swapping cells with wrap around (to maintain periodic boundary condit...
Definition: iterativesolver.F90:706
iterativesolver_mod::copy_halo_buffer_to_p
subroutine copy_halo_buffer_to_p(current_state, neighbour_description, dim, target_index, neighbour_location, current_page, source_data)
Copies the halo buffer to halo location for the p field.
Definition: iterativesolver.F90:651
iterativesolver_mod::timestep_callback
subroutine timestep_callback(current_state)
Timestep callback, this ignores all but the last column where it calls the solver.
Definition: iterativesolver.F90:85
iterativesolver_mod::psource
real(kind=default_precision), dimension(:,:,:), allocatable psource
Definition: iterativesolver.F90:38
collections_mod
Collection data structures.
Definition: collections.F90:7
grids_mod::x_index
integer, parameter, public x_index
Definition: grids.F90:14
optionsdatabase_mod::options_get_integer
integer function, public options_get_integer(options_database, key, index)
Retrieves an integer value from the database that matches the provided key.
Definition: optionsdatabase.F90:217
grids_mod::y_index
integer, parameter, public y_index
Definition: grids.F90:14
halo_communication_mod::init_halo_communication
subroutine, public init_halo_communication(current_state, get_fields_per_halo_cell, halo_state, halo_depth, involve_corners)
Initialises a halo swapping state, by determining the neighbours, size of data in each swap and alloc...
Definition: halocommunication.F90:295
datadefn_mod::precision_type
integer, public precision_type
Definition: datadefn.F90:19
communication_types_mod
Contains the types used for communication, holding the state of communications and supporting activit...
Definition: communicationtypes.F90:5
logging_mod::log_log
subroutine, public log_log(level, message, str)
Logs a message at the specified level. If the level is above the current level then the message is ig...
Definition: logging.F90:75
iterativesolver_mod::copy_p_to_halo_buffer
subroutine copy_p_to_halo_buffer(current_state, neighbour_description, dim, source_index, pid_location, current_page, source_data)
Copies the p field data to halo buffers for a specific process in a dimension and halo cell.
Definition: iterativesolver.F90:603
halo_communication_mod::initiate_nonblocking_halo_swap
subroutine, public initiate_nonblocking_halo_swap(current_state, halo_swap_state, copy_to_halo_buffer, copy_corners_to_halo_buffer, source_data)
Initiates a non blocking halo swap, this registers the receive requests, copies data into the send bu...
Definition: halocommunication.F90:245
logging_mod::log_get_logging_level
integer function, public log_get_logging_level()
Retrieves the current logging level.
Definition: logging.F90:122
halo_communication_mod::copy_field_to_buffer
subroutine, public copy_field_to_buffer(local_grid, halo_buffer, field_data, dim, source_index, halo_page)
Copies prognostic field data to send buffer for specific field, dimension, halo cell.
Definition: halocommunication.F90:433
logging_mod::log_debug
integer, parameter, public log_debug
Log DEBUG, INFO, WARNING and ERROR messages.
Definition: logging.F90:14
communication_types_mod::halo_communication_type
Maintains the state of a halo swap and contains buffers, neighbours etc.
Definition: communicationtypes.F90:28
grids_mod::grid_configuration_type
Wraps the dimensional configuration types.
Definition: grids.F90:101
monc_component_mod
Interfaces and types that MONC components must specify.
Definition: monc_component.F90:6
iterativesolver_mod::bicgstab
subroutine bicgstab(current_state, A, x, b, i_strt, i_end, j_strt, j_end, k_end)
Performs the BiCGStab KS method.
Definition: iterativesolver.F90:136
iterativesolver_mod::deduce_global_divmax
subroutine deduce_global_divmax(current_state)
Determines the global divmax which is written into the current state.
Definition: iterativesolver.F90:585
communication_types_mod::field_data_wrapper_type
Definition: communicationtypes.F90:14
halo_communication_mod::complete_nonblocking_halo_swap
subroutine, public complete_nonblocking_halo_swap(current_state, halo_swap_state, perform_local_data_copy, copy_from_halo_buffer, copy_from_halo_buffer_to_corner, source_data)
This completes a nonblocking halo swap and it is only during this call that the data fields themselve...
Definition: halocommunication.F90:182
iterativesolver_mod::tiny
real(kind=default_precision), parameter tiny
Minimum residual - if we go below this then something has gone wrong.
Definition: iterativesolver.F90:35
iterativesolver_mod::precond
subroutine precond(current_state, A, s, r, preits)
Jacobi preconditioner.
Definition: iterativesolver.F90:321
iterativesolver_mod::initialisation_callback
subroutine initialisation_callback(current_state)
Initialisation callback hook which will set up the halo swapping state and allocate some data.
Definition: iterativesolver.F90:58
iterativesolver_mod
This is the iterative pressure solver and uses a Jacobi preconditioned BiCGStab which we implement he...
Definition: iterativesolver.F90:2
iterativesolver_mod::calc_ax
subroutine calc_ax(current_state, A, x, Ax)
Calculates A * x.
Definition: iterativesolver.F90:379
iterativesolver_mod::matrix_type
A helper type to abstract the concrete details of the matrix.
Definition: iterativesolver.F90:25
grids_mod::z_index
integer, parameter, public z_index
Grid index parameters.
Definition: grids.F90:14
conversions_mod::conv_to_string
Converts data types to strings.
Definition: conversions.F90:38
iterativesolver_mod::symm_prob
logical symm_prob
Definition: iterativesolver.F90:33
iterativesolver_mod::preconditioner_iterations
integer preconditioner_iterations
Number of preconditioner iterations to perform per call.
Definition: iterativesolver.F90:31
iterativesolver_mod::finalisation_callback
subroutine finalisation_callback(current_state)
Called as MONC is shutting down and frees the halo swap state and deallocates local data.
Definition: iterativesolver.F90:124
state_mod::model_state_type
The ModelState which represents the current state of a run.
Definition: state.F90:39
iterativesolver_mod::copy_halo_buffer_to_calc_ax
subroutine copy_halo_buffer_to_calc_ax(current_state, neighbour_description, dim, target_index, neighbour_location, current_page, source_data)
Copies the halo buffer to halo location for the source field as required in the calc_Ax procedure.
Definition: iterativesolver.F90:673
iterativesolver_mod::prev_p
real(kind=default_precision), dimension(:,:,:), allocatable prev_p
Passed to BiCGStab as the RHS.
Definition: iterativesolver.F90:38
iterativesolver_mod::max_iterations
integer max_iterations
Maximum number of BiCGStab iterations.
Definition: iterativesolver.F90:31
halo_communication_mod::copy_buffer_to_field
subroutine, public copy_buffer_to_field(local_grid, halo_buffer, field_data, dim, target_index, halo_page)
Copies the received buffer for a specific field to the corresponding halo data of that prognostic fie...
Definition: halocommunication.F90:401
optionsdatabase_mod::options_get_logical
logical function, public options_get_logical(options_database, key, index)
Retrieves a logical value from the database that matches the provided key.
Definition: optionsdatabase.F90:154
iterativesolver_mod::cg_solver
subroutine cg_solver(current_state, A, x, b, i_strt, i_end, j_strt, j_end, k_end)
Performs the preconditioned conjugate gradient method.
Definition: iterativesolver.F90:249
iterativesolver_mod::iterativesolver_get_descriptor
type(component_descriptor_type) function, public iterativesolver_get_descriptor()
Descriptor of the iterative solver component used by the registry.
Definition: iterativesolver.F90:48
grids_mod::local_grid_type
Defined the local grid, i.e. the grid held on this process after decomposition.
Definition: grids.F90:118
iterativesolver_mod::inner_prod
real(kind=default_precision) function inner_prod(current_state, x, y, i_strt, i_end, j_strt, j_end, k_end)
Returns the global inner product of two vectors, ignoring the halo cells.
Definition: iterativesolver.F90:479
iterativesolver_mod::inner_prod_three_way
real(kind=default_precision) function, dimension(3) inner_prod_three_way(current_state, t, s, i_strt, i_end, j_strt, j_end, k_end)
Returns the global inner product of a pair of vectors, ignoring the halo cells for three separate pai...
Definition: iterativesolver.F90:507
logging_mod
Logging utility.
Definition: logging.F90:2
datadefn_mod
Contains common definitions for the data and datatypes used by MONC.
Definition: datadefn.F90:2
iterativesolver_mod::complete_psrce_calculation
subroutine complete_psrce_calculation(current_state, y_halo_size, x_halo_size)
Completes the psrce calculation by waiting on all outstanding psrce communications to complete and th...
Definition: iterativesolver.F90:736
logging_mod::log_master_log
subroutine, public log_master_log(level, message)
Will log just from the master process.
Definition: logging.F90:47
registry_mod
MONC component registry.
Definition: registry.F90:5
iterativesolver_mod::create_problem_matrix
type(matrix_type) function create_problem_matrix(z_size)
Creates a problem matrix, allocating the required data based upon the column size.
Definition: iterativesolver.F90:723
halo_communication_mod::get_single_field_per_halo_cell
integer function, public get_single_field_per_halo_cell(current_state)
A very common function, which returns a single field per halo cell which is used to halo swap just on...
Definition: halocommunication.F90:1230
iterativesolver_mod::first_run
logical first_run
Definition: iterativesolver.F90:39
halo_communication_mod::blocking_halo_swap
subroutine, public blocking_halo_swap(current_state, halo_swap_state, copy_to_halo_buffer, perform_local_data_copy, copy_from_halo_buffer, copy_corners_to_halo_buffer, copy_from_halo_buffer_to_corner, source_data)
Performs the entire halo swap operation, this is simply a wrapper around the nonblocking initiate and...
Definition: halocommunication.F90:112
grids_mod
Functionality to support the different types of grid and abstraction between global grids and local o...
Definition: grids.F90:5
halo_communication_mod::finalise_halo_communication
subroutine, public finalise_halo_communication(halo_swap_state)
Finalises the halo swap represented by the state by freeing up all the allocated memory.
Definition: halocommunication.F90:340
iterativesolver_mod::set_matrix_for_poisson
subroutine set_matrix_for_poisson(grid_configuration, A, z_size)
Sets the values of the provided matrix to solve the poisson equation.
Definition: iterativesolver.F90:538
iterativesolver_mod::tolerance
real(kind=default_precision) tolerance
Definition: iterativesolver.F90:30
optionsdatabase_mod
Manages the options database. Contains administration functions and deduce runtime options from the c...
Definition: optionsdatabase.F90:7
iterativesolver_mod::relaxation
real(kind=default_precision) relaxation
Solving tollerance.
Definition: iterativesolver.F90:30
iterativesolver_mod::copy_calc_ax_to_halo_buffer
subroutine copy_calc_ax_to_halo_buffer(current_state, neighbour_description, dim, source_index, pid_location, current_page, source_data)
Copies the source field data to halo buffers for a specific process in a dimension and halo cell - fo...
Definition: iterativesolver.F90:625
monc_component_mod::component_descriptor_type
Description of a component.
Definition: monc_component.F90:42
optionsdatabase_mod::options_get_real
real(kind=default_precision) function, public options_get_real(options_database, key, index)
Retrieves a real value from the database that matches the provided key.
Definition: optionsdatabase.F90:91
halo_communication_mod::perform_local_data_copy_for_field
subroutine, public perform_local_data_copy_for_field(field_data, local_grid, my_rank, halo_depth, involve_corners)
Will perform a a local copy for the halo data of a field.
Definition: halocommunication.F90:483
datadefn_mod::default_precision
integer, parameter, public default_precision
MPI communication type which we use for the prognostic and calculation data.
Definition: datadefn.F90:17
state_mod
The model state which represents the current state of a run.
Definition: state.F90:2
iterativesolver_mod::a
type(matrix_type) a
Definition: iterativesolver.F90:40