2 #include "petsc/finclude/petscvecdef.h" 3 #include "petsc/finclude/petscmatdef.h" 4 #include "petsc/finclude/petsckspdef.h" 5 #include "petsc/finclude/petscdmdadef.h" 33 real(kind=DEFAULT_PRECISION),
dimension(:,:,:),
allocatable ::
p_source,
prev_p 34 real(kind=DEFAULT_PRECISION) ::
cx,
cy 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)
309 subroutine copy_petsc_pointer_to_data(x, z_start_idx, z_end_idx, y_start_idx, y_end_idx, x_start_idx, x_end_idx, target_values)
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)
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...
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...
character(len=string_length) function determine_convegence_reason(r_code)
real(kind=default_precision), dimension(:), allocatable rdz
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.
type(halo_communication_type), save halo_swap_state
subroutine perform_local_data_copy_for_p(current_state, halo_depth, involve_corners, source_data)
Does local data copying for P variable halo swap.
real(kind=default_precision), dimension(:), allocatable rho
integer, parameter, public log_error
Only log ERROR messages.
subroutine copy_petsc_pointer_to_data(x, z_start_idx, z_end_idx, y_start_idx, y_end_idx, x_start_idx, x_end_idx, target_values)
Copies the data in a pointer that was provided by PETSc into some target data, doing it this way mean...
real(kind=default_precision), dimension(:), allocatable rhon
Contains the types used for communication, holding the state of communications and supporting activit...
character(len=string_length) function, public options_get_string(options_database, key, index)
Retrieves a string value from the database that matches the provided key.
PETSc solver component to call out to PETSc for solving the Poisson equation for pressure.
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...
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.
real(kind=default_precision), dimension(:), allocatable dz
real(kind=default_precision), dimension(:,:,:), allocatable p_source
Contains common definitions for the data and datatypes used by MONC.
The ModelState which represents the current state of a run.
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.
subroutine copy_halo_buffer_to_p(current_state, neighbour_description, dim, target_index, neighbour_location, current_page, source_data)
Conversion between common inbuilt FORTRAN data types.
real(kind=default_precision), dimension(:), allocatable dzn
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...
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...
subroutine copy_data_to_petsc_pointer(x, zs, ys, xs, zm, ym, xm, src_values)
Copies data into a data pointer which is provided by PETSc, doing it this ways allows us to give a sh...
Maintains the state of a halo swap and contains buffers, neighbours etc.
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...
subroutine compute_matrix(ksp, A, B, dummy, ierr)
Call back issued from within PETSc to create the matrix, this is only called once (the first PETSc ru...
Interfaces and types that MONC components must specify.
Defined the local grid, i.e. the grid held on this process after decomposition.
real(kind=default_precision), dimension(:,:,:), allocatable prev_p
subroutine init_callback(current_state)
Called upon model initialisation. Will basically read from the options database and set options in th...
real(kind=default_precision) cy
Provides the mechanism for halo swapping. This module contains the functionality required to determin...
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...
Describes the neighbours of a process in a specific dimension and contains the communication buffers ...
integer, parameter, public string_length
Default length of strings.
subroutine compute_rhs(ksp, b, dummy, ierr)
Callback issued from the PETSc library to compute the RHS, this is called every timestep (as we have ...
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 timestep_callback(current_state)
Timestep hook which is called at each timestep to solve the pressure equation via PETSc...
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.
Functionality to support the different types of grid and abstraction between global grids and local o...
subroutine apply_dimension_bounds(dim_size, dim_processes, length_array)
Applies dimension bounds to determine the number of elements held locally for each process in that di...
type(component_descriptor_type) function, public petsc_solver_get_descriptor()
Provides the descriptor back to the caller and is used in component registration. ...
logical function, public log_is_master()
Determines whether the process is the master logging process. This might be preferable rather than ca...
integer function, public options_get_integer(options_database, key, index)
Retrieves an integer value from the database that matches the provided key.
subroutine finalisation_callback(current_state)
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...
integer, parameter, public log_info
Log INFO, WARNING and ERROR messages.
real(kind=default_precision), dimension(:), allocatable rdzn
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
subroutine ksp_monitor(ksp, n, rnorm, dummy, ierr)
Monitor procedure called on each iteration, this is provided only at debugging level.
integer, parameter, public x_index
subroutine compute_initial_guess(ksp, x, dummy, ierr)
Determines the initial guess, this is called from within PETSc and sets it to be the last value of P ...
real(kind=default_precision) cx