17 use mpi,
only : mpi_max, mpi_sum, mpi_comm_world, mpi_request_null, mpi_statuses_ignore
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
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)
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)