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)