UFO
vert_interp.F90
Go to the documentation of this file.
1 ! (C) Copyright 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 perform linear interpolation
7 
9 
10 use, intrinsic :: iso_c_binding
11 use kinds, only: kind_real
12 use missing_values_mod
13 
14 implicit none
15 public
16 
17 contains
18 
19 ! ------------------------------------------------------------------------------
20 
21 subroutine vert_interp_weights(nlev,obl,vec,wi,wf)
22 
23 implicit none
24 integer, intent(in ) :: nlev !Number of model levels
25 real(kind_real), intent(in ) :: obl !Observation location
26 real(kind_real), intent(in ) :: vec(nlev) !Structured vector of grid points
27 integer, intent(out) :: wi !Index for interpolation
28 real(kind_real), intent(out) :: wf !Weight for interpolation
29 
30 integer :: k
31 
32 if (vec(1) < vec(nlev)) then !Pressure increases with index
33 
34  if (obl < vec(1)) then
35  wi = 1
36  wf = 1.0
37  elseif (obl > vec(nlev)) then
38  wi = nlev - 1
39  wf = 0.0
40  else
41  do k = 1,nlev-1
42  if (obl >= vec(k) .and. obl <= vec(k+1)) then
43  wi = k
44  endif
45  enddo
46  wf = (vec(wi+1) - obl)/(vec(wi+1) - vec(wi))
47  endif
48 
49 else !Pressure decreases with index
50 
51  if (obl > vec(1)) then
52  wi = 1
53  wf = 1.0
54  elseif (obl < vec(nlev)) then
55  wi = nlev - 1
56  wf = 0.0
57  else
58  do k = 1,nlev-1
59  if (obl >= vec(k+1) .and. obl <= vec(k)) then
60  wi = k
61  endif
62  enddo
63  wf = (vec(wi+1) - obl)/(vec(wi+1) - vec(wi))
64  endif
65 
66 endif
67 
68 end subroutine vert_interp_weights
69 
70 ! ------------------------------------------------------------------------------
71 
72 subroutine vert_interp_apply(nlev, fvec, f, wi, wf)
73 
74 implicit none
75 integer, intent(in ) :: nlev !Number of model levels
76 real(kind_real), intent(in ) :: fvec(nlev) !Field at grid points
77 integer, intent(in ) :: wi !Index for interpolation
78 real(kind_real), intent(in ) :: wf !Weight for interpolation
79 real(kind_real), intent(out) :: f !Output at obs location using linear interp
80 
81 if (fvec(wi) == missing_value(f) .or. fvec(wi+1) == missing_value(f)) then
82  f = missing_value(f)
83 else
84  f = fvec(wi)*wf + fvec(wi+1)*(1.0-wf)
85 endif
86 
87 end subroutine vert_interp_apply
88 
89 ! ------------------------------------------------------------------------------
90 
91 subroutine vert_interp_apply_tl(nlev, fvec_tl, f_tl, wi, wf)
92 
93 implicit none
94 integer, intent(in) :: nlev
95 real(kind_real), intent(in) :: fvec_tl(nlev)
96 integer, intent(in) :: wi
97 real(kind_real), intent(in) :: wf
98 real(kind_real), intent(out) :: f_tl
99 
100 if (fvec_tl(wi) == missing_value(f_tl) .or. fvec_tl(wi+1) == missing_value(f_tl)) then
101  f_tl = missing_value(f_tl)
102 else
103  f_tl = fvec_tl(wi)*wf + fvec_tl(wi+1)*(1.0_kind_real-wf)
104 endif
105 
106 end subroutine vert_interp_apply_tl
107 
108 ! ------------------------------------------------------------------------------
109 
110 subroutine vert_interp_apply_ad(nlev, fvec_ad, f_ad, wi, wf)
111 
112 implicit none
113 integer, intent(in) :: nlev
114 real(kind_real), intent(inout) :: fvec_ad(nlev)
115 integer, intent(in) :: wi
116 real(kind_real), intent(in) :: wf
117 real(kind_real), intent(in) :: f_ad
118 real(kind_real) :: missing
119 
120 missing = missing_value(missing)
121 
122 if (fvec_ad(wi) == missing .or. f_ad == missing) then
123  fvec_ad(wi ) = 0.0_kind_real
124 else
125  fvec_ad(wi ) = fvec_ad(wi ) + f_ad*wf
126 endif
127 if (fvec_ad(wi+1) == missing .or. f_ad == missing) then
128  fvec_ad(wi+1) = 0.0_kind_real
129 else
130  fvec_ad(wi+1) = fvec_ad(wi+1) + f_ad*(1.0_kind_real-wf)
131 endif
132 
133 end subroutine vert_interp_apply_ad
134 
135 ! ------------------------------------------------------------------------------
136 
137 end module vert_interp_mod
Fortran module to perform linear interpolation.
Definition: vert_interp.F90:8
subroutine vert_interp_apply_ad(nlev, fvec_ad, f_ad, wi, wf)
subroutine vert_interp_weights(nlev, obl, vec, wi, wf)
Definition: vert_interp.F90:22
subroutine vert_interp_apply(nlev, fvec, f, wi, wf)
Definition: vert_interp.F90:73
subroutine vert_interp_apply_tl(nlev, fvec_tl, f_tl, wi, wf)
Definition: vert_interp.F90:92