8 use fckit_configuration_module,
only: fckit_configuration
9 use fms_io_mod,
only: fms_io_init, fms_io_exit
10 use fms_mod,
only: read_data
11 use kinds,
only: kind_real
33 real(kind=kind_real),
private,
allocatable :: kct(:,:)
38 procedure :: setup => soca_balance_setup
41 procedure :: delete => soca_balance_delete
44 procedure :: mult => soca_balance_mult
47 procedure :: multad => soca_balance_multad
50 procedure :: multinv => soca_balance_multinv
53 procedure :: multinvad => soca_balance_multinvad
69 subroutine soca_balance_setup(self, f_conf, traj, geom)
71 type(fckit_configuration),
intent(in) :: f_conf
73 type(
soca_geom),
target,
intent(in) :: geom
75 integer :: isc, iec, jsc, jec
76 integer :: isd, ied, jsd, jed
77 integer :: i, j, k, nl
78 real(kind=kind_real),
allocatable :: jac(:)
79 type(
soca_field),
pointer :: tocn, socn, hocn, cicen, mld, layer_depth
82 character(len=:),
allocatable :: filename, mask_name
83 real(kind=kind_real),
allocatable :: jac_mask(:,:)
84 real(kind=kind_real) :: threshold
86 logical :: mask_detadt = .false.
87 logical :: mask_detads = .false.
90 character(len=:),
allocatable :: kct_name
91 real(kind=kind_real),
allocatable :: kct(:,:)
96 isc=geom%isc; iec=geom%iec
97 jsc=geom%jsc; jec=geom%jec
98 isd=geom%isd; ied=geom%ied
99 jsd=geom%jsd; jed=geom%jed
102 allocate(jac_mask(isd:ied,jsd:jed))
103 jac_mask = 1.0_kind_real
104 nlayers = 0.0_kind_real
105 if ( f_conf%has(
"jac_mask") )
then
106 jac_mask = 0.0_kind_real
107 call f_conf%get_or_die(
"jac_mask.filename", filename)
108 call f_conf%get_or_die(
"jac_mask.name", mask_name)
109 call f_conf%get_or_die(
"jac_mask.threshold", threshold)
110 call f_conf%get_or_die(
"jac_mask.nlayers", nlayers)
111 call f_conf%get_or_die(
"jac_mask.detadt", mask_detadt)
112 call f_conf%get_or_die(
"jac_mask.detads", mask_detads)
114 call read_data(filename, mask_name, jac_mask, domain=geom%Domain%mpp_domain)
116 where(jac_mask<threshold)
117 jac_mask = 0.0_kind_real
122 call f_conf%get_or_die(
"dsdtmax", self%kst%dsdtmax)
123 call f_conf%get_or_die(
"dsdzmin", self%kst%dsdzmin)
124 call f_conf%get_or_die(
"dtdzmin", self%kst%dtdzmin)
125 call f_conf%get_or_die(
"nlayers", self%kst%nlayers)
129 call traj%get(
"tocn", tocn)
130 call traj%get(
"socn", socn)
131 call traj%get(
"hocn", hocn)
132 call traj%get(
"mld", mld)
133 call traj%get(
"layer_depth", layer_depth)
134 if (traj%has(
"cicen"))
call traj%get(
"cicen", cicen)
138 allocate(self%kst%jacobian(isc:iec,jsc:jec,geom%nzo))
140 self%kst%jacobian=0.0
146 call soca_soft_jacobian(jac,&
150 &self%kst%dsdtmax, self%kst%dsdzmin, self%kst%dtdzmin)
153 if (layer_depth%val(i,j,k) < mld%val(i,j,1))
then
154 jac(k) = 0.0_kind_real
157 self%kst%jacobian(i,j,:) = jac(:)
158 self%kst%jacobian(i,j,1:self%kst%nlayers) = 0.0_kind_real
164 allocate(self%ksshts%kssht, mold=self%kst%jacobian)
165 allocate(self%ksshts%ksshs, mold=self%kst%jacobian)
167 self%ksshts%kssht=0.0_kind_real
168 self%ksshts%ksshs=0.0_kind_real
172 call soca_steric_jacobian (jac, &
175 &layer_depth%val(i,j,k),&
179 self%ksshts%kssht(i,j,k) = jac(1)*jac_mask(i,j)
180 self%ksshts%ksshs(i,j,k) = jac(2)*jac_mask(i,j)
183 self%ksshts%kssht(i,j,1:nlayers) = 0.0_kind_real
184 self%ksshts%ksshs(i,j,1:nlayers) = 0.0_kind_real
191 if (mask_detadt) self%ksshts%kssht = 0.0_kind_real
192 if (mask_detads) self%ksshts%ksshs = 0.0_kind_real
195 if (traj%has(
"cicen"))
then
197 allocate(kct(isd:ied,jsd:jed))
199 if ( f_conf%has(
"dcdt") )
then
200 call f_conf%get_or_die(
"dcdt.filename", filename)
201 call f_conf%get_or_die(
"dcdt.name", kct_name)
203 call read_data(filename, kct_name, kct, domain=geom%Domain%mpp_domain)
206 allocate(self%kct(isc:iec,jsc:jec))
207 self%kct = 0.0_kind_real
210 if (sum(cicen%val(i,j,:)) > 1.0e-3_kind_real)
then
217 end subroutine soca_balance_setup
224 subroutine soca_balance_delete(self)
228 deallocate(self%kst%jacobian)
229 deallocate(self%ksshts%kssht)
230 deallocate(self%ksshts%ksshs)
233 if (
allocated(self%kct))
deallocate(self%kct)
234 end subroutine soca_balance_delete
241 subroutine soca_balance_mult(self, dxa, dxm)
249 integer :: i, j, k, n
256 call dxa%get(
"tocn",tocn_a)
257 call dxa%get(
"socn",socn_a)
259 do n=1,
size(dxm%fields)
260 fld_m => dxm%fields(n)
261 fld_a => dxa%fields(n)
263 do i = self%geom%isc, self%geom%iec
264 do j = self%geom%jsc, self%geom%jec
265 select case(fld_m%name)
267 fld_m%val(i,j,:) = fld_a%val(i,j,:)
270 fld_m%val(i,j,:) = fld_a%val(i,j,:) + &
271 & self%kst%jacobian(i,j,:) * tocn_a%val(i,j,:)
274 fld_m%val(i,j,:) = fld_a%val(i,j,:)
276 fld_m%val(i,j,:) = fld_m%val(i,j,:) + &
277 & self%ksshts%kssht(i,j,k) * tocn_a%val(i,j,k) + &
278 & self%ksshts%ksshs(i,j,k) * socn_a%val(i,j,k)
283 fld_m%val(i,j,k) = fld_a%val(i,j,k) + &
284 & self%kct(i,j) * tocn_a%val(i,j,1)
291 end subroutine soca_balance_mult
298 subroutine soca_balance_multad(self, dxa, dxm)
304 type(
soca_field),
pointer :: socn_m, ssh_m, cicen_m
309 call dxm%get(
"socn", socn_m)
310 call dxm%get(
"ssh", ssh_m)
311 if (dxm%has(
"cicen"))
call dxm%get(
"cicen",cicen_m)
313 do n = 1,
size(dxa%fields)
314 fld_a => dxa%fields(n)
315 fld_m => dxm%fields(n)
317 do i = self%geom%isc, self%geom%iec
318 do j = self%geom%jsc, self%geom%jec
319 select case(fld_a%name)
321 fld_a%val(i,j,:) = fld_m%val(i,j,:)
324 fld_a%val(i,j,:) = fld_m%val(i,j,:) + &
325 & self%kst%jacobian(i,j,:) * socn_m%val(i,j,:) + &
326 & self%ksshts%kssht(i,j,:) * ssh_m%val(i,j,1)
328 if (
associated(cicen_m))
then
329 fld_a%val(i,j,1) = fld_a%val(i,j,1) + &
330 & self%kct(i,j) * sum(cicen_m%val(i,j,:))
334 fld_a%val(i,j,:) = fld_m%val(i,j,:) + &
335 & self%ksshts%ksshs(i,j,:) * ssh_m%val(i,j, 1)
341 end subroutine soca_balance_multad
348 subroutine soca_balance_multinv(self, dxa, dxm)
353 integer :: i, j, k, n
357 call dxm%get(
"tocn", tocn_m)
358 call dxm%get(
"socn", socn_m)
360 do n = 1,
size(dxa%fields)
361 fld_a => dxa%fields(n)
362 fld_m => dxm%fields(n)
364 do i = self%geom%isc, self%geom%iec
365 do j = self%geom%jsc, self%geom%jec
366 select case(fld_a%name)
368 fld_a%val(i,j,:) = fld_m%val(i,j,:)
371 fld_a%val(i,j,:) = fld_m%val(i,j,:) - &
372 & self%kst%jacobian(i,j,:) * tocn_m%val(i,j,:)
375 fld_a%val(i,j, :) = fld_m%val(i,j, :)
377 fld_a%val(i,j,:) = fld_a%val(i,j,:) + &
378 & ( self%ksshts%ksshs(i,j,k) * self%kst%jacobian(i,j,k) - &
379 & self%ksshts%kssht(i,j,k) ) * tocn_m%val(i,j,k) - &
380 & self%ksshts%ksshs(i,j,k) * socn_m%val(i,j,k)
384 fld_a%val(i,j,:) = fld_m%val(i,j,:)
386 fld_a%val(i,j,k) = fld_a%val(i,j,k) - &
387 & self%kct(i,j) * tocn_m%val(i,j,1)
394 end subroutine soca_balance_multinv
401 subroutine soca_balance_multinvad(self, dxa, dxm)
408 type(
soca_field),
pointer :: socn_a, ssh_a, cicen_a
412 call dxa%get(
"socn", socn_a)
413 call dxa%get(
"ssh", ssh_a)
414 if (dxa%has(
"cicen"))
call dxa%get(
"cicen",cicen_a)
416 do n = 1,
size(dxm%fields)
417 fld_m => dxm%fields(n)
418 fld_a => dxa%fields(n)
420 do i = self%geom%isc, self%geom%iec
421 do j = self%geom%jsc, self%geom%jec
422 select case (fld_m%name)
424 fld_m%val(i,j,:) = fld_a%val(i,j,:)
427 fld_m%val(i,j,:) = fld_a%val(i,j,:) &
428 & - self%kst%jacobian(i,j,:) * socn_a%val(i,j,:) &
429 & + ( self%ksshts%ksshs(i,j,:) * self%kst%jacobian(i,j,:) &
430 & - self%ksshts%kssht(i,j,:) ) * ssh_a%val(i,j,1)
432 if (
associated(cicen_a))
then
433 fld_m%val(i,j,1) = fld_m%val(i,j,1) &
434 & - self%kct(i,j) * sum(cicen_a%val(i,j,:))
438 fld_m%val(i,j,:) = fld_a%val(i,j,:) - &
439 & self%ksshts%ksshs(i,j,:) * ssh_a%val(i,j,1)
445 end subroutine soca_balance_multinvad
Handle fields for the model.
variable transform: SSH balance
variable transform: S/T balance
Variable transform for the balance operators (K)
Holds all data and metadata related to a single field variable.
Hold the jacobians for the ssh to s/t balance transform.
Hold the configuration and jacobians for the s/t balance transform.