10 use fckit_configuration_module,
only: fckit_configuration
11 use fckit_log_module,
only: fckit_log
36 integer :: isc, iec, jsc, jec, npz
53 subroutine create(self, geom, bg, fg, dummyconf)
59 type(fckit_configuration),
intent(in) :: dummyconf
71 if (bg%has_field(
't' ))
call bg%get_field(
't' , self%t )
72 if (bg%has_field(
'sphum' ))
call bg%get_field(
'sphum' , self%q )
73 if (bg%has_field(
'o3mr' ))
call bg%get_field(
'o3mr' , self%o3)
74 if (bg%has_field(
'o3ppmv'))
call bg%get_field(
'o3ppmv', self%o3)
84 if (
allocated(self%t ))
deallocate(self%t )
85 if (
allocated(self%q ))
deallocate(self%q )
86 if (
allocated(self%o3))
deallocate(self%o3)
99 integer :: f, ji, jj, jk, nf2do
100 character(len=field_clen),
allocatable :: fields_to_do_(:)
101 character(len=field_clen),
allocatable :: fields_to_do(:)
102 real(kind=
kind_real),
pointer :: field_ptr(:,:,:)
105 logical :: have_winds
106 real(kind=
kind_real),
allocatable :: ua(:,:,:)
107 real(kind=
kind_real),
allocatable :: va(:,:,:)
108 real(kind=
kind_real),
pointer :: ud(:,:,:)
109 real(kind=
kind_real),
pointer :: vd(:,:,:)
113 real(kind=
kind_real),
pointer :: q(:,:,:)
114 real(kind=
kind_real),
pointer :: t(:,:,:)
115 real(kind=
kind_real),
allocatable :: tv(:,:,:)
119 real(kind=
kind_real),
allocatable :: qmr(:,:,:)
123 real(kind=
kind_real),
allocatable :: o3(:,:,:)
127 real(kind=
kind_real),
allocatable :: ps(:,:,:)
128 real(kind=
kind_real),
pointer :: delp(:,:,:)
133 call copy_subset(dxm%fields, dxg%fields, fields_to_do_)
139 if (
allocated(fields_to_do_)) nf2do =
size(fields_to_do_)
141 if (dxg%has_field(
'ua'))
then
142 allocate(fields_to_do(nf2do+2))
143 if (
allocated(fields_to_do_)) fields_to_do(1:nf2do) = fields_to_do_
144 fields_to_do(nf2do+1) =
'ua'
145 fields_to_do(nf2do+2) =
'va'
147 if (
allocated(fields_to_do_))
then
148 allocate(fields_to_do(nf2do))
149 fields_to_do(1:nf2do) = fields_to_do_
156 if (.not.
allocated(fields_to_do))
return
161 if (dxg%has_field(
'ud'))
call abor1_ftn(
"GeoVaLs state should not have D-Grid winds")
167 if (dxm%has_field(
'ud'))
then
168 call dxm%get_field(
'ud', ud)
169 call dxm%get_field(
'vd', vd)
170 allocate(ua(self%isc:self%iec,self%jsc:self%jec,self%npz))
171 allocate(va(self%isc:self%iec,self%jsc:self%jec,self%npz))
172 call d2a(geom, ud, vd, ua, va)
174 elseif (dxm%has_field(
'ua'))
then
175 call dxm%get_field(
'ua', ua)
176 call dxm%get_field(
'va', va)
184 if (
allocated(self%t) .and.
allocated(self%t) .and. &
185 dxm%has_field(
't') .and. dxm%has_field(
'sphum'))
then
186 call dxm%get_field(
't', t)
187 call dxm%get_field(
'sphum', q)
188 allocate(tv(self%isc:self%iec,self%jsc:self%jec,self%npz))
189 call t_to_tv_tl(geom, self%t, t, self%q, q, tv )
197 if (
allocated(self%q) .and. dxm%has_field(
'sphum'))
then
198 call dxm%get_field(
'sphum', q)
199 allocate(qmr(self%isc:self%iec,self%jsc:self%jec,self%npz))
208 if (
allocated(self%o3) .and. dxm%has_field(
'o3mr') )
then
209 call dxm%get_field(
'o3mr', o3)
212 do jj = self%jsc, self%jec
213 do ji = self%isc, self%iec
214 if (self%o3(ji,jj,jk) >= 0.0_kind_real)
then
215 o3(ji,jj,jk) = o3(ji,jj,jk) *
constoz
217 o3(ji,jj,jk) = 0.0_kind_real
223 if (
allocated(self%o3) .and. dxm%has_field(
'o3ppmv') )
then
224 call dxm%get_field(
'o3ppmv', o3)
227 do jj = self%jsc, self%jec
228 do ji = self%isc, self%iec
229 if (self%o3(ji,jj,jk) >= 0.0_kind_real)
then
232 o3(ji,jj,jk) = 0.0_kind_real
245 if (dxm%has_field(
'ps'))
then
246 call dxm%get_field(
'ps', ps)
248 elseif (dxm%has_field(
'delp'))
then
249 call dxm%get_field(
'delp', delp)
250 allocate(ps(self%isc:self%iec,self%jsc:self%jec,1))
251 ps(:,:,1) = sum(delp,3)
258 do f = 1,
size(fields_to_do)
260 call dxg%get_field(trim(fields_to_do(f)), field_ptr)
262 select case (trim(fields_to_do(f)))
266 if (.not. have_winds)
call field_fail(fields_to_do(f))
271 if (.not. have_winds)
call field_fail(fields_to_do(f))
276 if (.not. have_tv)
call field_fail(fields_to_do(f))
281 if (.not. have_ps)
call field_fail(fields_to_do(f))
284 case (
"humidity_mixing_ratio")
286 if (.not. have_qmr)
call field_fail(fields_to_do(f))
289 case (
"mole_fraction_of_ozone_in_air")
290 if (.not. have_o3)
call field_fail(fields_to_do(f))
294 case (
"mass_content_of_cloud_liquid_water_in_atmosphere_layer")
295 case (
"mass_content_of_cloud_ice_in_atmosphere_layer")
301 call abor1_ftn(
"fv3jedi_lvc_model2geovals_mod.multiply unknown field: "//trim(fields_to_do(f)) &
302 //
". Not in input field and no transform case specified.")
310 dxg%calendar_type = dxm%calendar_type
311 dxg%date_init = dxm%date_init
324 integer :: fg, fm, ji, jj, jk, dxg_index, num_not_copied
325 real(kind=
kind_real),
pointer :: field_ptr(:,:,:)
326 character(len=field_clen),
allocatable :: fields_to_do(:)
327 character(len=field_clen) :: not_copied_(10000)
328 logical,
allocatable :: field_passed(:)
329 integer :: noassim_index
332 logical :: have_awinds, have_dwinds
333 integer :: ua_index, va_index
334 real(kind=
kind_real),
pointer :: ua(:,:,:)
335 real(kind=
kind_real),
pointer :: va(:,:,:)
336 real(kind=
kind_real),
allocatable :: ud(:,:,:)
337 real(kind=
kind_real),
allocatable :: vd(:,:,:)
342 real(kind=
kind_real),
pointer :: tv(:,:,:)
343 real(kind=
kind_real),
allocatable :: q_tv(:,:,:)
344 real(kind=
kind_real),
allocatable :: t_tv(:,:,:)
345 real(kind=
kind_real),
pointer :: tptr(:,:,:)
350 real(kind=
kind_real),
pointer :: qmr(:,:,:)
351 real(kind=
kind_real),
allocatable :: q_qmr(:,:,:)
352 real(kind=
kind_real),
pointer :: qptr(:,:,:)
355 logical :: have_o3, have_o3_mass, have_o3_ppmv, have_mfo3
356 integer :: mfo3_index
357 real(kind=
kind_real),
pointer :: mfo3(:,:,:)
358 real(kind=
kind_real),
allocatable :: o3(:,:,:)
363 real(kind=
kind_real),
pointer :: ps(:,:,:)
364 real(kind=
kind_real),
allocatable :: delp(:,:,:)
379 allocate(field_passed(
size(dxg%fields)))
380 field_passed = .false.
384 do fm = 1,
size(dxm%fields)
386 if (.not.trim(dxm%fields(fm)%fv3jedi_name) ==
'ua' .and. &
387 .not.trim(dxm%fields(fm)%fv3jedi_name) ==
'va' .and. &
388 dxg%has_field( dxm%fields(fm)%fv3jedi_name, dxg_index))
then
389 call dxg%get_field(dxm%fields(fm)%fv3jedi_name, field_ptr)
390 dxm%fields(fm)%array = dxm%fields(fm)%array + field_ptr
391 field_passed(dxg_index) = .true.
393 num_not_copied = num_not_copied + 1
394 not_copied_(num_not_copied) = dxm%fields(fm)%fv3jedi_name
398 allocate(fields_to_do(num_not_copied))
399 fields_to_do(1:num_not_copied) = not_copied_(1:num_not_copied)
404 have_awinds = .false.
405 have_dwinds = .false.
406 if (dxg%has_field(
"ua", ua_index) .and. dxg%has_field(
"va", va_index))
then
407 call dxg%get_field(
'ua', ua)
408 call dxg%get_field(
'va', va)
409 if (dxm%has_field(
'ud'))
then
410 allocate(ud(self%isc:self%iec ,self%jsc:self%jec+1,self%npz))
411 allocate(vd(self%isc:self%iec+1,self%jsc:self%jec ,self%npz))
414 call d2a_ad(geom, ud, vd, ua, va)
416 elseif (dxm%has_field(
'ua'))
then
419 call abor1_ftn(
"fv3jedi_lvc_model2geovals_mod.multiplyadjoint: Winds found in GeoVaLs but"// &
420 " not in the model.")
428 if (
allocated(self%t) .and.
allocated(self%t) .and. dxg%has_field(
'tv', tv_index))
then
429 call dxg%get_field(
'tv', tv)
430 allocate(t_tv(self%isc:self%iec,self%jsc:self%jec,self%npz))
431 allocate(q_tv(self%isc:self%iec,self%jsc:self%jec,self%npz))
434 call t_to_tv_ad(geom, self%t, t_tv, self%q, q_tv, tv )
442 if (
allocated(self%q) .and. dxg%has_field(
'humidity_mixing_ratio', qmr_index))
then
443 call dxg%get_field(
'humidity_mixing_ratio', qmr)
444 allocate(q_qmr(self%isc:self%iec,self%jsc:self%jec,self%npz))
445 q_qmr = 0.0_kind_real
454 if (dxg%has_field(
"ps", ps_index))
then
455 call dxg%get_field(
'ps', ps)
456 allocate(delp(self%isc:self%iec,self%jsc:self%jec,self%npz))
459 delp(:,:,jk) = delp(:,:,jk) + ps(:,:,1)
471 have_o3_mass = .false.
472 have_o3_ppmv = .false.
474 have_o3_mass = dxm%has_field(
'o3mr')
475 have_o3_ppmv = dxm%has_field(
'o3ppmv')
476 have_mfo3 = dxg%has_field(
"mole_fraction_of_ozone_in_air", mfo3_index)
478 if (
allocated(self%o3) .and. have_mfo3 .and. (have_o3_mass .or. have_o3_ppmv) )
then
479 call dxg%get_field(
'mole_fraction_of_ozone_in_air', mfo3)
480 allocate(o3(self%isc:self%iec,self%jsc:self%jec,self%npz))
483 do jj = self%jsc, self%jec
484 do ji = self%isc, self%iec
485 if (self%o3(ji,jj,jk) >= 0.0_kind_real .and. have_o3_mass)
then
486 o3(ji,jj,jk) = o3(ji,jj,jk) *
constoz
487 else if (have_o3_ppmv .and. self%o3(ji,jj,jk) >= 0.0_kind_real )
then
490 o3(ji,jj,jk) = 0.0_kind_real
499 if (dxg%has_field(
"mass_content_of_cloud_liquid_water_in_atmosphere_layer", noassim_index)) &
500 field_passed(noassim_index) = .true.
501 if (dxg%has_field(
"mass_content_of_cloud_ice_in_atmosphere_layer", noassim_index)) &
502 field_passed(noassim_index) = .true.
503 if (dxg%has_field(
"p", noassim_index)) &
504 field_passed(noassim_index) = .true.
505 if (dxg%has_field(
"pe", noassim_index)) &
506 field_passed(noassim_index) = .true.
520 do fm = 1,
size(fields_to_do)
522 call dxm%get_field(trim(fields_to_do(fm)), field_ptr)
524 select case(trim(fields_to_do(fm)))
528 if (have_dwinds)
then
529 field_passed(ua_index) = .true.
530 field_ptr = field_ptr + ud
535 if (have_dwinds)
then
536 field_passed(va_index) = .true.
537 field_ptr = field_ptr + vd
542 if (have_awinds)
then
543 field_passed(ua_index) = .true.
544 field_ptr = field_ptr + ua
549 if (have_awinds)
then
550 field_passed(va_index) = .true.
551 field_ptr = field_ptr + va
557 field_passed(ps_index) = .true.
558 field_ptr = field_ptr + delp
564 field_passed(mfo3_index) = .true.
565 field_ptr = field_ptr + o3
570 field_passed(mfo3_index) = .true.
571 field_ptr = field_ptr + o3
589 do fg = 1,
size(dxg%fields)
591 if (.not. field_passed(fg))
then
593 select case(trim(dxg%fields(fg)%fv3jedi_name))
597 if (.not. have_tv)
call field_fail(trim(dxg%fields(fg)%fv3jedi_name))
598 field_passed(tv_index) = .true.
599 call dxm%get_field(
"t", tptr)
600 call dxm%get_field(
"sphum", qptr)
604 case (
"humidity_mixing_ratio")
606 if (.not. have_qmr)
call field_fail(trim(dxg%fields(fg)%fv3jedi_name))
607 field_passed(qmr_index) = .true.
608 call dxm%get_field(
"sphum", qptr)
613 call abor1_ftn(
"GeoVaLs field "//trim(dxg%fields(fg)%fv3jedi_name)//
" has no known link "// &
614 "to fields in model state")
624 do fg = 1,
size(dxg%fields)
625 if (.not. field_passed(fg))
then
626 call abor1_ftn(
"fv3jedi_lvc_model2geovals_mod.multiplyadjoint failed to send all geoval "// &
627 "fields to a model field")
634 dxm%calendar_type = dxg%calendar_type
635 dxm%date_init = dxg%date_init