UFO
vert_interp_lay_mod.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 subroutine get_integral_limits(airpressure, botpressure, toppressure, modelpressure, nlevs, nlocs, nsig)
20 implicit none
21 integer,intent(in) :: nlevs, nlocs, nsig
22 real(kind_real) , dimension(nlocs),intent(in) :: airpressure
23 real(kind_real), dimension(nlocs),intent(inout) :: botpressure,toppressure
24 real(kind_real), dimension(nsig+1,nlocs),intent(in) :: modelpressure
25 ! local
26 integer :: nprofs, iobs, iprof, kk, k1, k2
27 if (nlevs == 1) then ! total column ozone
28  do iobs = 1, nlocs
29  toppressure(iobs) = modelpressure(nsig+1,iobs)
30  botpressure(iobs) = modelpressure(1,iobs)
31  enddo
32 else
33  !Obs pressures read in as Pa
34  nprofs = nlocs/nlevs
35  iobs = 0
36  do iprof = 1, nprofs
37  do kk = 1, nlevs
38  k1 = kk
39  k2 = kk - 1
40  if (k2 == 0) k2 = 1
41  if (kk == nlevs) then
42  k1 = nlevs - 1
43  k2 = 1
44  endif
45  iobs = iobs+1
46  toppressure(iobs) = airpressure(k2)
47  botpressure(iobs) = airpressure(k1)
48  if( kk == 1 ) then
49  toppressure(iobs) = modelpressure(nsig+1, iobs)
50  botpressure(iobs) = airpressure(k1)
51  if(botpressure(iobs) < modelpressure(nsig+1, iobs)) then
52  botpressure(iobs) = modelpressure(nsig+1, iobs)
53  endif
54  else if( kk == nlevs) then
55  toppressure(iobs) = modelpressure(nsig+1, iobs)
56  botpressure(iobs) = modelpressure(1, iobs)
57  endif
58  enddo
59  enddo
60 endif
61 
62 end subroutine get_integral_limits
63 
64 real function pindex(nx, press, obspressure)
65 ! This routine handles press (pressure) in decendent order (bottom2top)
66 ! press(1): highest pressure value
67 ! press(nx): lowerest pressure value
68 
69 implicit none
70 
71 integer :: ix, k, nx
72 real(kind_real) :: ozp, obspressure, psi
73 real(kind_real), dimension(nx) :: press
74 
75 psi = 1.0_kind_real/press(1)
76 if(obspressure*psi < 1.) then
77  ozp = obspressure
78 else
79  ozp = press(1)
80 endif
81 if( ozp >= press(1)) then
82  ix = 1
83 else
84  ix = 0
85  do k = 1, nx-1
86  if(ozp >= press(k)) then
87  ix = k
88  exit
89  endif
90  enddo
91  if(ix == 0) ix = nx
92  if(ix > 1)ix = ix -1
93 endif
94 ozp = float(ix) + &
95  (ozp-press(ix))/(press(ix+1)-press(ix))
96 pindex = ozp
97 return
98 end function pindex
99 
100 subroutine apply_layer_integral(coefficient, modelozone, modelpressure, botpressure, toppressure, nsig, layer_oz)
101 implicit none
102 integer,intent(in) :: nsig
103 real, intent(in) :: coefficient
104 real(kind_real),intent(in) :: botpressure, toppressure
105 real(kind_real), dimension(:), intent(in) :: modelpressure, modelozone
106 real(kind_real), intent(out) :: layer_oz
107 ! local
108 integer :: kk, iz1, iz2
109 real(kind_real) :: pob,delz,g,delp4,dz1
110 real(kind_real) :: topozp, botozp
111 topozp = pindex(nsig+1, modelpressure, toppressure)
112 botozp = pindex(nsig+1, modelpressure, botpressure)
113 pob = botozp
114 iz1 = topozp
115 if (iz1>nsig) iz1=nsig
116 iz2 = pob
117 layer_oz = 0._kind_real
118 dz1 = topozp
119 do kk=iz1,iz2,-1
120  delz = 1.0_kind_real
121  if(kk == iz1) delz = dz1 - iz1
122  if (kk == iz2) delz = delz - pob + iz2
123  delp4 = modelpressure(kk)-modelpressure(kk+1) ! [Pa]
124  layer_oz = layer_oz + modelozone(kk)*coefficient*(delz*delp4)
125 enddo
126 
127 end subroutine apply_layer_integral
128 
129 subroutine undo_layer_integral(coefficient, modelozone, modelpressure, botpressure, toppressure, nsig, layer_oz)
130 implicit none
131 integer,intent(in) :: nsig
132 real,intent(in) :: coefficient
133 real(kind_real),intent(in) :: botpressure, toppressure
134 real(kind_real), dimension(:),intent(in) :: modelpressure
135 real(kind_real), dimension(:),intent(out):: modelozone
136 real(kind_real), intent(in) :: layer_oz
137 ! local
138 integer :: kk, iz1, iz2
139 real(kind_real) :: pob,delz,g,delp4,dz1
140 real(kind_real) :: topozp, botozp
141 topozp = pindex(nsig+1, modelpressure, toppressure)
142 botozp = pindex(nsig+1, modelpressure, botpressure)
143 pob = botozp
144 iz1 = topozp
145 if (iz1>nsig) iz1=nsig
146 iz2 = pob
147 dz1 = topozp
148 modelozone = 0.0_kind_real
149 do kk=iz1,iz2,-1
150  delz = 1.0_kind_real
151  if(kk == iz1) delz = dz1 - iz1
152  if (kk == iz2) delz = delz - pob + iz2
153  delp4 = modelpressure(kk)-modelpressure(kk+1) ! [Pa]
154  modelozone(kk) = modelozone(kk) + layer_oz*coefficient*(delz*delp4)
155 enddo
156 
157 end subroutine undo_layer_integral
158 
159 
160 subroutine vert_interp_lay_apply_tl(modelozoned, layer_ozd, coefficient, modelpressure, botpressure, toppressure, nsig)
161 real(kind_real), intent(in) ::modelozoned(:)
162 real(kind_real),intent(in):: botpressure, toppressure
163 real(kind_real), intent(in), dimension(nsig+1) :: modelpressure
164 real(kind_real), intent(out) :: layer_ozd
165 integer,intent(in) :: nsig
166 real,intent(in) :: coefficient
167 call apply_layer_integral(coefficient, modelozoned, modelpressure, botpressure, toppressure, nsig, layer_ozd)
168 end subroutine vert_interp_lay_apply_tl
169 
170 subroutine vert_interp_lay_apply_ad(modelozoneb, layer_ozb, coefficient, modelpressure, botpressure, toppressure, nsig)
171 real(kind_real), intent(out) ::modelozoneb(:)
172 real(kind_real),intent(in):: botpressure, toppressure
173 real(kind_real), intent(in), dimension(nsig+1) :: modelpressure
174 real(kind_real), intent(in) :: layer_ozb
175 integer,intent(in) :: nsig
176 real,intent(in) :: coefficient
177 call undo_layer_integral(coefficient, modelozoneb, modelpressure, botpressure, toppressure, nsig, layer_ozb)
178 end subroutine vert_interp_lay_apply_ad
179 
180 
181 end module vert_interp_lay_mod
Fortran module to perform linear interpolation.
subroutine undo_layer_integral(coefficient, modelozone, modelpressure, botpressure, toppressure, nsig, layer_oz)
subroutine vert_interp_lay_apply_tl(modelozoned, layer_ozd, coefficient, modelpressure, botpressure, toppressure, nsig)
real function pindex(nx, press, obspressure)
subroutine apply_layer_integral(coefficient, modelozone, modelpressure, botpressure, toppressure, nsig, layer_oz)
subroutine get_integral_limits(airpressure, botpressure, toppressure, modelpressure, nlevs, nlocs, nsig)
subroutine vert_interp_lay_apply_ad(modelozoneb, layer_ozb, coefficient, modelpressure, botpressure, toppressure, nsig)