@@ -21,6 +21,9 @@ module skeb_main_alg_mod
2121 ! use collections
2222 use function_space_collection_mod, only: function_space_collection
2323 use mesh_collection_mod, only: mesh_collection
24+ ! Physical constants
25+ use planet_constants_mod, only: planet_radius
26+
2427 ! xios output and timers
2528 use io_config_mod, only: write_diag, use_xios_io
2629 use timing_mod, only: start_timing, stop_timing, tik, LPROF
@@ -38,8 +41,6 @@ module skeb_main_alg_mod
3841
3942 private
4043
41- ! Logical controlling whether spectral coeffs need calculating
42- logical(kind=l_def), save :: initialize_skeb_spectral_coeffs = .true.
4344 logical(kind=l_def ) :: du_rot_skeb_flag
4445 logical(kind=l_def ) :: dv_rot_skeb_flag
4546 logical(kind=l_def ) :: du_div_skeb_flag
@@ -56,7 +57,7 @@ module skeb_main_alg_mod
5657 real(kind=r_def), parameter :: TWOP_P1 = 2.0_r_def*P + 1.0_r_def
5758 real(kind=r_def), parameter :: FOUR_ON_VAR = 48.0_r_def
5859
59- public skeb_main_alg
60+ public skeb_main_alg, skeb_init_power_law
6061
6162 contains
6263 !>@brief Run the Stochastic Kinetic Energy Backscatter (SKEB)
@@ -87,13 +88,18 @@ module skeb_main_alg_mod
8788 !> 8) Add wind increments to the flow and diagnostics
8889 !>
8990 !> See UMD81 for full scheme details
90- !>@param[in] du_stph Stochastic Physics increments for winds
91- !>@param[in] rho Density on W3
92- !>@param[in] u prognostic winds in W2
93- !>@param[in] convection_fields Fields from convection scheme
94- !>@param[in] clock Model time information
95-
96- subroutine skeb_main_alg(du_stph, rho, u, convection_fields, derived_fields, clock)
91+ !>@param[in] du_stph Stochastic Physics increments for winds
92+ !>@param[in] rho Density on W3
93+ !>@param[in] u prognostic winds in W2
94+ !>@param[in] convection_fields Fields from convection scheme
95+ !>@param[in,out] skeb_spectral_coeffc Real Spectral coefficients
96+ !>@param[in,out] skeb_spectral_coeffs Imaginary Spectral coefficients
97+ !>@param[in,out] skeb_power_law Spectral power law
98+ !>@param[in] clock Model time information
99+
100+ subroutine skeb_main_alg(du_stph, rho, u, convection_fields, derived_fields, &
101+ skeb_spectral_coeffc, skeb_spectral_coeffs, &
102+ skeb_power_law, clock)
97103
98104 ! SKEB namelist options
99105 use stochastic_physics_config_mod, only: &
@@ -174,9 +180,6 @@ module skeb_main_alg_mod
174180 ! extract u and v from SKEB winds for diagnostics
175181 use physics_mappings_alg_mod, only: map_physics_winds
176182
177- ! Physical constants
178- use planet_constants_mod, only: planet_radius
179-
180183 use sci_enforce_upper_bound_kernel_mod, only: enforce_upper_bound_kernel_type
181184 use enforce_crit_kernel_mod, only: enforce_crit_kernel_type
182185
@@ -193,6 +196,11 @@ module skeb_main_alg_mod
193196 type( field_collection_type ), intent(in) :: convection_fields
194197 type( field_collection_type ), intent(in) :: derived_fields
195198
199+ ! Spectral coefficients
200+ real(r_def), intent(inout) :: skeb_spectral_coeffc(:)
201+ real(r_def), intent(inout) :: skeb_spectral_coeffs(:)
202+ real(r_def), intent(inout) :: skeb_power_law(:)
203+
196204 ! classes
197205 class(clock_type), intent(in) :: clock
198206
@@ -274,27 +282,22 @@ module skeb_main_alg_mod
274282 !w2 intermediate field for scaling by cos(lat)
275283 type( field_type ) :: field_w2
276284
277- ! Spectral coefficients
278- real(kind=r_def), allocatable, save :: skeb_spectral_coeffc(:)
279- real(kind=r_def), allocatable, save :: skeb_spectral_coeffs(:)
280- real(kind=r_def), allocatable, save :: skeb_power_law(:)
281-
282285 ! time decorrelation parameter
283- real(kind=r_def), save :: skeb_alpha
286+ real(kind=r_def) :: skeb_alpha
284287
285288 ! Convective resolution factor to modulate conv mask
286289 real(kind=r_def) :: convective_resolution_factor
287290
288291 ! scaling total dissipation by br/total_backscatter
289292 real(kind=r_def) :: factor_psif, max_backscatter, crit_backscatter
290293 ! parameters for the power law and decorrelation time alpha
291- real(kind=r_def) :: gamma, dt, spl_coeff
294+ real(kind=r_def) :: dt
292295
293296 ! mesh_id
294297 integer(kind=i_def) :: mesh_id
295298
296299 ! Iterators in for loops
297- integer(i_def) :: m, n, n_row , stencil_extent
300+ integer(i_def) :: n , stencil_extent
298301
299302 ! SKEB calculations are performed at cell centres (W3 points). To index the
300303 ! "eta_theta_levels" array correctly at these points, set offset to 1
@@ -325,66 +328,13 @@ module skeb_main_alg_mod
325328 setval_c(fp_skeb, 0.0_r_def) )
326329
327330 dt = real(clock%get_seconds_per_step(), r_def)
331+ skeb_alpha=1-exp(-dt/skeb_decorrelation_time)
328332
329333 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
330334 !! 1) Create Forcing Pattern !!
331335 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
332336
333- ! Initialize spectral coefficients for the forcing pattern
334- if (initialize_skeb_spectral_coeffs) then
335-
336- !allocate spectral coefficients and power law
337- allocate(skeb_spectral_coeffc(stph_spectral_dim))
338- allocate(skeb_spectral_coeffs(stph_spectral_dim))
339- allocate(skeb_power_law(stph_spectral_dim))
340-
341- ! set them to zero (invokes don't work for non-fields types)
342- skeb_spectral_coeffc = 0.0_r_def
343- skeb_spectral_coeffs = 0.0_r_def
344- skeb_power_law = 0.0_r_def
345-
346- !!!!!! 1.a compute power law
347-
348- ! compute alpha for temporal decorrelation
349- skeb_alpha=1-exp(-dt/skeb_decorrelation_time)
350-
351- ! This power law is what Glenn Shutts observed in the CRM simulations
352- ! (see Berner et al., 2009: J. Atmos. Sci, pp 603-626)
353- gamma = 0.0_r_def
354- do n = stph_n_min, stph_n_max
355- gamma = gamma + (n+1)*(2*n+1)*n**(TWOP_P1)
356- end do
357- gamma = gamma/skeb_alpha
358-
359- ! Below we calculate the power law which is given as
360- ! g(n) = spl_coeff * n^p
361- ! where
362- ! spl_coeff = SQRT([4 * Pi * a^2 * skeb_total_backscatter]/[dt * var * gamma])
363- ! var is the variance of random numbers [-0.5; 0.5] = 1/12
364- ! tested by 1000 cases of random arrays of size = 1e9
365- ! note: (4/var) is pre-calculated as FOUR_ON_VAR = 48
366-
367- ! Set n_row as the summatory of n
368- n_row = 0
369- ! add up those scales below the minimum wavenumber to the
370- ! row iterator
371- do n = 1, stph_n_min-1
372- n_row = n_row + n
373- end do
374-
375- ! Build power law
376- spl_coeff = planet_radius * sqrt(FOUR_ON_VAR*pi*skeb_total_backscatter/ &
377- (dt*gamma))
378- do n = stph_n_min, stph_n_max
379- n_row = n_row + n
380- do m = 0, n
381- skeb_power_law(n_row + m) = spl_coeff * n**P
382- end do
383- end do
384- initialize_skeb_spectral_coeffs = .false.
385- end if
386-
387- !!!!!! 1.b call stph_fp_main to create forcing pattern for SKEB
337+ !!!!!! Create forcing pattern for SKEB
388338 call stph_fp_main_alg(skeb_level_bottom-1_i_def, skeb_level_top-1_i_def, &
389339 lev_offset, stph_n_min, stph_n_max, stph_spectral_dim, &
390340 skeb_alpha, skeb_power_law, &
@@ -701,4 +651,64 @@ module skeb_main_alg_mod
701651 end if ! end if write_diags and use_xios
702652
703653 end subroutine skeb_main_alg
654+
655+ ! Initialise the power law array
656+ ! @param[out] skeb_power_law Power law array
657+ ! @param[in] clock Model clock
658+ subroutine skeb_init_power_law(skeb_power_law, clock)
659+ use stochastic_physics_config_mod, only: skeb_decorrelation_time, &
660+ skeb_total_backscatter, &
661+ stph_n_min, stph_n_max
662+
663+ real(r_def), intent(out) :: skeb_power_law(:)
664+ class(clock_type), intent(in) :: clock
665+
666+ ! time decorrelation parameter
667+ real(kind=r_def) :: skeb_alpha
668+ real(kind=r_def) :: gamma, dt, spl_coeff
669+
670+ ! Iterators in for loops
671+ integer(i_def) :: m, n, n_row
672+
673+ skeb_power_law = 0.0_r_def
674+
675+ ! compute alpha for temporal decorrelation
676+ dt = real(clock%get_seconds_per_step(), r_def)
677+ skeb_alpha=1-exp(-dt/skeb_decorrelation_time)
678+
679+ ! This power law is what Glenn Shutts observed in the CRM simulations
680+ ! (see Berner et al., 2009: J. Atmos. Sci, pp 603-626)
681+ gamma = 0.0_r_def
682+ do n = stph_n_min, stph_n_max
683+ gamma = gamma + (n+1)*(2*n+1)*n**(TWOP_P1)
684+ end do
685+ gamma = gamma/skeb_alpha
686+
687+ ! Below we calculate the power law which is given as
688+ ! g(n) = spl_coeff * n^p
689+ ! where
690+ ! spl_coeff = SQRT([4 * Pi * a^2 * skeb_total_backscatter]/[dt * var * gamma])
691+ ! var is the variance of random numbers [-0.5; 0.5] = 1/12
692+ ! tested by 1000 cases of random arrays of size = 1e9
693+ ! note: (4/var) is pre-calculated as FOUR_ON_VAR = 48
694+
695+ ! Set n_row as the summatory of n
696+ n_row = 0
697+ ! add up those scales below the minimum wavenumber to the
698+ ! row iterator
699+ do n = 1, stph_n_min-1
700+ n_row = n_row + n
701+ end do
702+
703+ ! Build power law
704+ spl_coeff = planet_radius * sqrt(FOUR_ON_VAR*pi*skeb_total_backscatter/ &
705+ (dt*gamma))
706+ do n = stph_n_min, stph_n_max
707+ n_row = n_row + n
708+ do m = 0, n
709+ skeb_power_law(n_row + m) = spl_coeff * n**P
710+ end do
711+ end do
712+
713+ end subroutine skeb_init_power_law
704714end module skeb_main_alg_mod
0 commit comments