MONC
stepfields.F90
Go to the documentation of this file.
1 
10  use science_constants_mod, only : rlargep
11  implicit none
12 
13 #ifndef TEST_MODE
14  private
15 #endif
16 
18 
19 
20  real(kind=DEFAULT_PRECISION), allocatable :: resetq_min(:)
21  logical :: l_nonconservative_positive_q=.true.
22 
24 
25 contains
26 
30  stepfields_get_descriptor%name="stepfields"
31  stepfields_get_descriptor%version=0.1
35  end function stepfields_get_descriptor
36 
39  subroutine initialisation_callback(current_state)
40  type(model_state_type), target, intent(inout) :: current_state
41 
42  allocate(resetq_min(current_state%number_q_fields))
43  cfl_is_enabled=is_component_enabled(current_state%options_database, "cfltest")
44  if (cfl_is_enabled) call reset_local_minmax_values(current_state)
45  end subroutine initialisation_callback
46 
47 
50  subroutine finalisation_callback(current_state)
51  type(model_state_type), target, intent(inout) :: current_state
52 
53  deallocate(resetq_min)
54  end subroutine finalisation_callback
55 
58  subroutine timestep_callback(current_state)
59  type(model_state_type), target, intent(inout) :: current_state
60 
61  integer :: iq
62 
63  if (cfl_is_enabled .and. current_state%first_timestep_column) then
64  if (mod(current_state%timestep, current_state%cfl_frequency) == 1 .or. &
65  current_state%timestep-current_state%start_timestep .le. current_state%cfl_frequency) then
67  call reset_local_minmax_values(current_state)
68  else
69  determine_flow_minmax=.false.
70  end if
71  end if
72 
73  if (.not. current_state%halo_column) then
75  call determine_local_flow_minmax(current_state, current_state%column_local_y, current_state%column_local_x)
76  call step_all_fields(current_state)
77  end if
78 
79  ! Remove negative rounding errors
81  do iq=1,current_state%number_q_fields
82  if (current_state%first_timestep_column)then
83  resetq_min(iq)=minval(current_state%zq(iq)%data(:,current_state%column_local_y, current_state%column_local_x))
84  else
85  resetq_min(iq)=min(resetq_min(iq),&
86  minval(current_state%zq(iq)%data(:,current_state%column_local_y, current_state%column_local_x)))
87  end if
88  call remove_negative_rounding_errors_for_single_field(current_state%column_local_x, current_state%column_local_y, &
89  current_state%column_local_x-2, current_state%column_local_y-1, current_state%zq(iq), current_state%local_grid)
90  end do
91  end if
92 
93  end subroutine timestep_callback
94 
97  subroutine step_all_fields(current_state)
98  type(model_state_type), target, intent(inout) :: current_state
99 
100  integer :: x_prev, y_prev, i, k
101  real(kind=DEFAULT_PRECISION) :: c1, c2
102 
103  x_prev = current_state%column_local_x-2
104  y_prev = current_state%column_local_y-1
105 
106  c1 = 1.0_default_precision - 2.0_default_precision*current_state%tsmth
107  c2 = current_state%tsmth
108 
109 #ifdef U_ACTIVE
110  call step_single_field(current_state%column_local_x, current_state%column_local_y, &
111  x_prev, y_prev, current_state%u, current_state%zu, current_state%su, current_state%local_grid, .true., &
112  current_state%field_stepping, current_state%dtm, current_state%ugal, c1, c2, .false., current_state%savu)
113 #endif
114 #ifdef V_ACTIVE
115  call step_single_field(current_state%column_local_x, current_state%column_local_y, &
116  x_prev, y_prev, current_state%v, current_state%zv, current_state%sv, current_state%local_grid, .true., &
117  current_state%field_stepping, current_state%dtm, current_state%vgal, c1, c2, .false., current_state%savv)
118 #endif
119 #ifdef W_ACTIVE
120  call step_single_field(current_state%column_local_x, current_state%column_local_y, &
121  x_prev, y_prev, current_state%w, current_state%zw, current_state%sw, current_state%local_grid, .false., &
122  current_state%field_stepping, current_state%dtm, real(0., kind=DEFAULT_PRECISION), c1, c2, .false., current_state%savw)
123 #endif
124  if (current_state%th%active) then
125  call step_single_field(current_state%column_local_x, current_state%column_local_y, &
126  x_prev, y_prev, current_state%th, current_state%zth, current_state%sth, current_state%local_grid, .false., &
127  current_state%field_stepping, current_state%dtm, real(0., kind=DEFAULT_PRECISION), c1, c2, &
128  current_state%field_stepping == centred_stepping)
129  endif
130  do i=1,current_state%number_q_fields
131  if (current_state%q(i)%active) then
132  call step_single_field(current_state%column_local_x, current_state%column_local_y, x_prev, y_prev, &
133  current_state%q(i), current_state%zq(i), current_state%sq(i), current_state%local_grid, .false., &
134  current_state%field_stepping, current_state%dtm, real(0., kind=DEFAULT_PRECISION), c1, c2, &
135  current_state%field_stepping == centred_stepping)
136  end if
137  end do
138  end subroutine step_all_fields
139 
145  subroutine determine_local_flow_minmax(current_state, local_y, local_x)
146  type(model_state_type), target, intent(inout) :: current_state
147  integer, intent(in) :: local_x, local_y
148 
149  integer :: k
150 
151  do k=2, current_state%local_grid%local_domain_end_index(z_index)
152 #ifdef U_ACTIVE
153  current_state%local_zumax = max(current_state%local_zumax, current_state%zu%data(k,local_y,local_x))
154  current_state%local_zumin = min(current_state%local_zumin, current_state%zu%data(k,local_y,local_x))
155 #endif
156 #ifdef V_ACTIVE
157  current_state%local_zvmax = max(current_state%local_zvmax, current_state%zv%data(k,local_y,local_x))
158  current_state%local_zvmin = min(current_state%local_zvmin, current_state%zv%data(k,local_y,local_x))
159 #endif
160 #ifdef W_ACTIVE
161  if (k .lt. current_state%local_grid%local_domain_end_index(z_index)) then
162  current_state%abswmax(k) = max(current_state%abswmax(k), abs(current_state%zw%data(k,local_y,local_x)))
163  end if
164 #endif
165  end do
166  end subroutine determine_local_flow_minmax
167 
170  subroutine reset_local_minmax_values(current_state)
171  type(model_state_type), intent(inout), target :: current_state
172 
173  ! Reset the local values for the next timestep
174  current_state%local_zumin=rlargep
175  current_state%local_zumax=-rlargep
176  current_state%local_zvmin=rlargep
177  current_state%local_zvmax=-rlargep
178  current_state%abswmax=-rlargep
179  end subroutine reset_local_minmax_values
180 
189  subroutine remove_negative_rounding_errors_for_single_field(x_local_index, y_local_index, x_prev, y_prev, field, local_grid)
190  integer, intent(in) :: x_local_index, y_local_index, x_prev, y_prev
191  type(local_grid_type), intent(inout) :: local_grid
192  type(prognostic_field_type), intent(inout) :: field
193 
194  if (x_prev .ge. local_grid%local_domain_start_index(x_index)) then
195  call remove_negative_rounding_errors_in_slice(y_local_index, x_prev, y_prev, field, local_grid)
196  end if
197  if (x_local_index == local_grid%local_domain_end_index(x_index)) then
198  if (x_local_index .gt. 1) then
199  call remove_negative_rounding_errors_in_slice(y_local_index, x_local_index-1, y_prev, field, local_grid)
200  end if
201  call remove_negative_rounding_errors_in_slice(y_local_index, x_local_index, y_prev, field, local_grid)
202  end if
204 
212  subroutine remove_negative_rounding_errors_in_slice(y_local_index, x_prev, y_prev, field, local_grid)
213  integer, intent(in) :: y_local_index, x_prev, y_prev
214  type(local_grid_type), intent(inout) :: local_grid
215  type(prognostic_field_type), intent(inout) :: field
216 
217  if (y_prev .ge. local_grid%local_domain_start_index(y_index)) then
218  where (field%data(:, y_prev, x_prev) < 0.0_default_precision)
219  field%data(:, y_prev, x_prev)=0.0_default_precision
220  end where
221  end if
222  if (y_local_index == local_grid%local_domain_end_index(y_index)) then
223  where (field%data(:, y_local_index, x_prev) < 0.0_default_precision)
224  field%data(:, y_local_index, x_prev)=0.0_default_precision
225  end where
226  end if
228 
246  subroutine step_single_field(x_local_index, y_local_index, x_prev, y_prev, field, zfield, sfield, local_grid,&
247  flow_field, direction, dtm, gal, c1, c2, do_timesmoothing, sav)
248  integer, intent(in) :: x_local_index, y_local_index, x_prev, y_prev, direction
249  real(kind=DEFAULT_PRECISION), intent(in) :: dtm, gal
250  logical, intent(in) :: flow_field, do_timesmoothing
251  type(local_grid_type), intent(inout) :: local_grid
252  type(prognostic_field_type), intent(inout) :: field, zfield, sfield
253  real(kind=DEFAULT_PRECISION), intent(in) :: c1, c2
254  type(prognostic_field_type), optional, intent(inout) :: sav
255 
256  if (x_prev .ge. local_grid%local_domain_start_index(x_index)) then
257  if (present(sav)) then
258  call step_column_in_slice(y_local_index, x_prev, y_prev, field, zfield, sfield, local_grid, &
259  flow_field, direction, dtm, gal, c1, c2, do_timesmoothing, sav)
260  else
261  call step_column_in_slice(y_local_index, x_prev, y_prev, field, zfield, sfield, local_grid, &
262  flow_field, direction, dtm, gal, c1, c2, do_timesmoothing)
263  end if
264  end if
265 
266  if (x_local_index == local_grid%local_domain_end_index(x_index)) then
267  ! If this is the last slice then process x-1 (if applicable) and x too
268  if (x_local_index .gt. 1) then
269  if (present(sav)) then
270  call step_column_in_slice(y_local_index, x_local_index-1, y_prev, field, zfield, sfield, local_grid, &
271  flow_field, direction, dtm, gal, c1, c2, do_timesmoothing, sav)
272  else
273  call step_column_in_slice(y_local_index, x_local_index-1, y_prev, field, zfield, sfield, local_grid, &
274  flow_field, direction, dtm, gal, c1, c2, do_timesmoothing)
275  end if
276  end if
277  if (present(sav)) then
278  call step_column_in_slice(y_local_index, x_local_index, y_prev, field, zfield, sfield, local_grid, &
279  flow_field, direction, dtm, gal, c1, c2, do_timesmoothing, sav)
280  else
281  call step_column_in_slice(y_local_index, x_local_index, y_prev, field, zfield, sfield, local_grid, &
282  flow_field, direction, dtm, gal, c1, c2, do_timesmoothing)
283  end if
284  end if
285  end subroutine step_single_field
286 
295  subroutine perform_timesmooth_for_field(field, zfield, local_grid, x_index, y_index, c1, c2)
296  type(prognostic_field_type), intent(inout) :: field, zfield
297  type(local_grid_type), intent(inout) :: local_grid
298  integer, intent(in) :: x_index, y_index
299  real(kind=DEFAULT_PRECISION), intent(in) :: c1, c2
300 
301  integer :: k
302 
303  do k=1,local_grid%size(z_index)
304  field%data(k, y_index, x_index)=c1*field%data(k, y_index, x_index)+c2*zfield%data(k, y_index, x_index)
305  end do
306  end subroutine perform_timesmooth_for_field
307 
326  subroutine step_column_in_slice(y_local_index, x_prev, y_prev, field, zfield, sfield, local_grid,&
327  flow_field, direction, dtm, gal, c1, c2, do_timesmoothing, sav)
328  integer, intent(in) :: y_local_index, x_prev, y_prev, direction
329  real(kind=DEFAULT_PRECISION), intent(in) :: dtm, gal
330  logical, intent(in) :: flow_field, do_timesmoothing
331  type(local_grid_type), intent(inout) :: local_grid
332  type(prognostic_field_type), intent(inout) :: field, zfield, sfield
333  real(kind=DEFAULT_PRECISION), intent(in) :: c1, c2
334  type(prognostic_field_type), optional, intent(inout) :: sav
335 
336  if (y_prev .ge. local_grid%local_domain_start_index(y_index)) then
337  if (do_timesmoothing) then
338  call perform_timesmooth_for_field(field, zfield, local_grid, x_prev, y_prev, c1, c2)
339  end if
340  if (present(sav)) then
341  call step_field(x_prev, y_prev, field, zfield, sfield, local_grid, flow_field, direction, dtm, gal, sav)
342  else
343  call step_field(x_prev, y_prev, field, zfield, sfield, local_grid, flow_field, direction, dtm, gal)
344  end if
345  end if
346 
347  if (y_local_index == local_grid%local_domain_end_index(y_index)) then
348  if (do_timesmoothing) then
349  call perform_timesmooth_for_field(field, zfield, local_grid, x_prev, y_local_index, c1, c2)
350  end if
351  if (present(sav)) then
352  call step_field(x_prev, y_local_index, field, zfield, sfield, local_grid, flow_field, direction, dtm, gal, sav)
353  else
354  call step_field(x_prev, y_local_index, field, zfield, sfield, local_grid, flow_field, direction, dtm, gal)
355  end if
356  end if
357  end subroutine step_column_in_slice
358 
370  subroutine step_field(x_local_index, y_local_index, field, zfield, sfield, local_grid, flow_field, direction, dtm, gal, sav)
371  integer, intent(in) :: x_local_index, y_local_index, direction
372  real(kind=DEFAULT_PRECISION), intent(in) :: dtm, gal
373  logical, intent(in) :: flow_field
374  type(local_grid_type), intent(inout) :: local_grid
375  type(prognostic_field_type), intent(inout) :: field, zfield, sfield
376  type(prognostic_field_type), optional, intent(inout) :: sav
377 
378  integer :: k
379  real(kind=DEFAULT_PRECISION) :: actual_gal, dtm_x2
380 
381  dtm_x2 = 2.0_default_precision * dtm
382 
383  actual_gal = merge(gal, real(0.0_DEFAULT_PRECISION, kind=DEFAULT_PRECISION), flow_field)
384 
385  sfield%data(1,y_local_index, x_local_index)=0.0_default_precision
386 
387  do k=1,local_grid%size(z_index)
388  ! Save the Z field which is used in the Robert filter
389  if (present(sav) .and. direction .eq. centred_stepping) &
390  sav%data(k,y_local_index, x_local_index) = zfield%data(k, y_local_index, x_local_index) + actual_gal
391  if (flow_field) field%data(k, y_local_index, x_local_index) = actual_gal + field%data(k, y_local_index, x_local_index)
392  if (direction == forward_stepping) then
393  zfield%data(k, y_local_index, x_local_index) = field%data(k, y_local_index, x_local_index) + dtm * &
394  sfield%data(k, y_local_index, x_local_index)
395  else
396  zfield%data(k, y_local_index, x_local_index) = actual_gal+zfield%data(k, y_local_index, x_local_index)+dtm_x2*&
397  sfield%data(k, y_local_index, x_local_index)
398  end if
399  end do
400  end subroutine step_field
401 end module stepfields_mod
subroutine step_single_field(x_local_index, y_local_index, x_prev, y_prev, field, zfield, sfield, local_grid, flow_field, direction, dtm, gal, c1, c2, do_timesmoothing, sav)
Steps a single specific field. This will step on the yth column of the x-2 slice and x-1 and x if thi...
Definition: stepfields.F90:248
subroutine step_column_in_slice(y_local_index, x_prev, y_prev, field, zfield, sfield, local_grid, flow_field, direction, dtm, gal, c1, c2, do_timesmoothing, sav)
Will step a column in a specific slice. If y_prev is large enough then will step the y-1 column and i...
Definition: stepfields.F90:328
subroutine remove_negative_rounding_errors_in_slice(y_local_index, x_prev, y_prev, field, local_grid)
Removes the negative rounding errors from a slice of a single field. This works two columns behind an...
Definition: stepfields.F90:213
subroutine determine_local_flow_minmax(current_state, local_y, local_x)
Determines the minimum and maximum values for the local flow field. These are before the stepping...
Definition: stepfields.F90:146
real(kind=default_precision), public rlargep
integer, parameter, public forward_stepping
Definition: state.F90:15
logical cfl_is_enabled
Definition: stepfields.F90:17
real(kind=default_precision), dimension(:), allocatable resetq_min
Definition: stepfields.F90:20
Contains prognostic field definitions and functions.
Definition: prognostics.F90:2
A prognostic field which is assumed to be 3D.
Definition: prognostics.F90:13
logical l_nonconservative_positive_q
Definition: stepfields.F90:21
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 perform_timesmooth_for_field(field, zfield, local_grid, x_index, y_index, c1, c2)
Performs initial timesmoothing for a theta or Q field using Robert filter. This is finished off in sw...
Definition: stepfields.F90:296
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, parameter, public centred_stepping
Stepping parameter values which determine centred or forward stepping.
Definition: state.F90:15
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
type(component_descriptor_type) function, public stepfields_get_descriptor()
Provides the descriptor back to the caller and is used in component registration. ...
Definition: stepfields.F90:30
Scientific constant values used throughout simulations. Each has a default value and this can be over...
Interfaces and types that MONC components must specify.
Defined the local grid, i.e. the grid held on this process after decomposition.
Definition: grids.F90:111
subroutine step_field(x_local_index, y_local_index, field, zfield, sfield, local_grid, flow_field, direction, dtm, gal, sav)
Will do the actual field stepping.
Definition: stepfields.F90:371
subroutine reset_local_minmax_values(current_state)
Resets the local min and max values for the flow fields.
Definition: stepfields.F90:171
subroutine timestep_callback(current_state)
Called at each timestep and will perform swapping and smoothing as required.
Definition: stepfields.F90:59
logical determine_flow_minmax
Definition: stepfields.F90:17
subroutine initialisation_callback(current_state)
Initialisation callback.
Definition: stepfields.F90:40
subroutine remove_negative_rounding_errors_for_single_field(x_local_index, y_local_index, x_prev, y_prev, field, local_grid)
Removes the negative rounding errors from a specific single field. This works two columns behind and ...
Definition: stepfields.F90:190
Functionality to support the different types of grid and abstraction between global grids and local o...
Definition: grids.F90:5
subroutine finalisation_callback(current_state)
Finalisation callback.
Definition: stepfields.F90:51
Does the field stepping Stepping is called at the end of processing a column and steps the x-2 column...
Definition: stepfields.F90:3
The model state which represents the current state of a run.
Definition: state.F90:2
integer, parameter, public y_index
Definition: grids.F90:14
subroutine step_all_fields(current_state)
Steps all fields.
Definition: stepfields.F90:98
integer, parameter, public x_index
Definition: grids.F90:14
MONC component registry.
Definition: registry.F90:5