FV3 Bundle
gsw_deltasa_atlas.f90
Go to the documentation of this file.
1 !==========================================================================
2 elemental function gsw_deltasa_atlas (p, long, lat)
3 !==========================================================================
4 !
5 ! Calculates the Absolute Salinity Anomaly atlas value, deltaSA_atlas.
6 !
7 ! p : sea pressure [dbar]
8 ! long : longiture [deg E]
9 ! lat : latitude [deg N]
10 !
11 ! gsw_deltasa_atlas : Absolute Salinity Anomaly atlas value [g/kg]
12 !--------------------------------------------------------------------------
13 
15 
17 
19 
20 use gsw_mod_kinds
21 
22 implicit none
23 
24 real (r8), intent(in) :: p, long, lat
25 
26 real (r8) :: gsw_deltasa_atlas
27 
28 integer :: indx0, indy0, indz0, k, ndepth_max
29 
30 real (r8), dimension(4) :: dsar, dsar_old
31 real (r8) :: dlong, dlat
32 real (r8) :: p0_original, sa_upper, sa_lower
33 real (r8) :: r1, s1, t1, p_tmp, long360
34 
35 character (*), parameter :: func_name = "gsw_deltasa_atlas"
36 
37 long360 = long
38 if (long360.lt.0.0_r8) long360 = long360 + 360.0_r8
39 
40 indx0 = floor(1.0_r8 + (nx-1)*(long360-longs_ref(1)) / &
41  (longs_ref(nx)-longs_ref(1)))
42 
43 indy0 = floor(1.0_r8 + (ny-1)*(lat-lats_ref(1)) / (lats_ref(ny)-lats_ref(1)))
44 
45 if ((indx0.ge.1 .and. indx0.le.nx) .and. (indy0.ge.1 .and. indy0.le.ny)) then
46  if (indx0.eq.nx) indx0 = nx-1
47  if (indy0.eq.ny) indy0 = ny-1
48 else
49  ! This is to catch any out-of-range or nonsense lat/long input (including
50  ! NaN, +Inf, -Inf etc). Note: NaNs will not satisfy any "if" conditional
51  ! so will be trapped by the "else".
52  gsw_deltasa_atlas = gsw_error_code(2,func_name)
53  return
54 end if
55 
56 ! Look for the maximum valid "ndepth_ref" value around our point.
57 ! Note: invalid "ndepth_ref" values are NaNs (a hangover from the codes
58 ! Matlab origins), but we have replaced the NaNs with a value of "9e90",
59 ! hence we need an additional upper-limit check in the code below so they
60 ! will not be recognised as valid values.
61 ndepth_max = -1
62 do k = 1, 4
63  if ((ndepth_ref(indy0+delj(k),indx0+deli(k)).gt.0) .and. &
64  (ndepth_ref(indy0+delj(k),indx0+deli(k)).lt.99)) &
65  ndepth_max = max(ndepth_max,ndepth_ref(indy0+delj(k),indx0+deli(k)))
66 end do
67 
68 ! If we are a long way from the ocean then there will be no valid "ndepth_ref"
69 ! values near the point (ie. surrounded by NaNs) - so deltasa_atlas = 0.0
70 if (ndepth_max.eq.-1) then
71  gsw_deltasa_atlas = 0.0_r8
72  return
73 end if
74 
75 p0_original = p
76 p_tmp = p
77 if (p_tmp.gt.p_ref(ndepth_max)) p_tmp = p_ref(ndepth_max)
78 indz0 = gsw_util_indx(p_ref,p_tmp)
79 
80 dlong = longs_ref(indx0+1) - longs_ref(indx0)
81 dlat = lats_ref(indy0+1) - lats_ref(indy0)
82 
83 r1 = (long360-longs_ref(indx0)) / dlong
84 s1 = (lat-lats_ref(indy0)) / dlat
85 t1 = (p_tmp-p_ref(indz0)) / (p_ref(indz0+1)-p_ref(indz0))
86 
87 do k = 1, 4
88  dsar(k) = delta_sa_ref(indz0,indy0+delj(k),indx0+deli(k))
89 end do
90 
91 if ( longs_pan(1).le.long360 .and. long360.le.longs_pan(npan)-0.001_r8 .and. &
92  lats_pan(npan).le.lat .and. lat.le.lats_pan(1)) then
93  dsar_old = dsar
94  call gsw_add_barrier(dsar_old,long360,lat,longs_ref(indx0), &
95  lats_ref(indy0),dlong,dlat,dsar)
96 else if (abs(sum(dsar)).ge.1e10_r8) then
97  dsar_old = dsar
98  call gsw_add_mean(dsar_old,dsar)
99 end if
100 
101 sa_upper = (1.0_r8-s1)*(dsar(1) + r1*(dsar(2)-dsar(1))) + s1*(dsar(4) + &
102  r1*(dsar(3)-dsar(4)))
103 
104 do k = 1,4
105  dsar(k) = delta_sa_ref(indz0+1,indy0+delj(k),indx0+deli(k))
106 end do
107 
108 if ( longs_pan(1).le.long360 .and. long360.le.longs_pan(npan)-0.001_r8 .and. &
109  lats_pan(npan).le.lat .and. lat.le.lats_pan(1)) then
110  dsar_old = dsar
111  call gsw_add_barrier(dsar_old,long360,lat,longs_ref(indx0), &
112  lats_ref(indy0),dlong,dlat,dsar)
113 else if (abs(sum(dsar)).ge.1e10_r8) then
114  dsar_old = dsar
115  call gsw_add_mean(dsar_old,dsar)
116 end if
117 
118 sa_lower = (1.0_r8-s1)*(dsar(1) + r1*(dsar(2)-dsar(1))) + s1*(dsar(4) + &
119  r1*(dsar(3)-dsar(4)))
120 if (abs(sa_lower).ge.1e10_r8) sa_lower = sa_upper
121 gsw_deltasa_atlas = sa_upper + t1*(sa_lower-sa_upper)
122 
123 if (abs(gsw_deltasa_atlas).ge.1e10_r8) &
124  gsw_deltasa_atlas = gsw_error_code(3,func_name)
125 
126 return
127 end function
128 
129 !--------------------------------------------------------------------------
integer, parameter, public long
Definition: Type_Kinds.f90:76
elemental real(r8) function gsw_deltasa_atlas(p, long, lat)
real(r8), dimension(npan) longs_pan
integer, parameter nx
real(r8), dimension(npan) lats_pan
integer, parameter ny
real(r8), parameter, public gsw_error_limit
integer, dimension(4) delj
real(r8), dimension(nz) p_ref
real(r8), dimension(nx) longs_ref
integer, parameter npan
real(r8), dimension(nz, ny, nx) delta_sa_ref
integer, dimension(4) deli
#define max(a, b)
Definition: mosaic_util.h:33
integer, dimension(ny, nx) ndepth_ref
real(r8), dimension(ny) lats_ref
elemental real(r8) function, public gsw_error_code(err_num, func_name, error_code)