2 #include "petsc/finclude/petscvecdef.h" 
    3 #include "petsc/finclude/petscmatdef.h" 
    4 #include "petsc/finclude/petsckspdef.h" 
    5 #include "petsc/finclude/petscdmdadef.h" 
   52     type(model_state_type), 
target, 
intent(inout) :: current_state
 
   54     petscerrorcode :: ierr
 
   56     call petscfinalize(ierr)
 
   63     type(model_state_type), 
target, 
intent(inout) :: current_state
 
   65     petscerrorcode :: ierr
 
   69     integer :: y_lengths(current_state%parallel%dim_sizes(Y_INDEX)), x_lengths(current_state%parallel%dim_sizes(X_INDEX))
 
   70     integer new_communicator, my_transposed_rank, x_rank_val, y_rank_val
 
   72     call apply_dimension_bounds(current_state%global_grid%size(y_index), current_state%parallel%dim_sizes(y_index), y_lengths)
 
   73     call apply_dimension_bounds(current_state%global_grid%size(x_index), current_state%parallel%dim_sizes(x_index), x_lengths)
 
   75     allocate(
p_source(current_state%local_grid%size(z_index)-1, current_state%local_grid%size(y_index), &
 
   76          current_state%local_grid%size(x_index)), 
prev_p(current_state%local_grid%size(z_index)-1, &
 
   77          current_state%local_grid%size(y_index), current_state%local_grid%size(x_index)))
 
   79     cx=current_state%global_grid%configuration%horizontal%cx
 
   80     cy=current_state%global_grid%configuration%horizontal%cy
 
   81     allocate(
rdzn(current_state%local_grid%size(z_index)-1), 
rdz(current_state%local_grid%size(z_index)-1), &
 
   82          rho(current_state%local_grid%size(z_index)-1), 
rhon(current_state%local_grid%size(z_index)-1), &
 
   83          dz(current_state%local_grid%size(z_index)-1), 
dzn(current_state%local_grid%size(z_index)-1))
 
   84     rdzn=current_state%global_grid%configuration%vertical%rdzn(2:)
 
   85     rdz=current_state%global_grid%configuration%vertical%rdz(2:)
 
   86     rho=current_state%global_grid%configuration%vertical%rho(2:)
 
   87     rhon=current_state%global_grid%configuration%vertical%rhon(2:)
 
   88     dz=current_state%global_grid%configuration%vertical%dz(2:)
 
   89     dzn=current_state%global_grid%configuration%vertical%dzn(2:)
 
   91     z_start=current_state%local_grid%halo_size(z_index)+2
 
   92     z_end=current_state%local_grid%halo_size(z_index)+current_state%local_grid%size(z_index)
 
   93     y_start=current_state%local_grid%halo_size(y_index)+1
 
   94     y_end=current_state%local_grid%halo_size(y_index)+current_state%local_grid%size(y_index)
 
   95     x_start=current_state%local_grid%halo_size(x_index)+1
 
   96     x_end=current_state%local_grid%halo_size(x_index)+current_state%local_grid%size(x_index)
 
   98     y_rank_val = current_state%parallel%my_rank / current_state%parallel%dim_sizes(x_index)
 
   99     x_rank_val = mod(current_state%parallel%my_rank, current_state%parallel%dim_sizes(x_index))    
 
  100     my_transposed_rank = x_rank_val*current_state%parallel%dim_sizes(y_index) + y_rank_val
 
  102     call mpi_comm_split(current_state%parallel%monc_communicator, 1, my_transposed_rank, new_communicator, ierr)
 
  103     petsc_comm_world = new_communicator
 
  105     call petscinitialize(petsc_null_character, ierr)    
 
  106     call kspcreate(petsc_comm_world, ksp, ierr)
 
  107     call dmdacreate3d(petsc_comm_world, dm_boundary_none, dm_boundary_periodic, dm_boundary_periodic, dmda_stencil_star, &
 
  108          current_state%global_grid%size(z_index)-1, current_state%global_grid%size(y_index), &
 
  109          current_state%global_grid%size(x_index), 1, current_state%parallel%dim_sizes(y_index), &
 
  110          current_state%parallel%dim_sizes(x_index), 1, 1, (/ current_state%global_grid%size(z_index)-1 /), &
 
  111          y_lengths, x_lengths, da, ierr)
 
  112     call kspsetdm(ksp, da, ierr)
 
  113     call kspsetcomputerhs(ksp, 
compute_rhs, petsc_null_object, ierr)
 
  114     call kspsetcomputeoperators(ksp, 
compute_matrix, petsc_null_object, ierr)
 
  116     call petscoptionssetvalue(
"-options_left", 
"no", ierr)
 
  117     if (trim(options_get_string(current_state%options_database, 
"solver_type")) .ne. 
"auto") 
then 
  118       call petscoptionssetvalue(
"-ksp_type", trim(options_get_string(current_state%options_database, 
"solver_type")), ierr)
 
  120     if (trim(options_get_string(current_state%options_database, 
"preconditioner_type")) .ne. 
"auto") 
then 
  121       call petscoptionssetvalue(
"-pc_type", trim(options_get_string(current_state%options_database, 
"preconditioner_type")), ierr)
 
  123     if (trim(options_get_string(current_state%options_database, 
"norm_type")) .ne. 
"auto") 
then 
  124       if (trim(options_get_string(current_state%options_database, 
"norm_type")) .eq. 
"preconditioned" .or. &
 
  125            trim(options_get_string(current_state%options_database, 
"norm_type")) .eq. 
"unpreconditioned" .or. &
 
  126            trim(options_get_string(current_state%options_database, 
"norm_type")) .eq. 
"natural" .or. &
 
  127            trim(options_get_string(current_state%options_database, 
"norm_type")) .eq. 
"none") 
then 
  128         call petscoptionssetvalue(
"-ksp_norm_type", trim(options_get_string(current_state%options_database, 
"norm_type")), ierr)
 
  130         call log_master_log(log_error, 
"Configured PETSc norm type of '"//&
 
  131              trim(options_get_string(current_state%options_database, 
"norm_type"))//
"' not recognised")
 
  134     call petscoptionssetvalue(
"-ksp_rtol", conv_to_string(options_get_real(current_state%options_database, 
"tolerance")), ierr)
 
  135     if (options_get_integer(current_state%options_database, 
"max_iterations") .gt. 0) 
then 
  136       call petscoptionssetvalue(
"-ksp_max_it", &
 
  137            conv_to_string(options_get_integer(current_state%options_database, 
"max_iterations")), ierr)
 
  139     call kspsetfromoptions(ksp, ierr)
 
  140     call kspsetinitialguessnonzero(ksp, petsc_true, ierr)
 
  142     if (log_is_master() .and. log_get_logging_level() == log_debug) 
then 
  143       call kspmonitorset(ksp,
ksp_monitor,petsc_null_object, petsc_null_function,ierr)
 
  145     prev_p=0.0_default_precision
 
  146     call init_halo_communication(current_state, get_single_field_per_halo_cell, 
halo_swap_state, 1, .false.)
 
  147     call kspgettype(ksp, ksp_type, ierr)
 
  148     call kspgetpc(ksp, pc_instance, ierr)
 
  149     call pcgettype(pc_instance, pc_type, ierr)
 
  150     call log_master_log(log_info, 
"PETSc iterative solver initialised, using "//trim(pc_type)//
" preconditioner with "//&
 
  151          trim(ksp_type)//
" solver")
 
  166     call log_log(log_debug, 
"Iteration="//trim(conv_to_string(n))//
" Rnorm="//trim(conv_to_string(rnorm, &
 
  167          exponent_small_numbers=.true.)))
 
  175     type(model_state_type), 
target, 
intent(inout) :: current_state
 
  177     petscerrorcode :: ierr
 
  179     petscscalar, 
pointer :: xx(:)
 
  180     integer :: its, i, j, k
 
  182     kspconvergedreason :: reason
 
  185          current_state%local_grid%halo_size(x_index))    
 
  188     call kspsolve(ksp, petsc_null_object, petsc_null_object, ierr)
 
  189     call kspgetsolution(ksp, x, ierr)
 
  190     call vecgetarrayreadf90(x, xx, ierr)
 
  193     call vecrestorearrayreadf90(x, xx, ierr)
 
  197     if (log_is_master() .and. log_get_logging_level() == log_debug) 
then 
  198       call kspgetiterationnumber(ksp, its, ierr)
 
  199       call kspgetresidualnorm(ksp, rnorm, ierr)
 
  200       call kspgetconvergedreason(ksp, reason, ierr)
 
  201       call log_log(log_debug, 
"Converged in "//trim(conv_to_string(its))//
" rnorm="//trim(conv_to_string(&
 
  209     integer, 
intent(in) :: r_code
 
  211     if (r_code == 1 .or. r_code == 2) 
then 
  213     else if (r_code == 9 .or. r_code == 3) 
then 
  215     else if (r_code == 4) 
then 
  217     else if (r_code == -3) 
then 
  219     else if (r_code == -4) 
then 
  221     else if (r_code .gt. 0) 
then 
  223     else if (r_code .lt. 0) 
then 
  235     petscerrorcode :: ierr
 
  241     petscscalar, 
pointer :: xx(:)
 
  242     petscint :: zs, ys, xs, zm, ym, xm
 
  244     call kspgetdm(ksp, dm, ierr)
 
  245     call dmdagetcorners(dm, zs, ys, xs, zm, ym, xm, ierr)
 
  246     call vecgetarrayf90(x, xx, ierr)
 
  248     call vecrestorearrayf90(x, xx, ierr)
 
  257     petscerrorcode :: ierr
 
  263     petscscalar, 
pointer :: xx(:)
 
  264     petscint :: zs, ys, xs, zm, ym, xm
 
  266     call kspgetdm(ksp, dm, ierr)
 
  267     call dmdagetcorners(dm, zs, ys, xs, zm, ym, xm, ierr)
 
  268     call vecgetarrayf90(b, xx, ierr)
 
  270     call vecrestorearrayf90(b, xx, ierr)
 
  284     integer, 
intent(in) :: zs, ys, xs, zm, ym, xm
 
  285     petscscalar, 
intent(inout) :: x(zs:zs+zm-1, ys:ys+ym-1, xs:xs+xm-1)
 
  286     real(kind=default_precision), 
dimension(:,:,:), 
intent(in) :: src_values
 
  293           x(k, j, i)=src_values((k-zs)+1, (j-ys)+1, (i-xs)+1)
 
  310      integer, 
intent(in) :: z_start_idx, z_end_idx, y_start_idx, y_end_idx, x_start_idx, x_end_idx
 
  311      petscscalar :: x((z_end_idx-z_start_idx)+1, (y_end_idx-y_start_idx)+1, (x_end_idx-x_start_idx)+1)
 
  312      real(kind=default_precision), 
dimension(:,:,:), 
intent(inout) :: target_values
 
  314      target_values(z_start_idx:z_end_idx, y_start_idx:y_end_idx, x_start_idx:x_end_idx)=x
 
  324     petscerrorcode :: ierr
 
  330     petscint :: zs, ys,xs, zm, ym, xm, mz, my, mx
 
  331     real(kind=default_precision) ::  v(7), hx, hy
 
  332     real(kind=default_precision), 
dimension(:), 
allocatable ::  hzu, hzd, d_sc  
 
  333     matstencil :: row(4),col(4,7)
 
  334     integer :: i, j, k, num
 
  336     call kspgetdm(ksp, dm, ierr)
 
  337     call dmdagetinfo(dm,petsc_null_integer, mz, my, mx, petsc_null_integer, petsc_null_integer, petsc_null_integer, &
 
  338      petsc_null_integer, petsc_null_integer, petsc_null_integer, petsc_null_integer, petsc_null_integer, petsc_null_integer, ierr)
 
  339     call dmdagetcorners(dm, zs, ys, xs, zm, ym, xm, ierr)
 
  341     allocate(hzu(0:mz-1), hzd(0:mz-1), d_sc(0:mz-1))
 
  348         hzd(k)=0.0_default_precision
 
  350       if (k .lt. mz-1) 
then 
  353         hzu(k)=0.0_default_precision
 
  362           row(matstencil_i) = k
 
  363           row(matstencil_j) = j
 
  364           row(matstencil_k) = i
 
  367           col(matstencil_i, 1)=k
 
  368           col(matstencil_j, 1)=j-1
 
  369           col(matstencil_k, 1)=i
 
  371           col(matstencil_i, 2)=k
 
  372           col(matstencil_j, 2)=j
 
  373           col(matstencil_k, 2)=i-1
 
  374           v(3)=d_sc(k) * (-(hzu(k) + hzd(k))) - (2.0*(hx + hy))
 
  375           col(matstencil_i, 3)=k
 
  376           col(matstencil_j, 3)=j
 
  377           col(matstencil_k, 3)=i
 
  379           col(matstencil_i, 4)=k
 
  380           col(matstencil_j, 4)=j 
 
  381           col(matstencil_k, 4)=i+1
 
  383           col(matstencil_i, 5)=k
 
  384           col(matstencil_j, 5)=j+1
 
  385           col(matstencil_k, 5)=i
 
  388             v(num)=(d_sc(k)*hzd(k))
 
  389             col(matstencil_i, num)=k-1
 
  390             col(matstencil_j, num)=j 
 
  391             col(matstencil_k, num)=i
 
  394           if (k .lt. mz-1) 
then 
  395             v(num)=(d_sc(k)*hzu(k))
 
  396             col(matstencil_i, num)=k+1
 
  397             col(matstencil_j, num)=j
 
  398             col(matstencil_k, num)=i
 
  401           call matsetvaluesstencil(b, 1, row, num-1, col, v, insert_values, ierr)
 
  405     call matassemblybegin(b, mat_final_assembly, ierr)
 
  406     call matassemblyend(b, mat_final_assembly, ierr)
 
  408       call matassemblybegin(a, mat_final_assembly, ierr)
 
  409       call matassemblyend(a, mat_final_assembly, ierr)
 
  411     deallocate(hzu, hzd, d_sc)
 
  419     integer, 
intent(in) :: dim_size, dim_processes
 
  420     integer, 
intent(out) :: length_array(:)
 
  422     integer :: i, dimension_division, dimension_extra
 
  424     dimension_division = dim_size / dim_processes
 
  425     length_array= dimension_division    
 
  427     dimension_extra = dim_size - (dimension_division * dim_processes)
 
  428     if (dimension_extra .gt. 0) 
then 
  429       do i=1, dimension_extra
 
  430         length_array(i)=length_array(i)+1
 
  441     type(model_state_type), 
target, 
intent(inout) :: current_state
 
  442     integer, 
intent(in) :: y_halo_size, x_halo_size
 
  444     integer :: ierr, combined_handles(2), i, j, k
 
  446     combined_handles(1)=current_state%psrce_x_hs_recv_request
 
  447     combined_handles(2)=current_state%psrce_y_hs_recv_request
 
  448     call mpi_waitall(2, combined_handles, mpi_statuses_ignore, ierr)
 
  450     do j=current_state%local_grid%local_domain_start_index(y_index), current_state%local_grid%local_domain_end_index(y_index)
 
  451       do k=2,current_state%local_grid%size(z_index)
 
  453         current_state%p%data(k,j,x_halo_size+1)=current_state%p%data(k,j,x_halo_size+1)-&
 
  454                current_state%psrce_recv_buffer_x(k-1,j-x_halo_size)
 
  457         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)-&
 
  458              current_state%global_grid%configuration%horizontal%cy * current_state%sv%data(k, j-1, x_halo_size+1)
 
  464     do i=current_state%local_grid%local_domain_start_index(x_index), current_state%local_grid%local_domain_end_index(x_index)
 
  465       do k=2,current_state%local_grid%size(z_index)
 
  466         current_state%p%data(k,y_halo_size+1,i)=current_state%p%data(k,y_halo_size+1,i)-&
 
  467              current_state%psrce_recv_buffer_y(k-1,i-y_halo_size)
 
  472     combined_handles(1)=current_state%psrce_x_hs_send_request
 
  473     combined_handles(2)=current_state%psrce_y_hs_send_request
 
  474     call mpi_waitall(2, combined_handles, mpi_statuses_ignore, ierr)
 
  486        pid_location, current_page, source_data)
 
  487     type(model_state_type), 
intent(inout) :: current_state
 
  488     integer, 
intent(in) :: dim, pid_location, source_index
 
  489     integer, 
intent(inout) :: current_page(:)
 
  490     type(neighbour_description_type), 
intent(inout) :: neighbour_description
 
  491     type(field_data_wrapper_type), 
dimension(:), 
intent(in), 
optional :: source_data
 
  493     call copy_field_to_buffer(current_state%local_grid, neighbour_description%send_halo_buffer, current_state%p%data, &
 
  494          dim, source_index, current_page(pid_location))
 
  496     current_page(pid_location)=current_page(pid_location)+1
 
  505        neighbour_location, current_page, source_data)
 
  506     type(model_state_type), 
intent(inout) :: current_state
 
  507     integer, 
intent(in) :: dim, target_index, neighbour_location
 
  508     integer, 
intent(inout) :: current_page(:)
 
  509     type(neighbour_description_type), 
intent(inout) :: neighbour_description
 
  510     type(field_data_wrapper_type), 
dimension(:), 
intent(in), 
optional :: source_data
 
  512     call copy_buffer_to_field(current_state%local_grid, neighbour_description%recv_halo_buffer, current_state%p%data, &
 
  513          dim, target_index, current_page(neighbour_location))
 
  515     current_page(neighbour_location)=current_page(neighbour_location)+1
 
  522     type(model_state_type), 
intent(inout) :: current_state
 
  523     integer, 
intent(in) :: halo_depth
 
  524     logical, 
intent(in) :: involve_corners
 
  525     type(field_data_wrapper_type), 
dimension(:), 
intent(in), 
optional :: source_data
 
  527     call perform_local_data_copy_for_field(current_state%p%data, current_state%local_grid, &
 
  528          current_state%parallel%my_rank, halo_depth, involve_corners)