FV3 Bundle
gsw_rr68_interp_sa_ct.f90
Go to the documentation of this file.
1 !==========================================================================
2 pure subroutine gsw_rr68_interp_sa_ct (sa, ct, p, p_i, sa_i, ct_i)
3 !==========================================================================
4 !
5 ! Interpolate Absolute Salinity and Conservative Temperature values to
6 ! arbitrary pressures using the Reiniger and Ross (1968) interpolation
7 ! scheme.
8 ! Note that this interpolation scheme requires at least four observed
9 ! bottles on the cast.
10 !
11 ! SA = Absolute Salinity [ g/kg ]
12 ! CT = Conservative Temperature (ITS-90) [ deg C ]
13 ! p = sea pressure [ dbar ]
14 ! ( i.e. absolute pressure - 10.1325 dbar )
15 ! p_i = pressures to interpolate to.
16 !
17 ! SA_i = interpolated SA values at pressures p_i.
18 ! CT_i = interpolated CT values at pressures p_i.
19 !--------------------------------------------------------------------------
20 
22 
24 
25 use gsw_mod_kinds
26 
27 implicit none
28 
29 real (r8), intent(in) :: sa(:), ct(:), p(:), p_i(:)
30 real (r8), intent(out) :: sa_i(:), ct_i(:)
31 
32 integer :: i, j, mp, mp_i, nshallow, ncentral, ndeep
33 
34 integer, allocatable :: ip(:), ip_i(:)
35 integer, allocatable :: ip_ishallow(:), ip_icentral(:), ip_ideep(:)
36 logical, allocatable :: shallow(:), central(:), deep(:)
37 real (r8), allocatable :: ip_shallow(:), ip_central(:), ip_deep(:)
38 real (r8), allocatable :: dp(:)
39 
40 character (*), parameter :: func_name = "gsw_rr68_interp_sa_ct"
41 
42 mp = size(p)
43 if (mp .lt. 4) then ! need at least four bottles to perform this interpolation
44  sa_i = gsw_error_code(1,func_name)
45  ct_i = sa_i
46  return
47 end if
48 
49 allocate(dp(mp-1))
50 dp = p(2:mp) - p(1:mp-1)
51 if (any(dp .le. 0.0_r8)) then ! pressure must be monotonic
52  sa_i = gsw_error_code(2,func_name)
53  ct_i = sa_i
54  return
55 end if
56 
57 mp_i = size(p_i)
58 
59 allocate(shallow(mp_i),central(mp_i),deep(mp_i))
60 shallow = (p_i >= p(1) .and. p_i <= p(2) ); nshallow=count(shallow)
61 central = (p_i >= p(2) .and. p_i <= p(mp-1)); ncentral=count(central)
62 deep = (p_i >= p(mp-1) .and. p_i <= p(mp) ); ndeep=count(deep)
63 
64 if ((nshallow .eq. 0) .or. (ncentral .eq. 0) .or. (ndeep .eq. 0)) then
65  sa_i = gsw_error_code(3,func_name)
66  ct_i = sa_i
67  return
68 end if
69 
70 allocate(ip(mp),ip_i(mp_i))
71 ip = (/ (i, i=1,mp) /)
72 ip_i = (/ (i, i=1,mp_i) /)
73 
74 allocate(ip_shallow(nshallow),ip_central(ncentral),ip_deep(ndeep))
75 allocate(ip_ishallow(nshallow),ip_icentral(ncentral),ip_ideep(ndeep))
76 
77 ! Calculate the 2 outer extrapolated values and the inner interpolated values
78 
79 ip_icentral = pack(ip_i,central)
80 ip_central = gsw_util_interp1q_int(p,ip,p_i(ip_icentral))
81 call rr68_interp_section(0,ip_central,ip_icentral,sa_i,ct_i)
82 
83 ip_ishallow = pack(ip_i,shallow)
84 ip_shallow = gsw_util_interp1q_int(p,ip,p_i(ip_ishallow))
85 call rr68_interp_section(-1,ip_shallow,ip_ishallow,sa_i,ct_i)
86 
87 ip_ideep = pack(ip_i,deep)
88 ip_deep = gsw_util_interp1q_int(p,ip,p_i(ip_ideep))
89 call rr68_interp_section(+1,ip_deep,ip_ideep,sa_i,ct_i)
90 
91 ! Insert any observed bottles that are at the required interpolated pressures
92 do i = 1, mp_i
93  do j = 1, mp
94  if (p(j) .eq. p_i(i)) then
95  sa_i(i) = sa(j)
96  ct_i(i) = ct(j)
97  end if
98  end do
99 end do
100 
101 return
102 
103 contains
104 
105  pure subroutine rr68_interp_section (sectnum, ip_sect, ip_isect, sa_i, ct_i)
108 
109  implicit none
110 
111  integer, intent(in) :: sectnum, ip_isect(:)
112  real (r8), intent(in) :: ip_sect(:)
113  real (r8), intent(inout) :: sa_i(:), ct_i(:)
114 
115  integer nsect
116  real (r8) :: m
117 
118  integer, allocatable :: ip_1(:), ip_2(:), ip_3(:), ip_4(:)
119  real (r8), allocatable :: ct_12(:), ct_13(:), ct_23(:), ct_34(:), ctp1(:)
120  real (r8), allocatable :: ctp2(:), ct_ref(:), ctref_denom(:)
121  real (r8), allocatable :: ct_ref_minus_ctp1(:), ct_ref_minus_ctp2(:)
122  real (r8), allocatable :: ctref_num(:)
123  real (r8), allocatable :: gamma1_23(:), gamma1_24(:), gamma2_31(:)
124  real (r8), allocatable :: gamma2_34(:), gamma2_41(:), gamma3_12(:)
125  real (r8), allocatable :: gamma3_42(:), gamma4_12(:), gamma4_23(:)
126  real (r8), allocatable :: sa_12(:), sa_13(:), sa_23(:), sa_34(:), sap1(:)
127  real (r8), allocatable :: sap2(:), sa_ref(:), saref_denom(:)
128  real (r8), allocatable :: sa_ref_minus_sap1(:), sa_ref_minus_sap2(:)
129  real (r8), allocatable :: saref_num(:)
130 
131  nsect = size(ip_sect)
132  allocate(ip_1(nsect),ip_2(nsect),ip_3(nsect),ip_4(nsect))
133 
134  allocate(sa_12(nsect),sa_13(nsect),sa_23(nsect),sa_34(nsect))
135  allocate(sa_ref(nsect),saref_num(nsect),saref_denom(nsect))
136  allocate(sap1(nsect),sap2(nsect),sa_ref_minus_sap1(nsect))
137  allocate(sa_ref_minus_sap2(nsect))
138 
139  allocate(ct_12(nsect),ct_13(nsect),ct_23(nsect),ct_34(nsect))
140  allocate(ct_ref(nsect),ctref_num(nsect),ctref_denom(nsect))
141  allocate(ctp1(nsect),ctp2(nsect),ct_ref_minus_ctp1(nsect))
142  allocate(ct_ref_minus_ctp2(nsect))
143 
144  allocate(gamma1_23(nsect),gamma2_31(nsect),gamma3_12(nsect))
145  if (sectnum .eq. 0) then
146  allocate(gamma2_34(nsect),gamma3_42(nsect),gamma4_23(nsect))
147  else
148  allocate(gamma1_24(nsect),gamma2_41(nsect),gamma4_12(nsect))
149  end if
150 
151  if (sectnum .lt. 0) then ! shallow
152  ip_1 = floor(ip_sect)
153  ip_2 = ceiling(ip_sect)
154  where (ip_1 .eq. ip_2) ip_2 = ip_1 + 1
155  ip_3 = ip_2 + 1
156  ip_4 = ip_3 + 1
157  else if (sectnum .eq. 0) then ! central
158  ip_2 = floor(ip_sect)
159  ip_3 = ceiling(ip_sect)
160  where (ip_2 .eq. ip_3) ip_2 = ip_3 - 1
161  ip_1 = ip_2 - 1
162  where (ip_1 .lt. 1)
163  ip_1 = 1
164  ip_2 = 2
165  ip_3 = 3
166  end where
167  ip_4 = ip_3 + 1
168  else if (sectnum .gt. 0) then ! deep
169  ip_1 = ceiling(ip_sect)
170  ip_2 = floor(ip_sect)
171  where (ip_1 .eq. ip_2) ip_2 = ip_1 - 1
172  ip_3 = ip_2 - 1
173  ip_4 = ip_3 - 1
174  end if
175 
176  !eqn (3d)
177  sa_34 = sa(ip_3) + ((sa(ip_4) - sa(ip_3))*(p_i(ip_isect) - p(ip_3))/ &
178  (p(ip_4) - p(ip_3)))
179  ct_34 = ct(ip_3) + ((ct(ip_4) - ct(ip_3))*(p_i(ip_isect) - p(ip_3))/ &
180  (p(ip_4) - p(ip_3)))
181 
182  ! Construct the Reiniger & Ross reference curve equation.
183  ! m = the power variable
184  m = 1.7_r8
185 
186  if (sectnum .eq. 0) then
187 
188  sa_12 = sa(ip_1) + ((sa(ip_2) - sa(ip_1))*(p_i(ip_isect) - p(ip_1))/ &
189  (p(ip_2) - p(ip_1)))
190  ct_12 = ct(ip_1) + ((ct(ip_2) - ct(ip_1))*(p_i(ip_isect) - p(ip_1))/ &
191  (p(ip_2) - p(ip_1)))
192 
193  call gsw_linear_interp_sa_ct(sa,ct,p,p_i(ip_isect),sa_23,ct_23)
194 
195  ! eqn (3a)
196  saref_num = (abs(sa_23-sa_34)**m)*sa_12 + (abs(sa_12-sa_23)**m)*sa_34
197  ctref_num = (abs(ct_23-ct_34)**m)*ct_12 + (abs(ct_12-ct_23)**m)*ct_34
198 
199  saref_denom = abs(sa_23-sa_34)**m + abs(sa_12-sa_23)**m
200  ctref_denom = abs(ct_23-ct_34)**m + abs(ct_12-ct_23)**m
201 
202  where (saref_denom .eq. 0.0_r8)
203  sa_23 = sa_23 + 1.0e-6_r8
204  saref_num = (abs(sa_23-sa_34)**m)*sa_12+(abs(sa_12-sa_23)**m)*sa_34
205  saref_denom = abs(sa_23-sa_34)**m + abs(sa_12-sa_23)**m
206  end where
207  where (ctref_denom .eq. 0.0_r8)
208  ct_23 = ct_23 + 1.0e-6_r8
209  ctref_num = (abs(ct_23-ct_34)**m)*ct_12+(abs(ct_12-ct_23)**m)*ct_34
210  ctref_denom = abs(ct_23-ct_34)**m + abs(ct_12-ct_23)**m
211  end where
212 
213  sa_ref = 0.5_r8*(sa_23 + (saref_num/saref_denom))
214  ct_ref = 0.5_r8*(ct_23 + (ctref_num/ctref_denom))
215 
216  else
217 
218  call gsw_linear_interp_sa_ct(sa,ct,p,p_i(ip_isect),sa_12,ct_12)
219 
220  sa_13 = sa(ip_1) + ((sa(ip_3) - sa(ip_1))*(p_i(ip_isect) - p(ip_1))/&
221  (p(ip_3) - p(ip_1)))
222  ct_13 = ct(ip_1) + ((ct(ip_3) - ct(ip_1))*(p_i(ip_isect) - p(ip_1))/&
223  (p(ip_3) - p(ip_1)))
224 
225  sa_23 = sa(ip_2) + ((sa(ip_3) - sa(ip_2))*(p_i(ip_isect) - p(ip_2))/ &
226  (p(ip_3) - p(ip_2)))
227  ct_23 = ct(ip_2) + ((ct(ip_3) - ct(ip_2))*(p_i(ip_isect) - p(ip_2))/ &
228  (p(ip_3) - p(ip_2)))
229 
230  !eqn (3a')
231  saref_num = (abs(sa_12-sa_23)**m)*sa_34 + (abs(sa_12-sa_13)**m)*sa_23
232  ctref_num = (abs(ct_12-ct_23)**m)*ct_34 + (abs(ct_12-ct_13)**m)*ct_23
233 
234  saref_denom = abs(sa_12-sa_23)**m + abs(sa_12-sa_13)**m
235  ctref_denom = abs(ct_12-ct_23)**m + abs(ct_12-ct_13)**m
236 
237  where (saref_denom .eq. 0.0_r8)
238  sa_23 = sa_23 + 1.0e-6_r8
239  saref_num = (abs(sa_12-sa_23)**m)*sa_34+(abs(sa_12-sa_13)**m)*sa_23
240  saref_denom = abs(sa_12-sa_23)**m + abs(sa_12-sa_13)**m
241  end where
242  where (ctref_denom .eq. 0.0_r8)
243  ct_23 = ct_23 + 1.0e-6_r8
244  ctref_num = (abs(ct_12-ct_23)**m)*ct_34+(abs(ct_12-ct_13)**m)*ct_23
245  ctref_denom = abs(ct_12-ct_23)**m + abs(ct_12-ct_13)**m
246  end where
247 
248  sa_ref = 0.5_r8*(sa_12 + (saref_num/saref_denom))
249  ct_ref = 0.5_r8*(ct_12 + (ctref_num/ctref_denom))
250 
251  end if
252 
253  !eqn (3c)
254  gamma1_23 = ((p_i(ip_isect) - p(ip_2))*(p_i(ip_isect) - p(ip_3)))/ &
255  ((p(ip_1) - p(ip_2))*(p(ip_1) - p(ip_3)))
256  gamma2_31 = ((p_i(ip_isect) - p(ip_3))*(p_i(ip_isect) - p(ip_1)))/ &
257  ((p(ip_2) - p(ip_3))*(p(ip_2) - p(ip_1)))
258  gamma3_12 = ((p_i(ip_isect) - p(ip_1))*(p_i(ip_isect) - p(ip_2)))/ &
259  ((p(ip_3) - p(ip_1))*(p(ip_3) - p(ip_2)))
260 
261  if (sectnum .eq. 0) then
262  gamma2_34 = ((p_i(ip_isect) - p(ip_3))*(p_i(ip_isect) - p(ip_4)))/ &
263  ((p(ip_2) - p(ip_3))*(p(ip_2) - p(ip_4)))
264  gamma3_42 = ((p_i(ip_isect) - p(ip_4))*(p_i(ip_isect) - p(ip_2)))/ &
265  ((p(ip_3) - p(ip_4))*(p(ip_3) - p(ip_2)))
266  gamma4_23 = ((p_i(ip_isect) - p(ip_2))*(p_i(ip_isect) - p(ip_3)))/ &
267  ((p(ip_4) - p(ip_2))*(p(ip_4) - p(ip_3)))
268  else
269  gamma1_24 = ((p_i(ip_isect) - p(ip_2))*(p_i(ip_isect) - p(ip_4)))/ &
270  ((p(ip_1) - p(ip_2))*(p(ip_1) - p(ip_4)))
271  gamma2_41 = ((p_i(ip_isect) - p(ip_4))*(p_i(ip_isect) - p(ip_1)))/ &
272  ((p(ip_2) - p(ip_4))*(p(ip_2) - p(ip_1)))
273  gamma4_12 = ((p_i(ip_isect) - p(ip_1))*(p_i(ip_isect) - p(ip_2)))/ &
274  ((p(ip_4) - p(ip_1))*(p(ip_4) - p(ip_2)))
275  end if
276 
277  !eqn (3b/3b')
278  sap1 = gamma1_23*sa(ip_1) + gamma2_31*sa(ip_2) + gamma3_12*sa(ip_3)
279  ctp1 = gamma1_23*ct(ip_1) + gamma2_31*ct(ip_2) + gamma3_12*ct(ip_3)
280  if (sectnum .eq. 0) then
281  sap2 = gamma2_34*sa(ip_2) + gamma3_42*sa(ip_3) + gamma4_23*sa(ip_4)
282  ctp2 = gamma2_34*ct(ip_2) + gamma3_42*ct(ip_3) + gamma4_23*ct(ip_4)
283  else
284  sap2 = gamma1_24*sa(ip_1) + gamma2_41*sa(ip_2) + gamma4_12*sa(ip_4)
285  ctp2 = gamma1_24*ct(ip_1) + gamma2_41*ct(ip_2) + gamma4_12*ct(ip_4)
286  end if
287 
288  !eqn (3)
289  sa_ref_minus_sap1 = abs(sa_ref - sap1)
290  sa_ref_minus_sap2 = abs(sa_ref - sap2)
291  where (sa_ref_minus_sap1 .eq. 0.0_r8 .and. sa_ref_minus_sap2 .eq. 0.0_r8)
292  sa_ref = sa_ref + 1.0e-6_r8
293  sa_ref_minus_sap1 = abs(sa_ref - sap1)
294  sa_ref_minus_sap2 = abs(sa_ref - sap2)
295  end where
296 
297  ct_ref_minus_ctp1 = abs(ct_ref - ctp1)
298  ct_ref_minus_ctp2 = abs(ct_ref - ctp2)
299  where (ct_ref_minus_ctp1 .eq. 0.0_r8 .and. ct_ref_minus_ctp2 .eq. 0.0_r8)
300  ct_ref = ct_ref + 1.0e-6_r8
301  ct_ref_minus_ctp1 = abs(ct_ref - ctp1)
302  ct_ref_minus_ctp2 = abs(ct_ref - ctp2)
303  end where
304 
305  sa_i(ip_isect) = (sa_ref_minus_sap1*sap2 + sa_ref_minus_sap2*sap1) / &
306  (sa_ref_minus_sap1 + sa_ref_minus_sap2)
307  ct_i(ip_isect) = (ct_ref_minus_ctp1*ctp2 + ct_ref_minus_ctp2*ctp1) / &
308  (ct_ref_minus_ctp1 + ct_ref_minus_ctp2)
309  return
310  end subroutine rr68_interp_section
311 
312 end subroutine
313 
314 !--------------------------------------------------------------------------
integer, parameter, public ip
Definition: Type_Kinds.f90:97
pure subroutine gsw_rr68_interp_sa_ct(sa, ct, p, p_i, sa_i, ct_i)
elemental real(r8) function, public gsw_error_code(err_num, func_name, error_code)
pure subroutine rr68_interp_section(sectnum, ip_sect, ip_isect, sa_i, ct_i)