FV3 Bundle
ufo_insitutemperature_mod.F90
Go to the documentation of this file.
1 ! (C) Copyright 2017-2018 UCAR
2 !
3 ! This software is licensed under the terms of the Apache Licence Version 2.0
4 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
5 
6 !> Fortran module to handle temperature profile observations
7 
9 
10  use iso_c_binding
11  use obsspace_mod
12  use ufo_vars_mod
13  use ioda_locs_mod
14  use ufo_geovals_mod
15  use kinds
16 
17  implicit none
18  public :: ufo_insitutemperature
20  private
21  integer, parameter :: max_string=800
22 
23  !> Fortran derived type for insitu temperature profile observation operator
25  end type ufo_insitutemperature
26 
27  ! ------------------------------------------------------------------------------
28 
29 contains
30 
31  ! ------------------------------------------------------------------------------
32 
33  subroutine ufo_insitutemperature_simobs(self, geovals, hofx, obss)
35  use vert_interp_mod
36  use ufo_tpsp2ti_mod
38 
39  implicit none
40  type(ufo_insitutemperature), intent(in) :: self !< Trajectory
41  type(ufo_geovals), intent(in) :: geovals !< Model's Tp, Sp, h interpolated at obs location
42  type(c_ptr), value, intent(in) :: obss !< Insitu temperature observations
43  real(c_double), intent(inout) :: hofx(:) !< Ti(Tp,Sp,h)
44 
45  character(len=*), parameter :: myname_="ufo_insitutemperature_simobs"
46  character(max_string) :: err_msg
47 
48  integer :: iobs, ilev, nlev, nobs
49  type(ufo_geoval), pointer :: temp, salt, h
50  real (kind_real), allocatable :: depth(:,:)
51  real(kind_real) :: lono, lato, deptho
52  real(kind_real), allocatable :: obs_lon(:)
53  real(kind_real), allocatable :: obs_lat(:)
54  real(kind_real), allocatable :: obs_depth(:)
55  real(kind_real), allocatable :: obs_val(:)
56  integer :: obss_nobs
57 
58  ! Vertical interpolation
59  real(kind_real) :: wf, tp, sp, prs
60  integer :: wi
61 
62  ! netcdf stuff
63  character(len=120) :: filename !< name of outpu file for omf, lon, lat, ...
64  type(diag_marine_obs) :: insitu_out
65 
66  ! check if nobs is consistent in geovals & hofx
67  if (geovals%nobs /= size(hofx,1)) then
68  write(err_msg,*) myname_, ' error: nobs inconsistent!'
69  call abor1_ftn(err_msg)
70  endif
71 
72  ! check if sea temperature profile variable is in geovals and get it
73  call ufo_geovals_get_var(geovals, var_ocn_pot_temp, temp)
74 
75  ! check if sea salinity profile variable is in geovals and get it
76  call ufo_geovals_get_var(geovals, var_ocn_salt, salt)
77 
78  ! check if ocean layer thickness variable is in geovals and get it
79  call ufo_geovals_get_var(geovals, var_ocn_lay_thick, h)
80 
81  ! Read in obs data
82  obss_nobs = obsspace_get_nobs(obss)
83  allocate(obs_lon(obss_nobs))
84  allocate(obs_lat(obss_nobs))
85  allocate(obs_depth(obss_nobs))
86  allocate(obs_val(obss_nobs))
87 
88  call obsspace_get_db(obss, "Metadata", "longitude", obs_lon)
89  call obsspace_get_db(obss, "Metadata", "latitude", obs_lat)
90  call obsspace_get_db(obss, "Metadata", "ocean_depth", obs_depth)
91  call obsspace_get_db(obss, "ObsValue", "insitu_temperature", obs_val)
92 
93  nlev = temp%nval
94  nobs = temp%nobs
95  allocate(depth(nlev,nobs))
96  do iobs = 1,size(hofx,1)
97  !< Depth from layer thickness
98  depth(1,iobs)=0.5*h%vals(1,iobs)
99  do ilev = 2, nlev
100  depth(ilev,iobs)=sum(h%vals(1:ilev-1,iobs))+0.5*h%vals(ilev,iobs)
101  end do
102  end do
103 
104  ! Information for temporary output file
105 
106  hofx = 0.0
107  ! insitu temperature profile obs operator
108  do iobs = 1,size(hofx,1)
109 
110  lono = obs_lon(iobs)
111  lato = obs_lat(iobs)
112  deptho = obs_depth(iobs)
113 
114  !< Interpolation weight
115  call vert_interp_weights(nlev, deptho, depth(:,iobs), wi, wf)
116  if (deptho.ge.maxval(depth)) then
117  wi=nlev-1
118  wf=0.0
119  end if
120 
121  ! Interpolate temp_p, salt_p to deptho
122  call vert_interp_apply(nlev, temp%vals(:,iobs), tp, wi, wf)
123  call vert_interp_apply(nlev, salt%vals(:,iobs), sp, wi, wf)
124 
125  ! Get insitu temp at model levels and obs location (lono, lato, zo)
126  call insitu_t_nl(hofx(iobs), tp, sp, lono, lato, deptho)
127 
128  enddo
129 
130  deallocate(depth)
131  deallocate(obs_lon)
132  deallocate(obs_lat)
133  deallocate(obs_depth)
134  deallocate(obs_val)
135 
136  end subroutine ufo_insitutemperature_simobs
137 
138 end module ufo_insitutemperature_mod
Fortran module to handle temperature profile observations.
Definition: ncutils.F90:8
subroutine, public ufo_geovals_get_var(self, varname, geoval, status)
subroutine vert_interp_apply(nlev, fvec, f, wi, wf)
Definition: vert_interp.F90:67
subroutine, public ufo_insitutemperature_simobs(self, geovals, hofx, obss)
integer, parameter max_string
integer function, public obsspace_get_nobs(c_dom)
Return the number of observations.
character(len=maxvarlen), public var_ocn_lay_thick
Fortran module to perform linear interpolation.
Definition: vert_interp.F90:8
character(len=maxvarlen), public var_ocn_salt
character(len=maxvarlen), public var_ocn_pot_temp
type to hold interpolated fields required by the obs operators
Fortran module to handle temperature profile observations.
subroutine, public insitu_t_nl(temp_i, temp_p, salt_p, lono, lato, deptho)
Fortran module handling observation locations.
Fortran interface to ObsSpace.
Definition: obsspace_mod.F90:9
subroutine vert_interp_weights(nlev, obl, vec, wi, wf)
Definition: vert_interp.F90:20
Fortran derived type for insitu temperature profile observation operator.
type to hold interpolated field for one variable, one observation