MONC
diffusion.F90
Go to the documentation of this file.
1 
8  use grids_mod, only : z_index, x_index, y_index
14  implicit none
15 
16 #ifndef TEST_MODE
17  private
18 #endif
19 
20  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: th_diffusion
21  real(kind=DEFAULT_PRECISION), dimension(:,:), allocatable :: q_diffusion
22 
24 
25 contains
26 
30  diffusion_get_descriptor%name="diffusion"
31  diffusion_get_descriptor%version=0.1
35 
38  allocate(diffusion_get_descriptor%published_fields(2))
39  diffusion_get_descriptor%published_fields(1)="th_diffusion"
40  diffusion_get_descriptor%published_fields(2)="q_diffusion"
41  end function diffusion_get_descriptor
42 
47  subroutine field_information_retrieval_callback(current_state, name, field_information)
48  type(model_state_type), target, intent(inout) :: current_state
49  character(len=*), intent(in) :: name
50  type(component_field_information_type), intent(out) :: field_information
51 
52  ! Field description is the same regardless of the specific field being retrieved
53  field_information%field_type=component_array_field_type
54  field_information%data_type=component_double_data_type
55  if (name .eq. "q_diffusion") then
56  field_information%number_dimensions=2
57  else
58  field_information%number_dimensions=1
59  end if
60  field_information%dimension_sizes(1)=current_state%local_grid%size(z_index)
61  if (name .eq. "q_diffusion") field_information%dimension_sizes(2)=current_state%number_q_fields
62  field_information%enabled=.true.
64 
69  subroutine field_value_retrieval_callback(current_state, name, field_value)
70  type(model_state_type), target, intent(inout) :: current_state
71  character(len=*), intent(in) :: name
72  type(component_field_value_type), intent(out) :: field_value
73 
74  if (name .eq. "th_diffusion") then
75  allocate(field_value%real_1d_array(size(th_diffusion)), source=th_diffusion)
76  else if (name .eq. "q_diffusion") then
77  allocate(field_value%real_2d_array(size(q_diffusion, 1), size(q_diffusion, 2)), source=q_diffusion)
78  end if
79  end subroutine field_value_retrieval_callback
80 
83  subroutine initialisation_callback(current_state)
84  type(model_state_type), target, intent(inout) :: current_state
85 
86  integer :: z_size, y_size, x_size
87 
88  z_size=current_state%local_grid%size(z_index) + current_state%local_grid%halo_size(z_index) * 2
89  y_size=current_state%local_grid%size(y_index) + current_state%local_grid%halo_size(y_index) * 2
90  x_size=current_state%local_grid%size(x_index) + current_state%local_grid%halo_size(x_index) * 2
91  allocate(current_state%diff_coefficient%data(z_size, y_size, x_size))
92 
93  z_size=current_state%global_grid%size(z_index)
94  allocate(th_diffusion(z_size))
95  allocate(q_diffusion(z_size, current_state%number_q_fields))
96 
97  end subroutine initialisation_callback
98 
99  subroutine finalisation_callback(current_state)
100  type(model_state_type), target, intent(inout) :: current_state
101 
102  if (allocated(th_diffusion)) deallocate(th_diffusion)
103  if (allocated(q_diffusion)) deallocate(q_diffusion)
104  end subroutine finalisation_callback
105 
108  subroutine timestep_callback(current_state)
109  type(model_state_type), target, intent(inout) :: current_state
110 
111  integer :: local_y, local_x
112 
113  if (.not. current_state%use_viscosity_and_diffusion .or. current_state%halo_column) return
114  if (current_state%diffusion_halo_swap_state%swap_in_progress) then
115  ! If there is a diffusion halo swap in progress then complete it
116  call complete_nonblocking_halo_swap(current_state, current_state%diffusion_halo_swap_state, &
118  end if
119 
120  local_y=current_state%column_local_y
121  local_x=current_state%column_local_x
122 
123  if (current_state%th%active) call perform_th_diffusion(current_state, local_y, local_x)
124  if (current_state%number_q_fields .gt. 0) call perform_q_diffusion(current_state, local_y, local_x)
125  end subroutine timestep_callback
126 
131  subroutine perform_q_diffusion(current_state, local_y, local_x)
132  type(model_state_type), target, intent(inout) :: current_state
133  integer, intent(in) :: local_y, local_x
134 
135  integer :: n
136 
137  do n=1, current_state%number_q_fields
138  call general_diffusion(current_state, current_state%zq(n), current_state%sq(n), local_y, local_x, q_diffusion(:,n))
139  end do
140  end subroutine perform_q_diffusion
141 
146  subroutine perform_th_diffusion(current_state, local_y, local_x)
147  type(model_state_type), target, intent(inout) :: current_state
148  integer, intent(in) :: local_y, local_x
149 
150  integer :: k
151  real(kind=DEFAULT_PRECISION) :: adjustment
152 
153  call general_diffusion(current_state, current_state%zth, current_state%sth, local_y, local_x, th_diffusion)
154 
155  if (current_state%use_anelastic_equations) then
156  ! This code only needs to be executed if anelastic, otherwise THREF is constant and the increment calculated here is zero
157  do k=2, current_state%local_grid%size(z_index)
158  adjustment=(current_state%global_grid%configuration%vertical%cza(k)*&
159  current_state%global_grid%configuration%vertical%dthref(k)*&
160  current_state%diff_coefficient%data(k, local_y, local_x) - current_state%global_grid%configuration%vertical%czb(k)*&
161  current_state%global_grid%configuration%vertical%dthref(k-1)*&
162  current_state%diff_coefficient%data(k-1, local_y, local_x))
163  current_state%sth%data(k, local_y, local_x)=current_state%sth%data(k, local_y, local_x)+adjustment
164  th_diffusion(k)=th_diffusion(k)+adjustment
165  end do
166  end if
167  end subroutine perform_th_diffusion
168 
175  subroutine general_diffusion(current_state, field, source_field, local_y, local_x, diagnostics)
176  type(model_state_type), target, intent(inout) :: current_state
177  type(prognostic_field_type), intent(inout) :: field, source_field
178  integer, intent(in) :: local_y, local_x
179  real(kind=DEFAULT_PRECISION), dimension(:), intent(inout), optional :: diagnostics
180 
181  real(kind=DEFAULT_PRECISION) :: term
182  integer :: k
183 
184  do k=2, current_state%local_grid%size(z_index)
185  term=current_state%global_grid%configuration%horizontal%cx2*0.25_default_precision*&
186  (((current_state%diff_coefficient%data(k, local_y, local_x)+&
187  current_state%diff_coefficient%data(k, local_y, local_x-1))+&
188  (current_state%diff_coefficient%data(k-1, local_y, local_x)+&
189  current_state%diff_coefficient%data(k-1, local_y, local_x-1)))&
190  *(field%data(k, local_y, local_x-1)-field%data(k, local_y, local_x)) -&
191  ((current_state%diff_coefficient%data(k, local_y, local_x+1)+&
192  current_state%diff_coefficient%data(k, local_y, local_x))+&
193  (current_state%diff_coefficient%data(k-1, local_y, local_x+1)+&
194  current_state%diff_coefficient%data(k-1, local_y, local_x)))&
195  *(field%data(k, local_y, local_x)-field%data(k, local_y, local_x+1)) )&
196  +current_state%global_grid%configuration%horizontal%cy2*0.25_default_precision*(&
197  ((current_state%diff_coefficient%data(k, local_y, local_x)+&
198  current_state%diff_coefficient%data(k, local_y-1, local_x))+&
199  (current_state%diff_coefficient%data(k-1, local_y, local_x)+&
200  current_state%diff_coefficient%data(k-1, local_y-1, local_x)))&
201  *(field%data(k, local_y-1, local_x)-field%data(k, local_y, local_x)) -&
202  ((current_state%diff_coefficient%data(k, local_y+1, local_x)+&
203  current_state%diff_coefficient%data(k, local_y, local_x))+&
204  (current_state%diff_coefficient%data(k-1, local_y+1, local_x)+&
205  current_state%diff_coefficient%data(k-1, local_y, local_x)))&
206  *(field%data(k, local_y, local_x)-field%data(k, local_y+1, local_x)) )&
207  +( current_state%global_grid%configuration%vertical%czb(k)*&
208  current_state%diff_coefficient%data(k-1, local_y, local_x)*&
209  (field%data(k-1, local_y, local_x)-field%data(k, local_y, local_x)))
210 
211  if (k .lt. current_state%local_grid%size(z_index)) then
212  term=term - current_state%global_grid%configuration%vertical%cza(k)*&
213  current_state%diff_coefficient%data(k, local_y, local_x)*&
214  (field%data(k, local_y, local_x)-field%data(k+1, local_y, local_x))
215  end if
216  source_field%data(k, local_y, local_x)=source_field%data(k, local_y, local_x)+term
217  if (present(diagnostics)) diagnostics(k)=term
218  end do
219  end subroutine general_diffusion
220 
224  subroutine perform_local_data_copy_for_diff(current_state, halo_depth, involve_corners, source_data)
225  type(model_state_type), intent(inout) :: current_state
226  integer, intent(in) :: halo_depth
227  logical, intent(in) :: involve_corners
228  type(field_data_wrapper_type), dimension(:), intent(in), optional :: source_data
229 
230  call perform_local_data_copy_for_field(current_state%diff_coefficient%data, current_state%local_grid, &
231  current_state%parallel%my_rank, halo_depth, involve_corners)
232  end subroutine perform_local_data_copy_for_diff
233 
242  subroutine copy_halo_buffer_to_diff(current_state, neighbour_description, dim, target_index, &
243  neighbour_location, current_page, source_data)
244  type(model_state_type), intent(inout) :: current_state
245  integer, intent(in) :: dim, target_index, neighbour_location
246  integer, intent(inout) :: current_page(:)
247  type(neighbour_description_type), intent(inout) :: neighbour_description
248  type(field_data_wrapper_type), dimension(:), intent(in), optional :: source_data
249 
250  call copy_buffer_to_field(current_state%local_grid, neighbour_description%recv_halo_buffer, &
251  current_state%diff_coefficient%data, dim, target_index, current_page(neighbour_location))
252 
253  current_page(neighbour_location)=current_page(neighbour_location)+1
254  end subroutine copy_halo_buffer_to_diff
255 
265  subroutine copy_halo_buffer_to_diff_corners(current_state, neighbour_description, corner_loc, x_target_index, &
266  y_target_index, neighbour_location, current_page, source_data)
267  type(model_state_type), intent(inout) :: current_state
268  integer, intent(in) :: corner_loc, x_target_index, y_target_index, neighbour_location
269  integer, intent(inout) :: current_page(:)
270  type(neighbour_description_type), intent(inout) :: neighbour_description
271  type(field_data_wrapper_type), dimension(:), intent(in), optional :: source_data
272 
273  call copy_buffer_to_corner(current_state%local_grid, neighbour_description%recv_corner_buffer, &
274  current_state%diff_coefficient%data, corner_loc, x_target_index, y_target_index, current_page(neighbour_location))
275 
276  current_page(neighbour_location)=current_page(neighbour_location)+1
277  end subroutine copy_halo_buffer_to_diff_corners
278 end module diffusion_mod
subroutine copy_halo_buffer_to_diff(current_state, neighbour_description, dim, target_index, neighbour_location, current_page, source_data)
Copies the halo buffer to halo location for the diffusion coefficient field.
Definition: diffusion.F90:244
real(kind=default_precision), dimension(:,:), allocatable q_diffusion
Definition: diffusion.F90:21
Wrapper type for the value returned for a published field from a component.
integer, parameter, public forward_stepping
Definition: state.F90:15
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.
subroutine timestep_callback(current_state)
At each timestep will compute the diffusion source terms for TH and Q fields per column if these fiel...
Definition: diffusion.F90:109
subroutine perform_th_diffusion(current_state, local_y, local_x)
Computes the diffusion source terms for the theta field.
Definition: diffusion.F90:147
integer, parameter, public log_error
Only log ERROR messages.
Definition: logging.F90:11
Contains the types used for communication, holding the state of communications and supporting activit...
subroutine copy_halo_buffer_to_diff_corners(current_state, neighbour_description, corner_loc, x_target_index, y_target_index, neighbour_location, current_page, source_data)
Copies the corner halo buffer to the diffusion coefficient field corners.
Definition: diffusion.F90:267
Contains prognostic field definitions and functions.
Definition: prognostics.F90:2
A prognostic field which is assumed to be 3D.
Definition: prognostics.F90:13
Logging utility.
Definition: logging.F90:2
integer, parameter, public default_precision
MPI communication type which we use for the prognostic and calculation data.
Definition: datadefn.F90:17
integer, parameter, public z_index
Grid index parameters.
Definition: grids.F90:14
subroutine, public complete_nonblocking_halo_swap(current_state, halo_swap_state, perform_local_data_copy, copy_from_halo_buffer, copy_from_halo_buffer_to_corner, source_data)
This completes a nonblocking halo swap and it is only during this call that the data fields themselve...
Contains common definitions for the data and datatypes used by MONC.
Definition: datadefn.F90:2
The ModelState which represents the current state of a run.
Definition: state.F90:39
subroutine perform_local_data_copy_for_diff(current_state, halo_depth, involve_corners, source_data)
Does local data copying for diffusion coefficient variable halo swap.
Definition: diffusion.F90:225
logical function, public is_component_enabled(options_database, component_name)
Determines whether or not a specific component is registered and enabled.
Definition: registry.F90:334
subroutine, public log_master_log(level, message)
Will log just from the master process.
Definition: logging.F90:47
subroutine general_diffusion(current_state, field, source_field, local_y, local_x, diagnostics)
General diffusion computation for any field which is provided as arguments. Works in a column...
Definition: diffusion.F90:176
subroutine, public copy_buffer_to_corner(local_grid, halo_buffer, field_data, corner_loc, x_target_index, y_target_index, halo_page)
Copies the received buffer for a specific field to the corresponding corner of that field...
subroutine initialisation_callback(current_state)
Sets up the stencil_mod (used in interpolation) and allocates data for the flux fields.
Definition: diffusion.F90:84
subroutine perform_q_diffusion(current_state, local_y, local_x)
Computes the diffusion source terms for each Q field.
Definition: diffusion.F90:132
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 field_value_retrieval_callback(current_state, name, field_value)
Field value retrieval callback, this returns the value of a specific published field.
Definition: diffusion.F90:70
integer, parameter, public component_array_field_type
Maintains the state of a halo swap and contains buffers, neighbours etc.
Diffusion on the TH and Q fields.
Definition: diffusion.F90:2
Interfaces and types that MONC components must specify.
subroutine finalisation_callback(current_state)
Definition: diffusion.F90:100
Provides the mechanism for halo swapping. This module contains the functionality required to determin...
integer, parameter, public log_warn
Log WARNING and ERROR messages.
Definition: logging.F90:12
Describes the neighbours of a process in a specific dimension and contains the communication buffers ...
subroutine field_information_retrieval_callback(current_state, name, field_information)
Field information retrieval callback, this returns information for a specific components published fi...
Definition: diffusion.F90:48
real(kind=default_precision), dimension(:), allocatable th_diffusion
Definition: diffusion.F90:20
Functionality to support the different types of grid and abstraction between global grids and local o...
Definition: grids.F90:5
type(component_descriptor_type) function, public diffusion_get_descriptor()
Provides the descriptor back to the caller and is used in component registration. ...
Definition: diffusion.F90:30
The model state which represents the current state of a run.
Definition: state.F90:2
integer, parameter, public y_index
Definition: grids.F90:14
integer, parameter, public x_index
Definition: grids.F90:14
MONC component registry.
Definition: registry.F90:5
integer, parameter, public component_double_data_type