10 use fckit_exception_module,
only: fckit_exception
11 use kinds,
only: kind_real
14 use fms_io_mod,
only: read_data, fms_io_init, fms_io_exit
15 use horiz_interp_mod,
only : horiz_interp_new, horiz_interp, horiz_interp_type
16 use mom_domains,
only : pass_var, root_pe, sum_across_pes
17 use mom_error_handler,
only : is_root_pe
18 use mom_grid,
only : ocean_grid_type
19 use mom_horizontal_regridding,
only : meshgrid, fill_miss_2d
20 use mom_remapping,
only : remapping_cs, initialize_remapping, remapping_core_h
21 use mpp_domains_mod,
only : mpp_global_field, mpp_update_domains
22 use mpp_mod,
only : mpp_broadcast, mpp_sync, mpp_sync_self
34 real(kind=kind_real),
allocatable,
dimension(:,:,:),
private :: hocn_src, hocn_des
38 procedure :: setup => soca_convertstate_setup
41 procedure :: change_resol => soca_convertstate_change_resol
44 procedure :: change_resol2d => soca_convertstate_change_resol2d
47 procedure :: clean => soca_convertstate_delete
60 subroutine soca_convertstate_setup(self, src, des, hocn, hocn2)
72 call read_data(trim(src%geom_grid_file),
'nzo_zstar', tmp(1), domain=src%Domain%mpp_domain)
73 src%nzo_zstar = tmp(1)
75 call read_data(trim(des%geom_grid_file),
'nzo_zstar', tmp(1), domain=des%Domain%mpp_domain)
76 des%nzo_zstar = tmp(1)
78 if (des%nzo_zstar /= src%nzo_zstar)
call fckit_exception%abort(&
79 "target nzo_zstar /= source nzo_zstar! Reset maximum depth in target grid MOM_input file and re-run soca gridgen")
82 if (
allocated(src%h_zstar))
deallocate(src%h_zstar)
83 allocate(src%h_zstar(src%isd:src%ied,src%jsd:src%jed,1:src%nzo_zstar))
84 call read_data(trim(src%geom_grid_file),
'h_zstar', src%h_zstar, domain=src%Domain%mpp_domain)
86 if (
allocated(des%h_zstar))
deallocate(des%h_zstar)
87 allocate(des%h_zstar(des%isd:des%ied,des%jsd:des%jed,1:des%nzo_zstar))
88 call read_data(trim(des%geom_grid_file),
'h_zstar', des%h_zstar, domain=des%Domain%mpp_domain)
92 allocate(self%hocn_src(src%isd:src%ied,src%jsd:src%jed,1:src%nzo))
93 allocate(self%hocn_des(des%isd:des%ied,des%jsd:des%jed,1:des%nzo))
97 self%hocn_src = hocn%val
98 self%hocn_des = hocn2%val
100 end subroutine soca_convertstate_setup
107 subroutine soca_convertstate_delete(self)
110 deallocate(self%hocn_src)
111 deallocate(self%hocn_des)
113 end subroutine soca_convertstate_delete
120 subroutine soca_convertstate_change_resol2d(self, field_src, field_des, geom_src, geom_des)
122 type(
soca_field),
pointer,
intent(inout) :: field_src
123 type(
soca_field),
pointer,
intent(inout) :: field_des
124 type(
soca_geom),
intent(inout) :: geom_src
125 type(
soca_geom),
intent(inout) :: geom_des
128 integer :: i, j, k, tmp_nz, nz_
129 integer :: isc1, iec1, jsc1, jec1, isd1, ied1, jsd1, jed1, isg, ieg, jsg, jeg
130 integer :: isc2, iec2, jsc2, jec2, isd2, ied2, jsd2, jed2
131 type(remapping_cs) :: remapCS2
132 type(horiz_interp_type) :: Interp
133 real(kind=kind_real) :: missing = 0.d0
134 real(kind=kind_real) :: z_tot
135 real(kind=kind_real),
dimension(geom_src%isg:geom_src%ieg) :: lon_in
136 real(kind=kind_real),
dimension(geom_src%jsg:geom_src%jeg) :: lat_in
137 real(kind=kind_real),
dimension(geom_des%isd:geom_des%ied,geom_des%jsd:geom_des%jed) :: lon_out, lat_out
138 real(kind=kind_real),
dimension(geom_des%isd:geom_des%ied,geom_des%jsd:geom_des%jed) :: mask_
139 real(kind=kind_real),
allocatable :: tmp(:,:,:), tmp2(:,:,:), gdata(:,:,:)
142 isc1 = geom_src%isc ; iec1 = geom_src%iec ; jsc1 = geom_src%jsc ; jec1 = geom_src%jec
143 isd1 = geom_src%isd ; ied1 = geom_src%ied ; jsd1 = geom_src%jsd ; jed1 = geom_src%jed
144 isg = geom_src%isg ; ieg = geom_src%ieg ; jsg = geom_src%jsg ; jeg = geom_src%jeg
147 isc2 = geom_des%isc ; iec2 = geom_des%iec ; jsc2 = geom_des%jsc ; jec2 = geom_des%jec
148 isd2 = geom_des%isd ; ied2 = geom_des%ied ; jsd2 = geom_des%jsd ; jed2 = geom_des%jed
150 lon_in = geom_src%lonh ; lat_in = geom_src%lath
151 if (field_src%name ==
"uocn" .and. field_des%name ==
"uocn") lon_in = geom_src%lonq
152 if (field_src%name ==
"vocn" .and. field_des%name ==
"vocn") lat_in = geom_src%latq
156 allocate(tmp(isd1:ied1,jsd1:jed1,1:nz_),gdata(isg:ieg,jsg:jeg,1:nz_),tmp2(isd2:ied2,jsd2:jed2,1:nz_))
157 tmp = 0.d0 ; gdata = 0.d0 ; tmp2 = 0.d0;
158 tmp(:,:,1:nz_) = field_src%val(:,:,1:nz_)
161 call mpp_update_domains(tmp, geom_src%Domain%mpp_domain)
162 mask_ = field_des%mask
163 call mpp_global_field (geom_src%Domain%mpp_domain, tmp(:,:,1:nz_), gdata(:,:,1:nz_) )
166 call soca_hinterp(geom_des,field_des%val,gdata,mask_(:,:),nz_,missing,lon_in,lat_in,field_des%lon,field_des%lat)
169 call mpp_update_domains(field_des%val, geom_des%Domain%mpp_domain)
171 end subroutine soca_convertstate_change_resol2d
178 subroutine soca_convertstate_change_resol(self, field_src, field_des, geom_src, geom_des)
180 type(
soca_field),
pointer,
intent(inout) :: field_src
181 type(
soca_field),
pointer,
intent(inout) :: field_des
182 type(
soca_geom),
intent(inout) :: geom_src
183 type(
soca_geom),
intent(inout) :: geom_des
186 integer :: i, j, k, tmp_nz, nz_
187 integer :: isc1, iec1, jsc1, jec1, isd1, ied1, jsd1, jed1, isg, ieg, jsg, jeg
188 integer :: isc2, iec2, jsc2, jec2, isd2, ied2, jsd2, jed2
189 type(remapping_cs) :: remapCS2
190 type(horiz_interp_type) :: Interp
191 real(kind=kind_real) :: missing = 0.d0
192 real(kind=kind_real) :: pi_180, z_tot
193 real(kind=kind_real),
dimension(geom_src%isg:geom_src%ieg) :: lon_in
194 real(kind=kind_real),
dimension(geom_src%jsg:geom_src%jeg) :: lat_in
195 real(kind=kind_real),
dimension(geom_des%isd:geom_des%ied,geom_des%jsd:geom_des%jed) :: lon_out, lat_out
196 real(kind=kind_real),
dimension(geom_des%isd:geom_des%ied,geom_des%jsd:geom_des%jed) :: mask_
197 real(kind=kind_real),
allocatable :: tmp(:,:,:), tmp2(:,:,:), gdata(:,:,:)
198 real(kind=kind_real),
allocatable :: h1(:), h2(:)
199 real(kind=kind_real),
dimension(geom_src%isd:geom_src%ied,geom_src%jsd:geom_src%jed,1:geom_src%nzo_zstar) :: h_new1
200 real(kind=kind_real),
dimension(geom_des%isd:geom_des%ied,geom_des%jsd:geom_des%jed,1:geom_des%nzo_zstar) :: h_new2
202 pi_180=atan(1.0d0)/45.0d0
205 isc1 = geom_src%isc ; iec1 = geom_src%iec ; jsc1 = geom_src%jsc ; jec1 = geom_src%jec
206 isd1 = geom_src%isd ; ied1 = geom_src%ied ; jsd1 = geom_src%jsd ; jed1 = geom_src%jed
207 isg = geom_src%isg ; ieg = geom_src%ieg ; jsg = geom_src%jsg ; jeg = geom_src%jeg
210 isc2 = geom_des%isc ; iec2 = geom_des%iec ; jsc2 = geom_des%jsc ; jec2 = geom_des%jec
211 isd2 = geom_des%isd ; ied2 = geom_des%ied ; jsd2 = geom_des%jsd ; jed2 = geom_des%jed
214 call initialize_remapping(remapcs2,
'PPM_IH4')
217 if (field_des%metadata%io_file==
"ocn".or.field_des%metadata%io_file==
'ice')
then
218 mask_ = field_des%mask
219 h_new1(isc1:iec1,jsc1:jec1,1:geom_src%nzo_zstar) = geom_src%h_zstar(isc1:iec1,jsc1:jec1,1:geom_src%nzo_zstar)
220 h_new2(isc2:iec2,jsc2:jec2,1:geom_des%nzo_zstar) = geom_des%h_zstar(isc2:iec2,jsc2:jec2,1:geom_des%nzo_zstar)
221 call mpp_update_domains(mask_, geom_des%Domain%mpp_domain)
222 call mpp_update_domains(h_new1, geom_src%Domain%mpp_domain)
223 call mpp_update_domains(h_new2, geom_des%Domain%mpp_domain)
229 if (field_des%name ==
"hocn" )
then
232 lon_in = geom_src%lonh ; lat_in = geom_src%lath
233 if (field_src%name ==
"uocn" .and. field_des%name ==
"uocn") lon_in = geom_src%lonq
234 if (field_src%name ==
"vocn" .and. field_des%name ==
"vocn") lat_in = geom_src%latq
240 nz_ = geom_src%nzo_zstar
241 if (field_src%nz == 1 .or. field_src%metadata%io_file==
"ice") nz_ = field_src%nz
242 allocate(tmp(isd1:ied1,jsd1:jed1,1:nz_),gdata(isg:ieg,jsg:jeg,1:nz_),tmp2(isd2:ied2,jsd2:jed2,1:nz_))
243 allocate(h1(field_src%nz),h2(nz_))
244 tmp = 0.d0 ; gdata = 0.d0 ; tmp2 = 0.d0;
245 if ( field_src%nz > 1 .and. field_src%metadata%io_file/=
"ice")
then
248 tmp_nz = field_src%nz
249 if(field_src%name ==
"uocn")
then
250 if (field_src%mask(i,j)>0.)
then
251 h1(1:tmp_nz) = 0.5 * ( self%hocn_src(i,j,1:tmp_nz) + self%hocn_src(i+1,j,1:tmp_nz) )
252 h2(1:nz_) = 0.5 * ( h_new1(i,j,1:nz_) + h_new1(i+1,j,1:nz_) )
253 call remapping_core_h(remapcs2, tmp_nz, h1(1:tmp_nz), field_src%val(i,j,1:tmp_nz), &
254 nz_, h2(1:nz_), tmp(i,j,1:nz_))
256 else if(field_src%name ==
"vocn")
then
257 if (field_src%mask(i,j)>0.)
then
258 h1(1:tmp_nz) = 0.5 * ( self%hocn_src(i,j,1:tmp_nz) + self%hocn_src(i,j+1,1:tmp_nz) )
259 h2(1:nz_) = 0.5 * ( h_new1(i,j,1:nz_) + h_new1(i,j+1,1:nz_) )
260 call remapping_core_h(remapcs2, tmp_nz, h1(1:tmp_nz), field_src%val(i,j,1:tmp_nz), &
261 nz_, h2(1:nz_), tmp(i,j,1:nz_))
264 if (field_src%mask(i,j) > 0.d0)
then
265 call remapping_core_h(remapcs2, tmp_nz, self%hocn_src(i,j,1:tmp_nz), field_src%val(i,j,1:tmp_nz), &
266 nz_, h_new1(i,j,1:nz_), tmp(i,j,1:nz_))
272 if (field_src%metadata%io_file==
"ocn") tmp(:,:,1) = field_src%val(:,:,1)
273 if (field_src%metadata%io_file==
"sfc") tmp(:,:,1) = field_src%val(:,:,1)
274 if (field_src%metadata%io_file==
"ice") tmp(:,:,1:nz_) = field_src%val(:,:,1:nz_)
276 call mpp_update_domains(tmp, geom_src%Domain%mpp_domain)
279 call mpp_global_field (geom_src%Domain%mpp_domain, tmp(:,:,1:nz_), gdata(:,:,1:nz_) )
280 call soca_hinterp(geom_des,tmp2(:,:,1:nz_),gdata,mask_(:,:),nz_,missing,lon_in,lat_in,field_des%lon,field_des%lat)
282 call mpp_update_domains(tmp2, geom_des%Domain%mpp_domain)
285 if(
allocated(h1))
deallocate(h1)
286 if(
allocated(h2))
deallocate(h2)
287 allocate(h1(nz_),h2(field_des%nz))
288 if ( field_des%nz > 1 .and. field_des%metadata%io_file/=
"ice")
then
292 if(field_des%name ==
"uocn")
then
293 if (field_des%mask(i,j)>0.)
then
294 h1(1:tmp_nz) = 0.5 * ( h_new2(i,j,1:tmp_nz) + h_new2(i+1,j,1:tmp_nz) )
295 h2(1:field_des%nz) = 0.5 * ( self%hocn_des(i,j,1:field_des%nz) + self%hocn_des(i+1,j,1:field_des%nz) )
296 call remapping_core_h(remapcs2, tmp_nz, h1(1:tmp_nz), tmp2(i,j,1:tmp_nz), &
297 field_des%nz, h2(1:field_des%nz), field_des%val(i,j,1:field_des%nz))
299 else if (field_des%name ==
"vocn")
then
300 if (field_des%mask(i,j)>0.)
then
301 h1(1:tmp_nz) = 0.5 * ( h_new2(i,j,1:tmp_nz) + h_new2(i,j+1,1:tmp_nz) )
302 h2(1:field_des%nz) = 0.5 * ( self%hocn_des(i,j,1:field_des%nz) + self%hocn_des(i,j+1,1:field_des%nz) )
303 call remapping_core_h(remapcs2, tmp_nz, h1(1:tmp_nz), tmp2(i,j,1:tmp_nz), &
304 field_des%nz, h2(1:field_des%nz), field_des%val(i,j,1:field_des%nz))
307 if (field_des%mask(i,j)>0.)
then
308 call remapping_core_h(remapcs2, tmp_nz, h_new2(i,j,1:tmp_nz), tmp2(i,j,1:tmp_nz), &
309 field_des%nz, self%hocn_des(i,j,1:field_des%nz), field_des%val(i,j,1:field_des%nz))
315 if (field_des%metadata%io_file==
"ocn") field_des%val(:,:,1) = tmp2(:,:,1)*field_des%mask(:,:)
316 if (field_des%metadata%io_file==
"sfc") field_des%val(:,:,1) = tmp2(:,:,1)
317 if (field_des%metadata%io_file==
"ice") field_des%val(:,:,1:field_des%nz) = tmp2(:,:,1:field_des%nz)
320 call mpp_update_domains(field_des%val, geom_des%Domain%mpp_domain)
322 end subroutine soca_convertstate_change_resol
329 subroutine soca_hinterp(self,field2,gdata,mask2,nz,missing,lon_in,lat_in,lon_out,lat_out)
331 real(kind=kind_real),
dimension(self%isd:self%ied,self%jsd:self%jed,1:nz),
intent(inout) :: field2
332 real(kind=kind_real),
dimension(:,:,:),
intent(in) :: gdata
333 real(kind=kind_real),
dimension(self%isd:self%ied,self%jsd:self%jed),
intent(in) :: mask2
334 integer,
intent(in) :: nz
335 real(kind=kind_real),
intent(in) :: missing
336 real(kind=kind_real),
dimension(:),
intent(in) :: lon_in, lat_in
337 real(kind=kind_real),
dimension(self%isd:self%ied,self%jsd:self%jed),
intent(in) :: lon_out, lat_out
340 integer :: i, j, k, isg, ieg, jsg, jeg, jeg1
341 integer :: isc2, iec2, jsc2, jec2, npoints
342 real(kind=kind_real) :: roundoff = 1.e-5
343 real(kind=kind_real) :: pi_180
344 type(horiz_interp_type) :: interp
345 type(ocean_grid_type) :: grid
346 real(kind_real),
dimension(:),
allocatable :: lath_inp
347 real(kind_real),
dimension(:,:),
allocatable :: lon_inp, lat_inp, tr_inp, mask_in_
348 real(kind_real),
dimension(self%isd:self%ied,self%jsd:self%jed) :: tr_out, fill, good, prev, mask_out_
349 real(kind=kind_real) :: max_lat,min_lat, pole, npole, varavg
350 real(kind=kind_real),
dimension(:),
allocatable :: last_row, lonh, lath
351 logical :: add_np, add_sp
353 pi_180=atan(1.0d0)/45.0d0
356 ieg =
size(gdata,1); jeg =
size(gdata,2)
359 isc2 = self%isc ; iec2 = self%iec ; jsc2 = self%jsc ; jec2 = self%jec
361 grid%isc = self%isc ; grid%iec = self%iec ; grid%jsc = self%jsc ; grid%jec = self%jec
362 grid%isd = self%isd ; grid%ied = self%ied ; grid%jsd = self%jsd ; grid%jed = self%jed
363 grid%Domain => self%Domain
366 max_lat = maxval(lat_in)
368 if (max_lat < 90.0)
then
371 allocate(lath(jsg:jeg1))
372 lath(jsg:jeg)=lat_in(:)
375 allocate(lath(jsg:jeg1))
378 min_lat = minval(lat_in)
380 if (min_lat > -90.0)
then
383 if (
allocated(lath_inp))
deallocate(lath_inp)
384 allocate(lath_inp(jeg1))
385 lath_inp(jsg+1:jeg1)=lath(:)
387 if (
allocated (lath))
deallocate(lath)
388 allocate(lath(jsg:jeg1))
392 allocate(lonh(isg:ieg))
395 allocate(lon_inp(isg:ieg,jsg:jeg1))
396 allocate(lat_inp(isg:ieg,jsg:jeg1))
397 call meshgrid(lonh,lath,lon_inp,lat_inp)
399 allocate(mask_in_(isg:ieg,jsg:jeg1))
400 allocate(tr_inp(isg:ieg,jsg:jeg1)) ;
allocate(last_row(isg:ieg))
403 if (is_root_pe())
then
405 last_row(:)=gdata(:,jeg,k); pole=0.d0; npole=0.d0
407 if (abs(gdata(i,jeg,k)-missing) > abs(roundoff))
then
408 pole = pole+last_row(i)
419 tr_inp(:,jsg) = gdata(:,jsg,k)
420 tr_inp(:,jsg+1:jeg1-1) = gdata(:,:,k)
421 tr_inp(:,jeg1) = pole
423 tr_inp(:,jsg:jeg) = gdata(:,:,k)
424 tr_inp(:,jeg1) = pole
429 tr_inp(:,jsg) = gdata(:,jsg,k)
430 tr_inp(:,jsg+1:jeg1) = gdata(:,:,k)
432 tr_inp(isg:ieg,jsg:jeg) = gdata(isg:ieg,jsg:jeg,k)
438 call mpp_broadcast(tr_inp, ieg*jeg1, root_pe())
442 do j=jsg,jeg1 ;
do i=isg,ieg
443 if (abs(tr_inp(i,j)-missing) <= abs(roundoff))
then
444 tr_inp(i,j) = missing
445 mask_in_(i,j) = 0.d0;
451 if (k==1)
call horiz_interp_new(interp, lon_inp(:,:)*pi_180, lat_inp(:,:)*pi_180, lon_out(isc2:iec2,jsc2:jec2)*pi_180, &
452 lat_out(isc2:iec2,jsc2:jec2)*pi_180, interp_method=
'bilinear', src_modulo=.true., mask_in=mask_in_)
454 call horiz_interp(interp, tr_inp, tr_out(isc2:iec2,jsc2:jec2), mask_in=mask_in_, missing_value=missing, missing_permit=3)
456 mask_out_ = 1.d0 ; fill = 0.d0 ; good = 0.d0
457 npoints = 0 ; varavg = 0.d0
460 if (abs(tr_out(i,j)-missing) < abs(roundoff)) mask_out_(i,j)=0.d0
461 if (mask_out_(i,j) < 1.0d0)
then
462 tr_out(i,j) = missing
465 npoints = npoints + 1
466 varavg = varavg + tr_out(i,j)
468 if (mask2(i,j) == 1.d0 .and. mask_out_(i,j) < 1.0d0) fill(i,j) = 1.d0
471 call pass_var(fill, self%Domain) ;
call pass_var(good, self%Domain)
472 call sum_across_pes(npoints) ;
call sum_across_pes(varavg)
473 if (npoints > 0)
then
474 varavg = varavg/real(npoints)
477 if (k==1) prev(:,:) = tr_out(:,:)
478 call fill_miss_2d(tr_out, good, fill, prev=prev, g=grid, smooth=.true.)
483 field2(:,:,k) = tr_out(:,:)*mask2(:,:)
484 prev(:,:) = field2(:,:,k)
488 end subroutine soca_hinterp
Handle fields for the model.
resolution change for fields
Holds all data and metadata related to a single field variable.