17   use mpi
, only : mpi_max, mpi_sum, mpi_comm_world, mpi_request_null, mpi_statuses_ignore
    26      real(kind=DEFAULT_PRECISION) :: n, s, e, w
    27      real(kind=DEFAULT_PRECISION), 
dimension(:), 
allocatable :: u, d, p, lu_d, lu_u, vol
    35   real(kind=DEFAULT_PRECISION), 
parameter :: 
tiny = 1.0e-16 
    38   real(kind=DEFAULT_PRECISION), 
dimension(:,:,:), 
allocatable :: 
psource, 
prev_p    58     type(model_state_type), 
target, 
intent(inout) :: current_state
    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")
    64     tolerance=options_get_real(current_state%options_database, 
"tolerance")
    65     max_iterations=options_get_integer(current_state%options_database, 
"max_iterations")
    67     symm_prob=options_get_logical(current_state%options_database, 
"symm_prob")
    69     call init_halo_communication(current_state, get_single_field_per_halo_cell, 
halo_swap_state, 1, .false.)
    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))
    85     type(model_state_type), 
target, 
intent(inout) :: current_state
    87     integer :: i_strt, i_end, j_strt, j_end, k_end
    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)
    96          current_state%local_grid%halo_size(x_index))
   105       current_state%p%data=0.0_default_precision
   109       current_state%p%data=
prev_p   113       call cg_solver(current_state, 
a, current_state%p%data, 
psource, i_strt, i_end, j_strt, j_end, k_end)
   115       call bicgstab(current_state, 
a, current_state%p%data, 
psource, i_strt, i_end, j_strt, j_end, k_end)
   118     prev_p=current_state%p%data
   124     type(model_state_type), 
target, 
intent(inout) :: current_state
   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
   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
   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
   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)
   151     call calc_ax(current_state, a, x, ax)
   156           r(k,j,i) = b(k,j,i) - ax(k,j,i)
   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
   166     alf = 1.0_default_precision
   167     omg = 1.0_default_precision
   168     nrm = 1.0_default_precision
   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)
   180                 t(k,j,i) = r(k,j,i) - bet*omg*v(k,j,i)
   188                 pp(k,j,i) = s(k,j,i) + bet*pp(k,j,i)
   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)
   200               s(k,j,i) = r(k,j,i) - alf*v(k,j,i)
   206         call calc_ax(current_state, a, cs, t)
   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)
   213         x = x + alf*pp + omg*cs
   217               r(k,j,i) = s(k,j,i) - omg*t(k,j,i)
   223         if (abs(omg) < 
tiny) 
then   224           call log_log(log_warn, 
"Convergence problem, omega="//conv_to_string(omg))
   227         err = sqrt(ss - 2*omg*ts + omg**2 *tt)/sc_err        
   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.)))
   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
   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
   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
   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)
   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)
   269     call calc_ax(current_state, a, x, ax)
   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)
   274     init_err = sqrt(
inner_prod(current_state, r, r, i_strt, i_end, j_strt, j_end, k_end))/sc_err
   279           rho = 
inner_prod(current_state, p, r, i_strt, i_end, j_strt, j_end, k_end)
   283           alf = 
inner_prod(current_state, z, r, i_strt, i_end, j_strt, j_end, k_end)
   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)
   294        err = sqrt(
inner_prod(current_state, r, r, i_strt, i_end, j_strt, j_end, k_end))/sc_err
   298     if( current_state%parallel%my_rank == 0 ) print*,it, err, init_err
   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.)))
   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
   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
   325     if (preits .lt. 0) 
then   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
   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)
   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)
   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)
   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) 
   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) 
   369   subroutine calc_ax(current_state, A, x, Ax)
   370     type(model_state_type), 
target, 
intent(inout) :: current_state
   372     real(kind=DEFAULT_PRECISION), 
dimension(:,:,:), 
target, 
intent(inout) :: x, Ax
   374     integer :: i, k, j, n, istart, iend, jstart, jend
   375     type(field_data_wrapper_type) :: source_data   
   382     ax(1,:,:) = 0.0_default_precision
   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
   391           istart=current_state%local_grid%local_domain_start_index(x_index)
   392           iend=current_state%local_grid%local_domain_start_index(x_index)
   394           istart=current_state%local_grid%local_domain_end_index(x_index)
   395           iend=current_state%local_grid%local_domain_end_index(x_index)
   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)
   402           jstart=current_state%local_grid%local_domain_end_index(y_index)
   403           jend=current_state%local_grid%local_domain_end_index(y_index)
   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)
   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)
   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
   430           istart=current_state%local_grid%local_domain_start_index(x_index)
   431           iend=current_state%local_grid%local_domain_start_index(x_index)
   433           istart=current_state%local_grid%local_domain_end_index(x_index)
   434           iend=current_state%local_grid%local_domain_end_index(x_index)
   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)
   441           jstart=current_state%local_grid%local_domain_end_index(y_index)
   442           jend=current_state%local_grid%local_domain_end_index(y_index)
   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)
   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)
   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
   474     real(kind=DEFAULT_PRECISION) :: local_sum, global_sum
   475     integer :: ierr, i, j, k
   477     local_sum=0.0_default_precision
   482           local_sum=local_sum+x(k,j,i)*y(k,j,i)
   487     call mpi_allreduce(local_sum, global_sum, 1, precision_type, mpi_sum, current_state%parallel%monc_communicator, ierr)
   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
   503     real(kind=DEFAULT_PRECISION), 
dimension(3) :: local_sum, global_sum
   504     integer :: ierr, i, j, k
   506     local_sum(1)=0.0_default_precision
   507     local_sum(2)=0.0_default_precision
   508     local_sum(3)=0.0_default_precision
   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)
   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
   529     type(grid_configuration_type), 
intent(inout) :: grid_configuration
   531     integer, 
intent(in) :: z_size    
   534     real(kind=DEFAULT_PRECISION) :: d_sc, concat_scalars    
   536     a%n=grid_configuration%horizontal%cx*grid_configuration%horizontal%cx
   538     a%e=grid_configuration%horizontal%cy*grid_configuration%horizontal%cy
   540     concat_scalars=a%n+a%s+a%e+a%w
   543          a%vol(k)=grid_configuration%vertical%dz(k)
   544          d_sc=1.0/grid_configuration%vertical%rhon(k)
   546          d_sc=grid_configuration%vertical%rdz(k) / grid_configuration%vertical%rhon(k)
   551         a%u(k)=0.0_default_precision
   553         a%u(k)=grid_configuration%vertical%rho(k)*grid_configuration%vertical%rdzn(k+1)
   556         a%d(k)=0.0_default_precision
   558         a%d(k)=grid_configuration%vertical%rho(k-1)*grid_configuration%vertical%rdzn(k)
   560       a%p(k) = d_sc * (-(a%u(k) + a%d(k))) - concat_scalars * a%vol(k)
   565      a%lu_d(k)=1.0_default_precision/a%p(k) 
   566      a%lu_u(k)=a%lu_d(k)*a%u(k) 
   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) 
   576     type(model_state_type), 
target, 
intent(inout) :: current_state
   580     call mpi_allreduce(current_state%local_divmax, current_state%global_divmax, 1, precision_type, mpi_max, &
   581          current_state%parallel%monc_communicator, ierr)
   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
   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))
   603     current_page(pid_location)=current_page(pid_location)+1
   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
   622     type(field_data_wrapper_type) :: selected_source
   624     selected_source=source_data(1)
   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))
   629     current_page(pid_location)=current_page(pid_location)+1
   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
   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))
   651     current_page(neighbour_location)=current_page(neighbour_location)+1
   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
   670     type(field_data_wrapper_type) :: selected_source
   672     selected_source=source_data(1)
   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))
   677     current_page(neighbour_location)=current_page(neighbour_location)+1
   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
   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)
   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
   702     type(field_data_wrapper_type) :: selected_source
   704     selected_source=source_data(1)
   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)
   714     integer, 
intent(in) :: z_size
   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))
   727     type(model_state_type), 
target, 
intent(inout) :: current_state
   728     integer, 
intent(in) :: y_halo_size, x_halo_size
   730     integer :: ierr, combined_handles(2), i, j, k
   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)
   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)
   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)
   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)
   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)
   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)
   763 integer, public precision_type
 
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...
 
type(halo_communication_type), save halo_swap_state
The halo swap state as initialised by that module. 
 
real(kind=default_precision) tolerance
 
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...
 
subroutine finalisation_callback(current_state)
Called as MONC is shutting down and frees the halo swap state and deallocates local data...
 
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. 
 
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...
 
integer, parameter, public log_error
Only log ERROR messages. 
 
Contains the types used for communication, holding the state of communications and supporting activit...
 
subroutine set_matrix_for_poisson(grid_configuration, A, z_size)
Sets the values of the provided matrix to solve the poisson equation. 
 
A helper type to abstract the concrete details of the matrix. 
 
subroutine deduce_global_divmax(current_state)
Determines the global divmax which is written into the current state. 
 
integer, parameter, public default_precision
MPI communication type which we use for the prognostic and calculation data. 
 
integer, parameter, public z_index
Grid index parameters. 
 
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...
 
subroutine initialisation_callback(current_state)
Initialisation callback hook which will set up the halo swapping state and allocate some data...
 
Contains common definitions for the data and datatypes used by MONC. 
 
The ModelState which represents the current state of a run. 
 
logical function, public is_component_enabled(options_database, component_name)
Determines whether or not a specific component is registered and enabled. 
 
subroutine, public log_master_log(level, message)
Will log just from the master process. 
 
integer, parameter, public log_debug
Log DEBUG, INFO, WARNING and ERROR messages. 
 
Conversion between common inbuilt FORTRAN data types. 
 
Converts data types to strings. 
 
Description of a component. 
 
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...
 
Wraps the dimensional configuration types. 
 
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...
 
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...
 
real(kind=default_precision), parameter tiny
Minimum residual - if we go below this then something has gone wrong. 
 
type(component_descriptor_type) function, public iterativesolver_get_descriptor()
Descriptor of the iterative solver component used by the registry. 
 
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. 
 
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...
 
Maintains the state of a halo swap and contains buffers, neighbours etc. 
 
Map data structure that holds string (length 20 maximum) key value pairs. 
 
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. 
 
real(kind=default_precision), dimension(:,:,:), allocatable psource
 
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...
 
Interfaces and types that MONC components must specify. 
 
real(kind=default_precision), dimension(:,:,:), allocatable prev_p
Passed to BiCGStab as the RHS. 
 
Defined the local grid, i.e. the grid held on this process after decomposition. 
 
Collection data structures. 
 
subroutine cg_solver(current_state, A, x, b, i_strt, i_end, j_strt, j_end, k_end)
Performs the preconditioned conjugate gradient method. 
 
subroutine perform_local_data_copy_for_p(current_state, halo_depth, involve_corners, source_data)
Does local data copying for P variable halo swap. 
 
Provides the mechanism for halo swapping. This module contains the functionality required to determin...
 
real(kind=default_precision) relaxation
Solving tollerance. 
 
integer, parameter, public log_warn
Log WARNING and ERROR messages. 
 
Describes the neighbours of a process in a specific dimension and contains the communication buffers ...
 
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...
 
This is the iterative pressure solver and uses a Jacobi preconditioned BiCGStab which we implement he...
 
subroutine precond(current_state, A, s, r, preits)
Jacobi preconditioner. 
 
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. 
 
subroutine bicgstab(current_state, A, x, b, i_strt, i_end, j_strt, j_end, k_end)
Performs the BiCGStab KS method. 
 
subroutine calc_ax(current_state, A, x, Ax)
Calculates A * x. 
 
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. 
 
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...
 
type(matrix_type) function create_problem_matrix(z_size)
Creates a problem matrix, allocating the required data based upon the column size. 
 
Functionality to support the different types of grid and abstraction between global grids and local o...
 
integer function, public options_get_integer(options_database, key, index)
Retrieves an integer value from the database that matches the provided key. 
 
subroutine, public finalise_halo_communication(halo_swap_state)
Finalises the halo swap represented by the state by freeing up all the allocated memory. 
 
Manages the options database. Contains administration functions and deduce runtime options from the c...
 
logical function, public options_get_logical(options_database, key, index)
Retrieves a logical value from the database that matches the provided key. 
 
integer preconditioner_iterations
Number of preconditioner iterations to perform per call. 
 
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...
 
integer max_iterations
Maximum number of BiCGStab iterations. 
 
The model state which represents the current state of a run. 
 
integer function, public log_get_logging_level()
Retrieves the current logging level. 
 
integer, parameter, public y_index
 
integer, parameter, public x_index
 
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...
 
subroutine timestep_callback(current_state)
Timestep callback, this ignores all but the last column where it calls the solver.