14 use mpi
, only : mpi_request_null, mpi_statuses_ignore
21 real(kind=DEFAULT_PRECISION),
dimension(:),
allocatable ::
cos_x,
cos_y 22 real(kind=DEFAULT_PRECISION) ::
pi 23 real(kind=DEFAULT_PRECISION),
dimension(:,:,:),
allocatable ::
pt 43 type(model_state_type),
target,
intent(inout) :: current_state
45 integer :: i, my_y_start, my_x_start
47 if (.not. is_component_enabled(current_state%options_database,
"diverr"))
then 48 call log_master_log(log_error,
"The FFT solver component requires the diverr component to be enabled")
51 pi=4.0_default_precision*atan(1.0_default_precision)
55 call init_halo_communication(current_state, get_single_field_per_halo_cell,
halo_swap_state, 1, .false.)
62 cos_x(i)=(2.0_default_precision/(current_state%global_grid%configuration%horizontal%dx*&
63 current_state%global_grid%configuration%horizontal%dx))&
64 *(cos(2.0_default_precision*
pi*
real(((i-1)+(my_x_start-1))/2, kind=default_precision)/&
65 real(current_state%global_grid%size(X_INDEX), kind=default_precision))-1.0_default_precision)
72 cos_y(i)=(2.0_default_precision/(current_state%global_grid%configuration%horizontal%dy*&
73 current_state%global_grid%configuration%horizontal%dy))&
74 *(cos(2.0_default_precision*
pi*
real(((i-1)+(my_y_start-1))/2, kind=default_precision)/&
75 real(current_state%global_grid%size(Y_INDEX), kind=default_precision))-1.0_default_precision)
78 current_state%psrce_x_hs_send_request=mpi_request_null
79 current_state%psrce_y_hs_send_request=mpi_request_null
80 current_state%psrce_x_hs_recv_request=mpi_request_null
81 current_state%psrce_y_hs_recv_request=mpi_request_null
87 type(model_state_type),
target,
intent(inout) :: current_state
89 integer :: start_loc(3), end_loc(3), i
92 start_loc(i)=current_state%local_grid%local_domain_start_index(i)
93 end_loc(i)=current_state%local_grid%local_domain_end_index(i)
97 current_state%local_grid%halo_size(x_index))
100 current_state%p%data=
real(current_state%parallel%my_rank, kind=8) + 1.d0
103 call perform_forward_3dfft(current_state, current_state%p%data(start_loc(z_index):end_loc(z_index), &
104 start_loc(y_index):end_loc(y_index), start_loc(x_index):end_loc(x_index)),
pt)
106 #ifndef FFT_TEST_MODE 114 call perform_backwards_3dfft(current_state,
pt, current_state%p%data(start_loc(z_index):end_loc(z_index), &
115 start_loc(y_index):end_loc(y_index), start_loc(x_index):end_loc(x_index)))
118 if (current_state%parallel%my_rank == 1)
then 119 write(*,*) current_state%parallel%my_rank, current_state%p%data(:,3,3)
131 type(model_state_type),
target,
intent(inout) :: current_state
133 call finalise_pencil_fft(current_state%parallel%monc_communicator)
145 type(model_state_type),
target,
intent(inout) :: current_state
146 integer,
intent(in) :: y_halo_size, x_halo_size
148 integer :: ierr, combined_handles(2), i, j, k
150 combined_handles(1)=current_state%psrce_x_hs_recv_request
151 combined_handles(2)=current_state%psrce_y_hs_recv_request
152 call mpi_waitall(2, combined_handles, mpi_statuses_ignore, ierr)
154 do j=current_state%local_grid%local_domain_start_index(y_index), current_state%local_grid%local_domain_end_index(y_index)
155 do k=2,current_state%local_grid%size(z_index)
157 current_state%p%data(k,j,x_halo_size+1)=current_state%p%data(k,j,x_halo_size+1)-&
158 current_state%psrce_recv_buffer_x(k-1,j-x_halo_size)
161 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)-&
162 current_state%global_grid%configuration%horizontal%cy * current_state%sv%data(k, j-1, x_halo_size+1)
168 do i=current_state%local_grid%local_domain_start_index(x_index), current_state%local_grid%local_domain_end_index(x_index)
169 do k=2,current_state%local_grid%size(z_index)
170 current_state%p%data(k,y_halo_size+1,i)=current_state%p%data(k,y_halo_size+1,i)-&
171 current_state%psrce_recv_buffer_y(k-1,i-y_halo_size)
176 combined_handles(1)=current_state%psrce_x_hs_send_request
177 combined_handles(2)=current_state%psrce_y_hs_send_request
178 call mpi_waitall(2, combined_handles, mpi_statuses_ignore, ierr)
189 type(model_state_type),
target,
intent(inout) :: current_state
190 real(kind=DEFAULT_PRECISION),
dimension(:,:,:),
intent(inout) :: pressure_term
191 integer,
intent(in) :: fourier_space_sizes(3)
193 integer :: i, j, k, j_start
194 real(kind=DEFAULT_PRECISION) :: b(fourier_space_sizes(z_index)), b1(fourier_space_sizes(z_index)), &
195 s(fourier_space_sizes(z_index)), s1(fourier_space_sizes(z_index)), cij
197 do i=1,fourier_space_sizes(x_index)
198 j_start=merge(3, 1, current_state%local_grid%start(y_index) ==1 .and. current_state%local_grid%start(x_index) == 1 &
200 do j=j_start,fourier_space_sizes(y_index)
203 b(2)=cij-current_state%global_grid%configuration%vertical%cza(2)
204 b1(2)=1.0_default_precision/b(2)
205 s1(2)=pressure_term(2,j,i)
207 do k=3,fourier_space_sizes(z_index)
208 b(k)=cij+current_state%global_grid%configuration%vertical%czg(k)
209 b1(k)=1.0_default_precision/(b(k)-current_state%global_grid%configuration%vertical%czh(k)*b1(k-1))
210 s1(k)=pressure_term(k,j,i)-current_state%global_grid%configuration%vertical%czb(k)*s1(k-1)*b1(k-1)
213 pressure_term(fourier_space_sizes(z_index),j,i)=s1(fourier_space_sizes(z_index))* b1(fourier_space_sizes(z_index))
215 do k=fourier_space_sizes(z_index)-1,2,-1
216 pressure_term(k,j,i)=(s1(k)-current_state%global_grid%configuration%vertical%cza(k)*&
217 pressure_term(k+1,j,i))*b1(k)
223 if (current_state%local_grid%start(y_index) == 1 .and. current_state%local_grid%start(x_index) == 1)
then 226 s(2)=pressure_term(2,j,i)
227 pressure_term(1,j,i)=0.0_default_precision
228 pressure_term(2,j,i)=0.0_default_precision
229 do k=3, fourier_space_sizes(z_index)
230 s(k)=pressure_term(k,j,i)
231 pressure_term(k,j,i)=(s(k-1)-current_state%global_grid%configuration%vertical%czg(k-1)*pressure_term(k-1,j,i)-&
232 current_state%global_grid%configuration%vertical%czb(k-1)*pressure_term(k-2,j,i))/&
233 current_state%global_grid%configuration%vertical%cza(k-1)
249 pid_location, current_page, source_data)
250 type(model_state_type),
intent(inout) :: current_state
251 integer,
intent(in) :: dim, pid_location, source_index
252 integer,
intent(inout) :: current_page(:)
253 type(neighbour_description_type),
intent(inout) :: neighbour_description
254 type(field_data_wrapper_type),
dimension(:),
intent(in),
optional :: source_data
256 call copy_field_to_buffer(current_state%local_grid, neighbour_description%send_halo_buffer, current_state%p%data, &
257 dim, source_index, current_page(pid_location))
259 current_page(pid_location)=current_page(pid_location)+1
268 neighbour_location, current_page, source_data)
269 type(model_state_type),
intent(inout) :: current_state
270 integer,
intent(in) :: dim, target_index, neighbour_location
271 integer,
intent(inout) :: current_page(:)
272 type(neighbour_description_type),
intent(inout) :: neighbour_description
273 type(field_data_wrapper_type),
dimension(:),
intent(in),
optional :: source_data
275 call copy_buffer_to_field(current_state%local_grid, neighbour_description%recv_halo_buffer, current_state%p%data, &
276 dim, target_index, current_page(neighbour_location))
278 current_page(neighbour_location)=current_page(neighbour_location)+1
285 type(model_state_type),
intent(inout) :: current_state
286 integer,
intent(in) :: halo_depth
287 logical,
intent(in) :: involve_corners
288 type(field_data_wrapper_type),
dimension(:),
intent(in),
optional :: source_data
290 call perform_local_data_copy_for_field(current_state%p%data, current_state%local_grid, &
291 current_state%parallel%my_rank, halo_depth, involve_corners)
subroutine tridiagonal_solver(current_state, pressure_term, fourier_space_sizes)
The tridiagonal solver which runs in Fourier space on the pressure terms. Note that because we are go...
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...
subroutine perform_local_data_copy_for_p(current_state, halo_depth, involve_corners, source_data)
Does local data copying for P variable halo swap.
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.
integer, parameter, public log_error
Only log ERROR messages.
Contains the types used for communication, holding the state of communications and supporting activit...
subroutine, public finalise_pencil_fft(monc_communicator)
Cleans up allocated buffer memory.
Pressure solver which uses a tridiagonal algorithm operating on the pressure terms in Fourier space...
type(halo_communication_type), save halo_swap_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 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...
subroutine initialisation_callback(current_state)
This initialisation callback sets up the pencil fft module, allocates data for the fourier space pres...
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.
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 perform_forward_3dfft(current_state, source_data, target_data)
Performs a forward 3D FFT and currently results in target data which is the X, Z, Y oriented pencil N...
real(kind=default_precision) pi
integer function, dimension(3), public initialise_pencil_fft(current_state, my_y_start, my_x_start)
Initialises the pencil FFT functionality, this will create the transposition structures needed...
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...
Interfaces and types that MONC components must specify.
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...
Provides the mechanism for halo swapping. This module contains the functionality required to determin...
subroutine, public perform_backwards_3dfft(current_state, source_data, target_data)
Performs a backwards 3D FFT and currently results in target data which is the X, Z, Y oriented pencil Note that the source_data here takes no account for the halo, it is up to caller to exclude this. This does no FFT in Z, but transposes to Y, does FFT in Y, then transposes to X and performs an FFT in that dimension. Pencil decomposition is used which has already been set up.
Describes the neighbours of a process in a specific dimension and contains the communication buffers ...
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.
integer, dimension(3) fourier_space_sizes
This Pencil FFT performs 3D forward and backwards FFTs using pencil decomposition. It uses FFTW for the actual FFT kernel and this module contains all the data decomposition around this. There is no FFT required in Z, so this performs FFTs in Y and X (in that order forward and reversed backwards.) The data decomposition is the complex aspect, there is the concept of forward and backwards transformations. Forward transformations will go from pencil Z to Y to X and the backwards transformations undo these, so go from X to Y to Z. Note that we use quite a lot of buffer space here, this could be cut down if Y=X dimensions so some optimisation on memory could be done there in that case.
Functionality to support the different types of grid and abstraction between global grids and local o...
subroutine timestep_callback(current_state)
Timestep call back, which will transform to Fourier space, do a tridiagonal solve and then back into ...
subroutine, public finalise_halo_communication(halo_swap_state)
Finalises the halo swap represented by the state by freeing up all the allocated memory.
real(kind=default_precision), dimension(:,:,:), allocatable pt
type(component_descriptor_type) function, public fftsolver_get_descriptor()
Descriptor of this component for registration.
subroutine copy_halo_buffer_to_p(current_state, neighbour_description, dim, target_index, neighbour_location, current_page, source_data)
The model state which represents the current state of a run.
subroutine finalisation_callback(current_state)
Called at MONC finalisation, will call to the pencil fft module to clean itself up and free the press...
real(kind=default_precision), dimension(:), allocatable cos_x
integer, parameter, public y_index
integer, parameter, public x_index
real(kind=default_precision), dimension(:), allocatable cos_y