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