MONC
forcing.F90
Go to the documentation of this file.
1 
2 module forcing_mod
5  use grids_mod, only : z_index, y_index, x_index
6  use state_mod, only : model_state_type
16 
17  implicit none
18 
19 #ifndef TEST_MODE
20  private
21 #endif
22 
23  integer, parameter :: divergence=0 ! Input for subsidence forcing is a divergence profile
24  integer, parameter :: subsidence=1 ! Input for subsidence forcing is the subsidence velocity profile
25 
26  integer, parameter :: tendency=0 ! Input for large-scale forcing: values are tendencies (time derivatives)
27  integer, parameter :: relaxation=1 ! Input for large-scale forcing: values are target values to relax to over timescale
28  integer, parameter :: increment=2 ! Input for large-scale forcing: values are increments (deltas) over timescale
29 
30  real(kind=DEFAULT_PRECISION), allocatable :: theta_profile(:) ! Local profile to be used in the subsidence calculation
31  real(kind=DEFAULT_PRECISION), allocatable :: q_profile(:) ! Local profile to be used in the subsidence calculation
32  real(kind=DEFAULT_PRECISION), allocatable :: u_profile(:) ! Local profile to be used in the subsidence calculation
33  real(kind=DEFAULT_PRECISION), allocatable :: v_profile(:) ! Local profile to be used in the subsidence calculation
34 
35  real(kind=DEFAULT_PRECISION), allocatable :: dtheta_profile(:) ! Local profile to be used in time-indpendent forcing
36  real(kind=DEFAULT_PRECISION), allocatable :: dq_profile(:) ! Local profile to be used in the time-indpendent forcing
37  real(kind=DEFAULT_PRECISION), allocatable :: du_profile(:) ! Local profile to be used in the time-indpendent forcing
38  real(kind=DEFAULT_PRECISION), allocatable :: dv_profile(:) ! Local profile to be used in the time-indpendent forcing
39  real(kind=DEFAULT_PRECISION), allocatable :: du_profile_diag(:), dv_profile_diag(:), dtheta_profile_diag(:), &
40  dq_profile_diag(:,:)
41 
42  real(kind=DEFAULT_PRECISION) :: forcing_timescale_theta ! Timescale for forcing of theta
43  real(kind=DEFAULT_PRECISION) :: forcing_timescale_q ! Timescale for forcing of q
44  real(kind=DEFAULT_PRECISION) :: forcing_timescale_u ! Timescale for forcing of u
45  real(kind=DEFAULT_PRECISION) :: forcing_timescale_v ! Timescale for forcing of v
46 
47  logical :: l_constant_forcing_theta ! Use a time-independent forcing for theta
48  logical :: l_constant_forcing_q ! Use a time-independent forcing for q
49  logical :: l_constant_forcing_u ! Use a time-independent forcing for u
50  logical :: l_constant_forcing_v ! Use a time-independent forcing for v
51 
52  integer :: constant_forcing_type_theta=tendency ! Method for large-scale forcing of theta
53  integer :: constant_forcing_type_q=tendency ! Method for large-scale forcing of q
54  integer :: constant_forcing_type_u=relaxation ! Method for large-scale forcing of u
55  integer :: constant_forcing_type_v=relaxation ! Method for large-scale forcing of v
56 
57  logical :: l_constant_forcing_theta_z2pressure ! profile is a function of pressure not height
58 
59  logical :: relax_to_initial_u_profile ! For relaxation, use initial profile as the target
60  logical :: relax_to_initial_v_profile ! For relaxation, use initial profile as the target
61  logical :: relax_to_initial_theta_profile ! For relaxation, use initial profile as the target
62 
63  logical :: l_subs_pl_theta ! if .true. then subsidence applied to theta field
64  logical :: l_subs_pl_q ! if .true. then subsidence applied to q fields
65 
66  logical :: l_subs_local_theta ! if .true. then subsidence applied locally (i.e. not with mean fields) to theta field
67  logical :: l_subs_local_q ! if .true. then subsidence applied locally (i.e. not with mean fields) to q fields
68 
69  character(len=STRING_LENGTH), dimension(:), allocatable :: names_force_pl_q ! names of q variables to force
70 
72 
73 contains
74 
78  forcing_get_descriptor%name="forcing"
79  forcing_get_descriptor%version=0.1
83 
86  allocate(forcing_get_descriptor%published_fields(8))
87 
88  forcing_get_descriptor%published_fields(1)="u_subsidence"
89  forcing_get_descriptor%published_fields(2)="v_subsidence"
90  forcing_get_descriptor%published_fields(3)="th_subsidence"
91  forcing_get_descriptor%published_fields(4)="q_subsidence"
92  forcing_get_descriptor%published_fields(5)="u_large_scale"
93  forcing_get_descriptor%published_fields(6)="v_large_scale"
94  forcing_get_descriptor%published_fields(7)="th_large_scale"
95  forcing_get_descriptor%published_fields(8)="q_large_scale"
96  end function forcing_get_descriptor
97 
102  subroutine field_information_retrieval_callback(current_state, name, field_information)
103  type(model_state_type), target, intent(inout) :: current_state
104  character(len=*), intent(in) :: name
105  type(component_field_information_type), intent(out) :: field_information
106 
107  field_information%field_type=component_array_field_type
108  field_information%data_type=component_double_data_type
109  field_information%number_dimensions=1
110  field_information%dimension_sizes(1)=current_state%local_grid%size(z_index)
111 
112  if (name .eq. "u_subsidence") then
113  field_information%enabled=current_state%u%active .and. l_subs_pl_theta .and. &
114  allocated(current_state%global_grid%configuration%vertical%olzubar)
115  else if (name .eq. "v_subsidence") then
116  field_information%enabled=current_state%v%active .and. l_subs_pl_theta .and. &
117  allocated(current_state%global_grid%configuration%vertical%olzvbar)
118  else if (name .eq. "th_subsidence") then
119  field_information%enabled=current_state%th%active .and. l_subs_pl_theta .and. &
120  allocated(current_state%global_grid%configuration%vertical%olzthbar)
121  else if (name .eq. "q_subsidence") then
122  field_information%number_dimensions=2
123  field_information%dimension_sizes(2)=current_state%number_q_fields
124  field_information%enabled=current_state%number_q_fields .gt. 0 .and. l_subs_pl_q .and. &
125  allocated(current_state%global_grid%configuration%vertical%olzqbar)
126  else if (name .eq. "u_large_scale") then
127  field_information%enabled=current_state%u%active .and. l_constant_forcing_u
128  else if (name .eq. "v_large_scale") then
129  field_information%enabled=current_state%v%active .and. l_constant_forcing_v
130  else if (name .eq. "th_large_scale") then
131  field_information%enabled=current_state%th%active .and. l_constant_forcing_theta
132  else if (name .eq. "q_large_scale") then
133  field_information%number_dimensions=2
134  field_information%dimension_sizes(2)=current_state%number_q_fields
135  field_information%enabled=current_state%number_q_fields .gt. 0 .and. l_constant_forcing_q
136  end if
138 
143  subroutine field_value_retrieval_callback(current_state, name, field_value)
144  type(model_state_type), target, intent(inout) :: current_state
145  character(len=*), intent(in) :: name
146  type(component_field_value_type), intent(out) :: field_value
147 
148  integer :: k, n, column_size
149 
150  column_size=current_state%local_grid%size(z_index)
151 
152  if (name .eq. "u_subsidence") then
153  allocate(field_value%real_1d_array(column_size))
154  do k=2, column_size-1
155  field_value%real_1d_array(k)=0.0_default_precision-2.0*&
156  current_state%global_grid%configuration%vertical%w_subs(k-1)*&
157  current_state%global_grid%configuration%vertical%tzc1(k)*(&
158  current_state%global_grid%configuration%vertical%olzubar(k)-&
159  current_state%global_grid%configuration%vertical%olzubar(k-1))+&
160  current_state%global_grid%configuration%vertical%w_subs(k)*&
161  current_state%global_grid%configuration%vertical%tzc2(k)*&
162  (current_state%global_grid%configuration%vertical%olzubar(k+1)-&
163  current_state%global_grid%configuration%vertical%olzubar(k))
164  end do
165  else if (name .eq. "v_subsidence") then
166  allocate(field_value%real_1d_array(column_size))
167  do k=2, column_size-1
168  field_value%real_1d_array(k)=0.0_default_precision-2.0*&
169  current_state%global_grid%configuration%vertical%w_subs(k-1)*&
170  current_state%global_grid%configuration%vertical%tzc1(k)*(&
171  current_state%global_grid%configuration%vertical%olzvbar(k)-&
172  current_state%global_grid%configuration%vertical%olzvbar(k-1))+&
173  current_state%global_grid%configuration%vertical%w_subs(k)*&
174  current_state%global_grid%configuration%vertical%tzc2(k)*(&
175  current_state%global_grid%configuration%vertical%olzvbar(k+1)-&
176  current_state%global_grid%configuration%vertical%olzvbar(k))
177  end do
178  else if (name .eq. "th_subsidence") then
179  allocate(field_value%real_1d_array(column_size))
180  do k=2, column_size-1
181  field_value%real_1d_array(k)=0.0_default_precision-2.0*&
182  current_state%global_grid%configuration%vertical%w_subs(k-1)*&
183  current_state%global_grid%configuration%vertical%tzc1(k)*(&
184  current_state%global_grid%configuration%vertical%olzthbar(k)-&
185  current_state%global_grid%configuration%vertical%olzthbar(k-1)+&
186  current_state%global_grid%configuration%vertical%dthref(k-1))+&
187  current_state%global_grid%configuration%vertical%w_subs(k)*&
188  current_state%global_grid%configuration%vertical%tzc2(k)*(&
189  current_state%global_grid%configuration%vertical%olzthbar(k+1)-&
190  current_state%global_grid%configuration%vertical%olzthbar(k)+&
191  current_state%global_grid%configuration%vertical%dthref(k))
192  end do
193  else if (name .eq. "q_subsidence") then
194  allocate(field_value%real_2d_array(column_size, current_state%number_q_fields))
195  do n=1, current_state%number_q_fields
196  do k=2, column_size-1
197  field_value%real_2d_array(k,n)=0.0_default_precision-2.0*&
198  current_state%global_grid%configuration%vertical%w_subs(k-1)*&
199  current_state%global_grid%configuration%vertical%tzc1(k)*(&
200  current_state%global_grid%configuration%vertical%olzqbar(k,n)-&
201  current_state%global_grid%configuration%vertical%olzqbar(k-1,n))+&
202  current_state%global_grid%configuration%vertical%w_subs(k)&
203  *current_state%global_grid%configuration%vertical%tzc2(k)*(&
204  current_state%global_grid%configuration%vertical%olzqbar(k+1,n)-&
205  current_state%global_grid%configuration%vertical%olzqbar(k,n))
206  end do
207  end do
208  else if (name .eq. "u_large_scale") then
209  allocate(field_value%real_1d_array(column_size))
210  field_value%real_1d_array=get_averaged_diagnostics(current_state, du_profile_diag)
211  else if (name .eq. "v_large_scale") then
212  allocate(field_value%real_1d_array(column_size))
213  field_value%real_1d_array=get_averaged_diagnostics(current_state, dv_profile_diag)
214  else if (name .eq. "th_large_scale") then
215  allocate(field_value%real_1d_array(column_size))
216  field_value%real_1d_array=dtheta_profile_diag
217  else if (name .eq. "q_large_scale") then
218  allocate(field_value%real_2d_array(column_size, current_state%number_q_fields))
219  do n=1, current_state%number_q_fields
220  field_value%real_2d_array(:,n)=get_averaged_diagnostics(current_state, dq_profile_diag(:,n))
221  end do
222  end if
223  end subroutine field_value_retrieval_callback
224 
226  subroutine init_callback(current_state)
227  type(model_state_type), target, intent(inout) :: current_state
228 
229  integer :: nq_force ! The number of q fields apply large-scale time-independent forcing
230  integer :: nzq ! The number of input levels for subsidence/divergence profile
231  integer :: i,n ! loop counters
232  integer :: iq ! temporary q varible index
233 
234  ! Input arrays for subsidence profile
235  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: f_subs_pl ! subsidence node for q variables
236  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: z_subs_pl ! subsidence node height values for q variables
237 
238  ! Input arrays for time-independent forcing
239  real(kind=DEFAULT_PRECISION), dimension(:, :), allocatable :: f_force_pl_q ! Forcing values for q variables
240  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: z_force_pl_q ! Forcing height values for q variables
241  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: f_force_pl_theta ! Forcing values for theta variable
242  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: z_force_pl_theta ! Forcing height values for theta variable
243  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: f_force_pl_u ! Forcing values for u variable
244  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: z_force_pl_u ! Forcing height values for u variable
245  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: f_force_pl_v ! Forcing values for v variable
246  real(kind=DEFAULT_PRECISION), dimension(:), allocatable :: z_force_pl_v ! Forcing height values for v variabl
247 
248  integer :: subsidence_input_type=divergence ! Determines if we're reading in a subsidence velocity or divergence
249 
250  real(kind=DEFAULT_PRECISION), allocatable :: f_force_pl_q_tmp(:) !temporary 1D storage of forcing for q fields
251  real(kind=DEFAULT_PRECISION), allocatable :: zgrid(:) ! z grid to use in interpolation
252 
253  character(len=STRING_LENGTH), dimension(:), allocatable :: units_q_force ! units of q variable forcing
254  character(len=STRING_LENGTH) :: units_theta_force='unset' ! units of theta variable forcing
255  character(len=STRING_LENGTH) :: units_u_force='unset' ! units of theta variable forcing
256  character(len=STRING_LENGTH) :: units_v_force='unset' ! units of theta variable forcing
257 
258  logical :: convert_input_theta_from_temperature=.false. ! If .true. input forcing data is for temperature and should
259  ! be converted to theta (potential temerature).
260 
261  integer :: k
262 
263  allocate(theta_profile(current_state%local_grid%size(z_index)), &
264  q_profile(current_state%local_grid%size(z_index)), &
265  u_profile(current_state%local_grid%size(z_index)), &
266  v_profile(current_state%local_grid%size(z_index)))
267 
268  allocate(dtheta_profile(current_state%local_grid%size(z_index)), &
269  dq_profile(current_state%local_grid%size(z_index)), &
270  du_profile(current_state%local_grid%size(z_index)), &
271  dv_profile(current_state%local_grid%size(z_index)))
272 
273  allocate(du_profile_diag(current_state%local_grid%size(z_index)), dv_profile_diag(current_state%local_grid%size(z_index)), &
274  dtheta_profile_diag(current_state%local_grid%size(z_index)), &
275  dq_profile_diag(current_state%local_grid%size(z_index), current_state%number_q_fields))
276 
277  allocate(zgrid(current_state%local_grid%size(z_index)))
278 
279  ! Subsidence forcing initialization
280 
281  l_subs_pl_theta=options_get_logical(current_state%options_database, "l_subs_pl_theta")
282  l_subs_pl_q=options_get_logical(current_state%options_database, "l_subs_pl_q")
283  subsidence_input_type=options_get_integer(current_state%options_database, "subsidence_input_type")
284  l_subs_local_theta=options_get_logical(current_state%options_database, "subsidence_local_theta")
285  l_subs_local_q=options_get_logical(current_state%options_database, "subsidence_local_q")
286 
287 
288  if ((l_subs_pl_theta .and. .not. l_subs_local_theta) .or. &
289  (l_subs_pl_q .and. .not. l_subs_local_q))then
290  if (.not. is_component_enabled(current_state%options_database, "mean_profiles")) then
291  call log_master_log(log_error, "Damping requires the mean profiles component to be enabled")
292  end if
293  end if
294 
295  if (l_subs_pl_theta .or. l_subs_pl_q)then
296  allocate(z_subs_pl(options_get_array_size(current_state%options_database, "z_subs_pl")), &
297  f_subs_pl(options_get_array_size(current_state%options_database, "f_subs_pl")))
298  call options_get_real_array(current_state%options_database, "z_subs_pl", z_subs_pl)
299  call options_get_real_array(current_state%options_database, "f_subs_pl", f_subs_pl)
300  ! Get profiles
301  zgrid=current_state%global_grid%configuration%vertical%z(:)
302  call piecewise_linear_1d(z_subs_pl(1:size(z_subs_pl)), f_subs_pl(1:size(f_subs_pl)), zgrid, &
303  current_state%global_grid%configuration%vertical%w_subs)
304  if (subsidence_input_type==divergence) then
305  current_state%global_grid%configuration%vertical%w_subs(:) = &
306  -1.0*current_state%global_grid%configuration%vertical%w_subs(:)*zgrid(:)
307  end if
308  deallocate(z_subs_pl, f_subs_pl)
309  end if
310 
311  ! Time independent large-scale forcing (proxy for e.g. advection/radiation)
312 
313  ! This probably isn't the right place to be doing this
314  if (.not. allocated(current_state%l_forceq))then
315  allocate(current_state%l_forceq(current_state%number_q_fields))
316  current_state%l_forceq=.false.
317  end if
318 
319  l_constant_forcing_theta=options_get_logical(current_state%options_database, "l_constant_forcing_theta")
320  l_constant_forcing_q=options_get_logical(current_state%options_database, "l_constant_forcing_q")
321  l_constant_forcing_u=options_get_logical(current_state%options_database, "l_constant_forcing_u")
322  l_constant_forcing_v=options_get_logical(current_state%options_database, "l_constant_forcing_v")
323 
324  if (l_constant_forcing_q) then
325  allocate(names_force_pl_q(options_get_array_size(current_state%options_database, "names_constant_forcing_q")))
326  call options_get_string_array(current_state%options_database, "names_constant_forcing_q", names_force_pl_q)
327  end if
328 
329  if (l_constant_forcing_theta)then
330  constant_forcing_type_theta=options_get_integer(current_state%options_database, "constant_forcing_type_theta")
331  forcing_timescale_theta=options_get_real(current_state%options_database, "forcing_timescale_theta")
332  l_constant_forcing_theta_z2pressure=options_get_logical(current_state%options_database, "l_constant_forcing_theta_z2pressure")
333 
334  allocate(z_force_pl_theta(options_get_array_size(current_state%options_database, "z_force_pl_theta")), &
335  f_force_pl_theta(options_get_array_size(current_state%options_database, "f_force_pl_theta")))
336  call options_get_real_array(current_state%options_database, "z_force_pl_theta", z_force_pl_theta)
337  call options_get_real_array(current_state%options_database, "f_force_pl_theta", f_force_pl_theta)
338  ! Get profiles
339  relax_to_initial_theta_profile=options_get_logical(current_state%options_database, "relax_to_initial_theta_profile")
341  current_state%global_grid%configuration%vertical%theta_force(:) = &
342  current_state%global_grid%configuration%vertical%theta_init(:)
343  else
345  zgrid=current_state%global_grid%configuration%vertical%zn(:)
346  else
347  zgrid=current_state%global_grid%configuration%vertical%prefn(:)
348  end if
349  call piecewise_linear_1d(z_force_pl_theta(1:size(z_force_pl_theta)), f_force_pl_theta(1:size(f_force_pl_theta)), zgrid, &
350  current_state%global_grid%configuration%vertical%theta_force)
351  end if
352 
353  ! Unit conversions...
354  if (convert_input_theta_from_temperature)then ! Input is temperature not theta
355  current_state%global_grid%configuration%vertical%theta_force(:) = &
356  current_state%global_grid%configuration%vertical%theta_force(:)* &
357  current_state%global_grid%configuration%vertical%prefrcp(:)
358  end if
359 
361  units_theta_force=options_get_string(current_state%options_database, "units_theta_force")
362  select case(trim(units_theta_force))
363  case(k_per_day)
364  current_state%global_grid%configuration%vertical%theta_force(:) = &
365  current_state%global_grid%configuration%vertical%theta_force(:)/seconds_in_a_day
366  case default !(k_per_second)
367  end select
368  end if
369  deallocate(z_force_pl_theta, f_force_pl_theta)
370  end if
371 
372 #ifdef U_ACTIVE
373  if (l_constant_forcing_u)then
374  constant_forcing_type_u=options_get_integer(current_state%options_database, "constant_forcing_type_u")
375  forcing_timescale_u=options_get_real(current_state%options_database, "forcing_timescale_u")
376  relax_to_initial_u_profile=options_get_logical(current_state%options_database, "relax_to_initial_u_profile")
378  current_state%global_grid%configuration%vertical%u_force(:) = &
379  current_state%global_grid%configuration%vertical%u_init(:)
380  else
381  allocate(z_force_pl_u(options_get_array_size(current_state%options_database, "z_force_pl_u")), &
382  f_force_pl_u(options_get_array_size(current_state%options_database, "f_force_pl_u")))
383  call options_get_real_array(current_state%options_database, "z_force_pl_u", z_force_pl_u)
384  call options_get_real_array(current_state%options_database, "f_force_pl_u", f_force_pl_u)
385  ! Get profiles
386  zgrid=current_state%global_grid%configuration%vertical%zn(:)
387  call piecewise_linear_1d(z_force_pl_u(1:size(z_force_pl_u)), f_force_pl_u(1:size(f_force_pl_u)), zgrid, &
388  current_state%global_grid%configuration%vertical%u_force)
389  deallocate(z_force_pl_u, f_force_pl_u)
390  end if
391 
392 
394  ! Unit conversions...
395  units_u_force=options_get_string(current_state%options_database, "units_u_force")
396  select case(trim(units_u_force))
397  case(m_per_second_per_day)
398  current_state%global_grid%configuration%vertical%u_force(:) = &
399  current_state%global_grid%configuration%vertical%u_force(:)/seconds_in_a_day
400  case default !(m_per_second_per_second)
401  end select
402  end if
403  end if
404 #endif
405 
406 #ifdef V_ACTIVE
407  if (l_constant_forcing_v)then
408  constant_forcing_type_v=options_get_integer(current_state%options_database, "constant_forcing_type_v")
409  forcing_timescale_v=options_get_real(current_state%options_database, "forcing_timescale_v")
410  relax_to_initial_v_profile=options_get_logical(current_state%options_database, "relax_to_initial_v_profile")
412  current_state%global_grid%configuration%vertical%v_force(:) = &
413  current_state%global_grid%configuration%vertical%v_init(:)
414  else
415  allocate(z_force_pl_v(options_get_array_size(current_state%options_database, "z_force_pl_v")), &
416  f_force_pl_v(options_get_array_size(current_state%options_database, "f_force_pl_v")))
417  call options_get_real_array(current_state%options_database, "z_force_pl_v", z_force_pl_v)
418  call options_get_real_array(current_state%options_database, "f_force_pl_v", f_force_pl_v)
419  ! Get profiles
420  zgrid=current_state%global_grid%configuration%vertical%zn(:)
421  call piecewise_linear_1d(z_force_pl_v(1:size(z_force_pl_v)), f_force_pl_v(1:size(f_force_pl_v)), zgrid, &
422  current_state%global_grid%configuration%vertical%v_force)
423  deallocate(z_force_pl_v, f_force_pl_v)
424  end if
425 
426 
428  ! Unit conversions...
429  units_v_force=options_get_string(current_state%options_database, "units_v_force")
430  select case(trim(units_v_force))
431  case(m_per_second_per_day)
432  current_state%global_grid%configuration%vertical%v_force(:) = &
433  current_state%global_grid%configuration%vertical%v_force(:)/seconds_in_a_day
434  case default !(m_per_second_per_second)
435  end select
436  end if
437  end if
438 #endif
439 
440  if (l_constant_forcing_q) then
441  constant_forcing_type_q=options_get_integer(current_state%options_database, "constant_forcing_type_q")
442  forcing_timescale_q=options_get_real(current_state%options_database, "forcing_timescale_q")
443  nq_force=size(names_force_pl_q)
444  allocate(z_force_pl_q(options_get_array_size(current_state%options_database, "z_force_pl_q")))
445  call options_get_real_array(current_state%options_database, "z_force_pl_q", z_force_pl_q)
446  nzq=size(z_force_pl_q)
447  zgrid=current_state%global_grid%configuration%vertical%zn(:)
448  allocate(f_force_pl_q_tmp(nq_force*nzq))
449  call options_get_real_array(current_state%options_database, "f_force_pl_q", f_force_pl_q_tmp)
450  allocate(f_force_pl_q(nzq, nq_force))
451  f_force_pl_q(1:nzq, 1:nq_force)=reshape(f_force_pl_q_tmp, (/nzq, nq_force/))
452 
453  allocate(units_q_force(options_get_array_size(current_state%options_database, "units_q_force")))
454  call options_get_string_array(current_state%options_database, "units_q_force", units_q_force)
455  do n=1, nq_force
456  iq=get_q_index(trim(names_force_pl_q(n)), 'forcing:time-independent')
457  call piecewise_linear_1d(z_force_pl_q(1:nzq), f_force_pl_q(1:nzq,n), zgrid, &
458  current_state%global_grid%configuration%vertical%q_force(:,iq))
459 
460  current_state%l_forceq(iq)=.true.
461 
462  ! Unit conversions...
464  select case(trim(units_q_force(n)))
465  case(kg_per_kg_per_day)
466  current_state%global_grid%configuration%vertical%q_force(:,iq) = &
467  current_state%global_grid%configuration%vertical%q_force(:,iq)/seconds_in_a_day
468  case(g_per_kg_per_day)
469  current_state%global_grid%configuration%vertical%q_force(:,iq) = &
470  0.001*current_state%global_grid%configuration%vertical%q_force(:,iq)/seconds_in_a_day
471  case(g_per_kg_per_second)
472  current_state%global_grid%configuration%vertical%q_force(:,iq) = &
473  0.001*current_state%global_grid%configuration%vertical%q_force(:,iq)
474  case default !(kg_per_kg_per_second)
475  end select
476  end if
477  end do
478  deallocate(f_force_pl_q_tmp, units_q_force, f_force_pl_q, z_force_pl_q)
479  end if
480 
481  deallocate(zgrid)
482  end subroutine init_callback
483 
487  subroutine timestep_callback(current_state)
488  type(model_state_type), target, intent(inout) :: current_state
489 
490  if (current_state%first_timestep_column) then
491  du_profile_diag=0.0_default_precision
492  dv_profile_diag=0.0_default_precision
493  dtheta_profile_diag=0.0_default_precision
494  dq_profile_diag=0.0_default_precision
495  end if
496 
497  if (current_state%halo_column .or. current_state%timestep<3) return
498  if (l_subs_pl_theta) then
499  call apply_subsidence_to_flow_fields(current_state)
500  call apply_subsidence_to_theta(current_state)
501  end if
502  if (l_subs_pl_q) call apply_subsidence_to_q_fields(current_state)
503 
505 #ifdef U_ACTIVE
507 #endif
508 #ifdef V_ACTIVE
510 #endif
512  end subroutine timestep_callback
513 
514  subroutine apply_subsidence_to_flow_fields(current_state)
515  type(model_state_type), intent(inout) :: current_state
516 
517  integer :: k
518  real(kind=DEFAULT_PRECISION) :: usub, vsub
519 
520 
521  if (l_subs_local_theta)then ! Use local gradients not global means
522  u_profile(:)=current_state%zu%data(:,current_state%column_local_y,current_state%column_local_x)
523  v_profile(:)=current_state%zv%data(:,current_state%column_local_y,current_state%column_local_x)
524  else
525  u_profile(:)=current_state%global_grid%configuration%vertical%olzubar(:)
526  v_profile(:)=current_state%global_grid%configuration%vertical%olzvbar(:)
527  end if
528 
529  do k=2,current_state%local_grid%size(z_index)-1
530 #ifdef U_ACTIVE
531  usub = 2.0 * (current_state%global_grid%configuration%vertical%w_subs(k-1)* &
532  current_state%global_grid%configuration%vertical%tzc1(k)*(u_profile(k)-u_profile(k-1)) &
533  + current_state%global_grid%configuration%vertical%w_subs(k)* &
534  current_state%global_grid%configuration%vertical%tzc2(k)* &
535  (u_profile(k+1) - u_profile(k)))
536  current_state%su%data(k,current_state%column_local_y,current_state%column_local_x) = &
537  current_state%su%data(k,current_state%column_local_y,current_state%column_local_x) - usub
538 #endif
539 #ifdef V_ACTIVE
540  vsub = 2.0 * (current_state%global_grid%configuration%vertical%w_subs(k-1)* &
541  current_state%global_grid%configuration%vertical%tzc1(k)*(v_profile(k)-v_profile(k-1)) &
542  + current_state%global_grid%configuration%vertical%w_subs(k)* &
543  current_state%global_grid%configuration%vertical%tzc2(k)* &
544  (v_profile(k+1) - v_profile(k)))
545  current_state%sv%data(k,current_state%column_local_y,current_state%column_local_x) = &
546  current_state%sv%data(k,current_state%column_local_y,current_state%column_local_x) - vsub
547 #endif
548  end do
549  k=current_state%local_grid%size(z_index)
550 #ifdef U_ACTIVE
551  usub = 2.0 * (current_state%global_grid%configuration%vertical%w_subs(k-1)* &
552  current_state%global_grid%configuration%vertical%tzc1(k)*(u_profile(k)-u_profile(k-1)))
553  current_state%su%data(k,current_state%column_local_y,current_state%column_local_x) = &
554  current_state%su%data(k,current_state%column_local_y,current_state%column_local_x) - usub
555 #endif
556 #ifdef V_ACTIVE
557  vsub = 2.0 * (current_state%global_grid%configuration%vertical%w_subs(k-1)* &
558  current_state%global_grid%configuration%vertical%tzc1(k)*(v_profile(k)-v_profile(k-1)))
559  current_state%sv%data(k,current_state%column_local_y,current_state%column_local_x) = &
560  current_state%sv%data(k,current_state%column_local_y,current_state%column_local_x) - vsub
561 #endif
562  end subroutine apply_subsidence_to_flow_fields
563 
564  subroutine apply_subsidence_to_theta(current_state)
565  type(model_state_type), intent(inout) :: current_state
566 
567  integer :: k
568  real(kind=DEFAULT_PRECISION) :: thsub
569 
570  if (l_subs_local_theta)then ! Use local gradients not global means
571  theta_profile(:)=current_state%zth%data(:,current_state%column_local_y,current_state%column_local_x) &
572  + current_state%global_grid%configuration%vertical%thref(:)
573  else
574  theta_profile(:)=current_state%global_grid%configuration%vertical%olzthbar(:) &
575  + current_state%global_grid%configuration%vertical%thref(:)
576  end if
577 
578  do k=2,current_state%local_grid%size(z_index)-1
579  thsub = current_state%global_grid%configuration%vertical%w_subs(k)* &
580  (theta_profile(k+1) - theta_profile(k))* &
581  current_state%global_grid%configuration%vertical%rdzn(k+1)
582 
583  current_state%sth%data(k,current_state%column_local_y,current_state%column_local_x) = &
584  current_state%sth%data(k,current_state%column_local_y,current_state%column_local_x) - thsub
585  end do
586  k=current_state%local_grid%size(z_index)
587  thsub = current_state%global_grid%configuration%vertical%w_subs(k)* &
588  (theta_profile(k) - theta_profile(k-1))* &
589  current_state%global_grid%configuration%vertical%rdzn(k)
590 
591  current_state%sth%data(k,current_state%column_local_y,current_state%column_local_x) = &
592  current_state%sth%data(k,current_state%column_local_y,current_state%column_local_x) - thsub
593  end subroutine apply_subsidence_to_theta
594 
595  subroutine apply_subsidence_to_q_fields(current_state)
596  type(model_state_type), intent(inout) :: current_state
597 
598  integer :: k, n
599  real(kind=DEFAULT_PRECISION) :: qsub
600 
601 
602  do n=1,current_state%number_q_fields
603  if (l_subs_local_q)then ! Use local gradients not global means
604  q_profile(:)=current_state%zq(n)%data(:,current_state%column_local_y,current_state%column_local_x)
605  else
606  q_profile(:)=current_state%global_grid%configuration%vertical%olzqbar(:,n)
607  end if
608  do k=2,current_state%local_grid%size(z_index)-1
609  qsub = current_state%global_grid%configuration%vertical%w_subs(k)* &
610  (q_profile(k+1) - q_profile(k))* &
611  current_state%global_grid%configuration%vertical%rdzn(k+1)
612  current_state%sq(n)%data(k,current_state%column_local_y,current_state%column_local_x) = &
613  current_state%sq(n)%data(k,current_state%column_local_y,current_state%column_local_x) - qsub
614  end do
615  k=current_state%local_grid%size(z_index)
616  qsub = current_state%global_grid%configuration%vertical%w_subs(k)* &
617  (q_profile(k) - q_profile(k-1))* &
618  current_state%global_grid%configuration%vertical%rdzn(k)
619  current_state%sq(n)%data(k,current_state%column_local_y,current_state%column_local_x) = &
620  current_state%sq(n)%data(k,current_state%column_local_y,current_state%column_local_x) - qsub
621  end do
622  end subroutine apply_subsidence_to_q_fields
623 
624  subroutine apply_time_independent_forcing_to_theta(current_state)
625  type(model_state_type), intent(inout) :: current_state
626 
627  integer :: k
628  real(kind=DEFAULT_PRECISION) :: dtm_scale
629 
631  dtm_scale=1.0_default_precision
632  else ! constant_forcing_type_theta==(RELAXATION or INCREMENT)
633  dtm_scale=1.0_default_precision/forcing_timescale_theta
634  end if
635 
637  dtheta_profile(:)=dtm_scale * (current_state%global_grid%configuration%vertical%theta_force(:) - &
638  current_state%zth%data(:,current_state%column_local_y,current_state%column_local_x) - &
639  current_state%global_grid%configuration%vertical%thref(:))
640  else ! constant_forcing_type_theta==(TENDENCY or INCREMENT)
641  dtheta_profile(:)=dtm_scale * current_state%global_grid%configuration%vertical%theta_force(:)
642  end if
643 
644 
646 
647  do k=2,current_state%local_grid%size(z_index)-1
648  current_state%sth%data(k,current_state%column_local_y,current_state%column_local_x) = &
649  current_state%sth%data(k,current_state%column_local_y,current_state%column_local_x) &
650  + dtheta_profile(k)
651  end do
652 
654 
655  subroutine apply_time_independent_forcing_to_q(current_state)
656  type(model_state_type), intent(inout) :: current_state
657 
658  integer :: n, k
659  real(kind=DEFAULT_PRECISION) :: dtm_scale
660 
661  do n=1,current_state%number_q_fields
662  if (current_state%l_forceq(n))then
664  dtm_scale=1.0_default_precision
665  else ! constant_forcing_type_q==(RELAXATION or INCREMENT)
666  dtm_scale=1.0_default_precision/forcing_timescale_q
667  end if
668 
670  dq_profile(:)=dtm_scale * (current_state%global_grid%configuration%vertical%q_force(:,n) - &
671  current_state%zq(n)%data(:,current_state%column_local_y,current_state%column_local_x))
672  else ! constant_forcing_type_q==(TENDENCY or INCREMENT)
673  dq_profile(:)=dtm_scale * current_state%global_grid%configuration%vertical%q_force(:,n)
674  end if
675 
677 
678  do k=2,current_state%local_grid%size(z_index)-1
679  current_state%sq(n)%data(k,current_state%column_local_y,current_state%column_local_x) = &
680  current_state%sq(n)%data(k,current_state%column_local_y,current_state%column_local_x) &
681  + dq_profile(k)
682  end do
683  end if
684  end do
685 
687 
688  subroutine apply_time_independent_forcing_to_u(current_state)
689  type(model_state_type), intent(inout) :: current_state
690 
691  integer :: k
692  real(kind=DEFAULT_PRECISION) :: dtm_scale
693 
695  dtm_scale=1.0_default_precision
696  else ! constant_forcing_type_u==(RELAXATION or INCREMENT)
697  dtm_scale=1.0_default_precision/forcing_timescale_u
698  end if
699 
701  du_profile(:)=dtm_scale * (current_state%global_grid%configuration%vertical%u_force(:) - &
702  current_state%global_grid%configuration%vertical%olzubar(:))
703  else ! constant_forcing_type_u==(TENDENCY or INCREMENT)
704  du_profile(:)=dtm_scale * current_state%global_grid%configuration%vertical%u_force(:)
705  end if
706 
708 
709  do k=2,current_state%local_grid%size(z_index)-1
710  current_state%su%data(k,current_state%column_local_y,current_state%column_local_x) = &
711  current_state%su%data(k,current_state%column_local_y,current_state%column_local_x) &
712  + du_profile(k)
713  end do
714 
716 
717  subroutine apply_time_independent_forcing_to_v(current_state)
718  type(model_state_type), intent(inout) :: current_state
719 
720  integer :: k
721  real(kind=DEFAULT_PRECISION) :: dtm_scale
722 
724  dtm_scale=1.0_default_precision
725  else ! constant_forcing_type_v==(RELAXATION or INCREMENT)
726  dtm_scale=1.0_default_precision/forcing_timescale_v
727  end if
728 
730  dv_profile(:)=dtm_scale * (current_state%global_grid%configuration%vertical%v_force(:) - &
731  current_state%global_grid%configuration%vertical%olzvbar(:) )
732  else ! constant_forcing_type_v==(TENDENCY or INCREMENT)
733  dv_profile(:)=dtm_scale * current_state%global_grid%configuration%vertical%v_force(:)
734  end if
735 
737 
738  do k=2,current_state%local_grid%size(z_index)-1
739  current_state%sv%data(k,current_state%column_local_y,current_state%column_local_x) = &
740  current_state%sv%data(k,current_state%column_local_y,current_state%column_local_x) &
741  + dv_profile(k)
742  end do
744 
747  subroutine finalisation_callback(current_state)
748  type(model_state_type), target, intent(inout) :: current_state
751  if (allocated(du_profile_diag)) deallocate(du_profile_diag)
752  if (allocated(dv_profile_diag)) deallocate(dv_profile_diag)
753  if (allocated(dtheta_profile_diag)) deallocate(dtheta_profile_diag)
754  if (allocated(dq_profile_diag)) deallocate(dq_profile_diag)
755  end subroutine finalisation_callback
756 
761  function get_averaged_diagnostics(current_state, diagnostics_summed)
762  type(model_state_type), target, intent(inout) :: current_state
763  real(kind=DEFAULT_PRECISION), dimension(:), intent(in) :: diagnostics_summed
764  real(kind=DEFAULT_PRECISION), dimension(size(diagnostics_summed)) :: get_averaged_diagnostics
765 
766  integer :: horizontal_points
767 
768  horizontal_points=current_state%local_grid%size(x_index) * current_state%local_grid%size(y_index)
769 
770  get_averaged_diagnostics(:)=diagnostics_summed(:)/horizontal_points
771  end function get_averaged_diagnostics
772 end module forcing_mod
integer, parameter tendency
Definition: forcing.F90:26
real(kind=default_precision), dimension(:), allocatable dv_profile
Definition: forcing.F90:38
logical relax_to_initial_theta_profile
Definition: forcing.F90:61
subroutine apply_time_independent_forcing_to_v(current_state)
Definition: forcing.F90:718
subroutine field_value_retrieval_callback(current_state, name, field_value)
Field value retrieval callback, this returns the value of a specific published field.
Definition: forcing.F90:144
integer function, public options_get_array_size(options_database, key)
Gets the size of the array held in the options database corresponding to a specific key...
type(component_descriptor_type) function, public forcing_get_descriptor()
Provides the component descriptor for the core to register.
Definition: forcing.F90:78
Wrapper type for the value returned for a published field from a component.
subroutine apply_subsidence_to_flow_fields(current_state)
Definition: forcing.F90:515
subroutine apply_time_independent_forcing_to_q(current_state)
Definition: forcing.F90:656
type(standard_q_names_type), public standard_q_names
Definition: q_indices.F90:59
real(kind=default_precision), dimension(:), allocatable dtheta_profile_diag
Definition: forcing.F90:39
integer, parameter, public log_error
Only log ERROR messages.
Definition: logging.F90:11
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.
integer constant_forcing_type_v
Definition: forcing.F90:55
real(kind=default_precision), dimension(:), allocatable u_profile
Definition: forcing.F90:32
subroutine finalisation_callback(current_state)
Finalises the component Current model state.
Definition: forcing.F90:748
Logging utility.
Definition: logging.F90:2
real(kind=default_precision), dimension(:), allocatable dq_profile
Definition: forcing.F90:36
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
real(kind=default_precision) function, dimension(size(diagnostics_summed)) get_averaged_diagnostics(current_state, diagnostics_summed)
Averages some diagnostic values across all local horizontal points.
Definition: forcing.F90:762
real(kind=default_precision) forcing_timescale_u
Definition: forcing.F90:44
real(kind=default_precision), dimension(:), allocatable du_profile
Definition: forcing.F90:37
logical l_constant_forcing_q
Definition: forcing.F90:48
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
integer constant_forcing_type_theta
Definition: forcing.F90:52
real(kind=default_precision), dimension(:), allocatable v_profile
Definition: forcing.F90:33
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 init_callback(current_state)
Initialises the forcing data structures.
Definition: forcing.F90:227
real(kind=default_precision), dimension(:), allocatable theta_profile
Definition: forcing.F90:30
subroutine, public log_master_log(level, message)
Will log just from the master process.
Definition: logging.F90:47
integer, parameter relaxation
Definition: forcing.F90:27
real(kind=default_precision), dimension(:), allocatable dtheta_profile
Definition: forcing.F90:35
logical relax_to_initial_v_profile
Definition: forcing.F90:60
integer, parameter, public component_array_field_type
real(kind=default_precision) forcing_timescale_theta
Definition: forcing.F90:42
subroutine apply_time_independent_forcing_to_theta(current_state)
Definition: forcing.F90:625
real(kind=default_precision), dimension(:,:), allocatable dq_profile_diag
Definition: forcing.F90:39
logical l_subs_local_theta
Definition: forcing.F90:66
Scientific constant values used throughout simulations. Each has a default value and this can be over...
logical l_constant_forcing_v
Definition: forcing.F90:50
This manages the Q variables and specifically the mapping between names and the index that they are s...
Definition: q_indices.F90:2
logical l_constant_forcing_u
Definition: forcing.F90:49
logical l_constant_forcing_theta_z2pressure
Definition: forcing.F90:57
Interfaces and types that MONC components must specify.
subroutine piecewise_linear_1d(zvals, vals, zgrid, field)
Does a simple 1d piecewise linear interpolation.
real(kind=default_precision), public seconds_in_a_day
real(kind=default_precision), dimension(:), allocatable dv_profile_diag
Definition: forcing.F90:39
subroutine, public options_get_logical_array(options_database, key, array_data, from, to)
Retrieves an entire (or subset) logical array.
subroutine apply_subsidence_to_theta(current_state)
Definition: forcing.F90:565
logical l_subs_pl_q
Definition: forcing.F90:64
integer, parameter, public string_length
Default length of strings.
Definition: datadefn.F90:10
subroutine apply_time_independent_forcing_to_u(current_state)
Definition: forcing.F90:689
real(kind=default_precision), dimension(:), allocatable q_profile
Definition: forcing.F90:31
integer constant_forcing_type_q
Definition: forcing.F90:53
real(kind=default_precision), dimension(:), allocatable du_profile_diag
Definition: forcing.F90:39
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...
Definition: grids.F90:5
integer function, public options_get_integer(options_database, key, index)
Retrieves an integer value from the database that matches the provided key.
subroutine timestep_callback(current_state)
Called for each data column and will determine the forcing values in x and y which are then applied t...
Definition: forcing.F90:488
integer, parameter subsidence
Definition: forcing.F90:24
Manages the options database. Contains administration functions and deduce runtime options from the c...
integer, parameter increment
Definition: forcing.F90:28
integer constant_forcing_type_u
Definition: forcing.F90:54
logical function, public options_get_logical(options_database, key, index)
Retrieves a logical value from the database that matches the provided key.
character(len=string_length), dimension(:), allocatable names_force_pl_q
Definition: forcing.F90:69
integer, parameter divergence
Definition: forcing.F90:23
subroutine apply_subsidence_to_q_fields(current_state)
Definition: forcing.F90:596
real(kind=default_precision) forcing_timescale_q
Definition: forcing.F90:43
Forcing, both subsidence and large scale.
Definition: forcing.F90:2
subroutine, public options_get_string_array(options_database, key, array_data, from, to)
Retrieves an entire (or subset) string array.
subroutine, public options_get_real_array(options_database, key, array_data, from, to)
Retrieves an entire (or subset) real array.
The model state which represents the current state of a run.
Definition: state.F90:2
integer, parameter, public y_index
Definition: grids.F90:14
logical relax_to_initial_u_profile
Definition: forcing.F90:59
logical l_subs_local_q
Definition: forcing.F90:67
subroutine field_information_retrieval_callback(current_state, name, field_information)
Field information retrieval callback, this returns information for a specific components published fi...
Definition: forcing.F90:103
integer, parameter, public x_index
Definition: grids.F90:14
integer function, public get_q_index(name, assigning_component)
Add in a new entry into the register if the name does not already exist or return the index of the pr...
Definition: q_indices.F90:112
real(kind=default_precision) forcing_timescale_v
Definition: forcing.F90:45
MONC component registry.
Definition: registry.F90:5
logical l_subs_pl_theta
Definition: forcing.F90:63
integer, parameter, public component_double_data_type
logical l_constant_forcing_theta
Definition: forcing.F90:47