10 use atlas_module,
only: atlas_fieldset, atlas_field, atlas_real, atlas_integer, atlas_functionspace
11 use fckit_configuration_module,
only: fckit_configuration
12 use fckit_log_module,
only: fckit_log
13 use kinds,
only: kind_real
14 use oops_variables_mod,
only: oops_variables
15 use random_mod,
only: normal_distribution
16 use tools_func,
only: gau2gc
17 use type_bump,
only: bump_type
30 type(bump_type),
pointer :: conv(:)
32 type(oops_variables) :: vars
34 real(kind=kind_real),
allocatable :: pert_scale(:)
35 type(oops_variables),
allocatable :: conv_vars(:)
39 procedure :: setup => soca_cov_setup
42 procedure :: delete => soca_cov_delete
45 procedure :: mult => soca_cov_c_mult
48 procedure :: sqrt_c_mult => soca_cov_sqrt_c_mult
51 procedure :: getconv => soca_cov_get_conv
67 subroutine soca_cov_setup(self, f_conf, geom, bkg, vars)
68 class(
soca_cov),
intent(inout) :: self
69 type(fckit_configuration),
intent(in) :: f_conf
72 type(oops_variables),
intent(in) :: vars
74 type(fckit_configuration) :: f_conf2
75 type(fckit_configuration),
allocatable :: f_conf_list(:)
76 character(len=:),
allocatable :: domain_vars(:)
77 character(len=:),
allocatable :: domain
78 integer :: i, isc, iec, jsc, jec, ivar
84 allocate(self%pert_scale(self%vars%nvars()))
86 if (f_conf%get(
"perturbation scales", f_conf2))
then
87 do ivar=1,self%vars%nvars()
88 if ( .not. f_conf2%get(self%vars%variable(ivar), self%pert_scale(ivar)))
then
89 if (geom%f_comm%rank() == 0)
call fckit_log%warning( &
90 "WARNING: no pertubation scale given for '" //trim(self%vars%variable(ivar)) &
91 //
"' using default of 1.0")
100 isc = bkg%geom%isc ; iec = bkg%geom%iec
101 jsc = bkg%geom%jsc ; jec = bkg%geom%jec
104 call f_conf%get_or_die(
"bump", f_conf2)
105 call f_conf%get_or_die(
"correlation", f_conf_list)
106 allocate(self%conv(
size(f_conf_list)))
107 allocate(self%conv_vars(
size(self%conv)))
108 do i=1,
size(f_conf_list)
109 call f_conf_list(i)%get_or_die(
"name", domain)
110 call f_conf_list(i)%get_or_die(
"variables", domain_vars)
111 self%conv_vars(i) = oops_variables()
112 call self%conv_vars(i)%push_back(domain_vars)
114 call soca_bump_correlation(self, self%conv(i), geom, f_conf2, f_conf_list(i), domain)
117 end subroutine soca_cov_setup
124 subroutine soca_cov_delete(self)
125 class(
soca_cov),
intent(inout) :: self
127 deallocate(self%conv)
128 deallocate(self%conv_vars)
129 deallocate(self%pert_scale)
132 end subroutine soca_cov_delete
140 subroutine soca_cov_get_conv(self, field, conv)
141 class(
soca_cov),
intent(inout) :: self
142 type(
soca_field),
pointer,
intent(in) :: field
143 type(bump_type),
pointer,
intent(out) :: conv
148 if (field%metadata%grid /=
"h" )
then
149 call abor1_ftn(
"ERROR: cannot use fields on u/v grids" )
154 outer:
do j=1,
size(self%conv_vars)
155 do k=1,self%conv_vars(j)%nvars()
156 if (self%conv_vars(j)%variable(k) == field%name)
then
162 if ( .not.
associated(conv))
then
163 call abor1_ftn(
"ERROR: No valid bump operator found for field '"//field%name//
"'")
172 subroutine soca_cov_c_mult(self, dx)
173 class(
soca_cov),
intent(inout) :: self
177 type(bump_type),
pointer :: conv
179 do i = 1, self%vars%nvars()
181 if (.not. dx%has(self%vars%variable(i))) cycle
183 call dx%get(trim(self%vars%variable(i)), field)
186 if ( field%name ==
"hocn" ) cycle
189 call self%getConv(field, conv)
193 call soca_2d_convol(field%val(:,:,z), conv, dx%geom)
196 end subroutine soca_cov_c_mult
204 subroutine soca_cov_sqrt_c_mult(self, dx)
205 class(
soca_cov),
intent(inout) :: self
209 real(kind=kind_real) :: scale
210 type(bump_type),
pointer :: conv
212 do i = 1, self%vars%nvars()
214 call dx%get(trim(self%vars%variable(i)), field)
217 if ( field%name ==
"hocn" ) cycle
220 if (.not.
allocated(self%pert_scale))
then
221 call abor1_ftn(
"ERROR: cannot use sqrt_C_mult if no perturbation scales given")
223 do j=1,self%vars%nvars()
224 if (self%vars%variable(j) == field%name)
exit
226 scale = self%pert_scale(j)
229 call self%getConv(field, conv)
233 call soca_2d_sqrt_convol(field%val(:,:,z), conv, dx%geom, scale)
237 end subroutine soca_cov_sqrt_c_mult
251 subroutine soca_bump_correlation(self, horiz_convol, geom, f_conf_bump, f_conf_domain, domain)
252 class(
soca_cov),
intent(inout) :: self
253 type(bump_type),
intent(inout) :: horiz_convol
255 type(fckit_configuration),
intent(in) :: f_conf_bump, f_conf_domain
256 character(len=3),
intent(in) :: domain
259 integer,
pointer :: int_ptr_2(:,:)
260 real(kind=kind_real),
pointer :: real_ptr_1(:), real_ptr_2(:,:)
261 real(kind=kind_real),
allocatable :: lats(:), area(:)
262 type(atlas_functionspace) :: afunctionspace
263 type(atlas_fieldset) :: afieldset, rh, rv
264 type(atlas_field) :: afield
265 type(fckit_configuration) :: f_grid
266 real(kind=kind_real) :: r_base, r_mult, r_min, r_max, r_min_grid
270 f_grid = fckit_configuration()
271 call f_grid%set(
'prefix', domain)
272 call f_grid%set(
'nl', 1)
273 call f_grid%set(
'nv', 1)
274 call f_grid%set(
'variables', [
'var'])
277 afunctionspace = atlas_functionspace(geom%afunctionspace%c_ptr())
280 afieldset = atlas_fieldset()
282 lats = pack(geom%lat(geom%isc:geom%iec,geom%jsc:geom%jec),.true.)
285 afield = geom%afunctionspace%create_field(name=
'area', kind=atlas_real(kind_real), levels=0)
286 call afield%data(real_ptr_1)
287 area = pack(geom%cell_area(geom%isc:geom%iec,geom%jsc:geom%jec),.true.)
289 call afieldset%add(afield)
293 afield = geom%afunctionspace%create_field(name=
'vunit', kind=atlas_real(kind_real), levels=1)
294 call afield%data(real_ptr_2)
295 real_ptr_2(1,:) = 1.0
296 call afieldset%add(afield)
300 afield = geom%afunctionspace%create_field(name=
'gmask', kind=atlas_integer(kind(0)), levels=1)
301 call afield%data(int_ptr_2)
302 int_ptr_2(1,:) = int(pack(geom%mask2d(geom%isc:geom%iec,geom%jsc:geom%jec),.true.))
303 call afieldset%add(afield)
307 call horiz_convol%create(geom%f_comm,afunctionspace,afieldset,f_conf_bump,f_grid)
309 if (horiz_convol%nam%new_nicas)
then
311 if (.not. f_conf_domain%get(
'base value', r_base)) r_base = 0.0
312 if (.not. f_conf_domain%get(
'rossby mult', r_mult)) r_mult = 0.0
313 if (.not. f_conf_domain%get(
'min grid mult', r_min_grid)) r_min_grid = 1.0
314 if (.not. f_conf_domain%get(
'min value', r_min)) r_min = 0.0
315 if (.not. f_conf_domain%get(
'max value', r_max)) r_max = huge(r_max)
322 rh = atlas_fieldset()
323 afield = geom%afunctionspace%create_field(
'var',kind=atlas_real(kind_real),levels=0)
325 call afield%data(real_ptr_1)
326 real_ptr_1 = r_base + r_mult*pack(geom%rossby_radius(geom%isc:geom%iec,geom%jsc:geom%jec), .true.)
328 if (r_min_grid .gt. 0.0)
then
329 real_ptr_1 = max(real_ptr_1, sqrt(area)*r_min_grid )
331 real_ptr_1 = min(r_max, real_ptr_1)
332 real_ptr_1 = max(r_min, real_ptr_1)
333 real_ptr_1 = real_ptr_1 * gau2gc
338 rv = atlas_fieldset()
339 afield = geom%afunctionspace%create_field(
'var',kind=atlas_real(kind_real),levels=0)
341 call afield%data(real_ptr_1)
346 call horiz_convol%set_parameter(
'cor_rh', rh)
347 call horiz_convol%set_parameter(
'cor_rv', rv)
355 call horiz_convol%run_drivers()
357 end subroutine soca_bump_correlation
365 subroutine soca_2d_convol(dx, horiz_convol, geom)
366 real(kind=kind_real),
intent(inout) :: dx(:,:)
367 type(bump_type),
intent(inout) :: horiz_convol
370 type(atlas_fieldset) :: tmp_incr
373 call geom%struct2atlas(dx(:,:), tmp_incr)
376 call horiz_convol%apply_nicas(tmp_incr)
379 call geom%atlas2struct(dx(:,:), tmp_incr)
382 call tmp_incr%final()
384 end subroutine soca_2d_convol
392 subroutine soca_2d_sqrt_convol(dx, horiz_convol, geom, pert_scale)
393 real(kind=kind_real),
intent(inout) :: dx(:,:)
394 type(bump_type),
intent(inout) :: horiz_convol
396 real(kind=kind_real),
intent(in) :: pert_scale
398 type(atlas_fieldset) :: tmp_incr
399 real(kind=kind_real),
allocatable :: pcv(:)
400 integer,
parameter :: rseed = 1
405 call geom%struct2atlas(dx(:,:), tmp_incr)
408 call horiz_convol%get_cv_size(nn)
411 call normal_distribution(pcv, 0.0_kind_real, 1.0_kind_real, rseed)
412 pcv = pert_scale * pcv
415 call horiz_convol%apply_nicas_sqrt(pcv, tmp_incr)
418 call geom%atlas2struct(dx(:,:), tmp_incr)
422 call tmp_incr%final()
424 end subroutine soca_2d_sqrt_convol
Structure holding configuration variables for the 3d error covariance matrices of the SOCA analysis.
Handle fields for the model.
SOCA background/model covariance.
Holds all data and metadata related to a single field variable.